# This is a patch for xemacs-21.5.25 to update it to xemacs-21.5.26 # # To apply this patch: # STEP 1: Chdir to the source directory. # STEP 2: Run the 'applypatch' program with this patch file as input. # # If you do not have 'applypatch', it is part of the 'makepatch' package # that you can fetch from the Comprehensive Perl Archive Network: # http://www.perl.com/CPAN/authors/Johan_Vromans/makepatch-x.y.tar.gz # In the above URL, 'x' should be 2 or higher. # # To apply this patch without the use of 'applypatch': # STEP 1: Chdir to the source directory. # If you have a decent Bourne-type shell: # STEP 2: Run the shell with this file as input. # If you don't have such a shell, you may need to manually create/delete # the files as shown below. # STEP 3: Run the 'patch' program with this file as input. # # These are the commands needed to create/delete files/directories: # rm -f './README.ben-separate-stderr' rm -f './README.ben-mule-21-5' rm -f './CHANGES-msw' rm -f './CHANGES-ben-mule' touch './src/alsaplay.c' chmod 0644 './src/alsaplay.c' # # This command terminates the shell and need not be executed manually. exit # #### End of Preamble #### #### Patch data follows #### diff -c 'xemacs-21.5.25/CHANGES-beta' 'xemacs-21.5.26/CHANGES-beta' Index: ./CHANGES-beta *** ./CHANGES-beta Sun Feb 26 22:10:24 2006 --- ./CHANGES-beta Sat Apr 1 02:50:38 2006 *************** *** 1,3 **** --- 1,48 ---- + to 21.5.26 "endive" + + Major Features and Backward Incompatible Changes + + -- Improve: search for package roots on Windows. -- Vin Shelton + -- Improve: support asynchronous finalization, remove explicit finalizers, and support for statistics for explicitly finalized objects. -- Marcus Crestani, Adrian Aichner + -- New: support ALSA sound on Linux. -- Jerry James + + User-Visible Bug Fixes and Minor Improvements + + -- Fix: GC cursor display in mc-alloc. -- Marcus Crestani + -- Fix: next-error.el vs. compile.el name clashes. -- Malcolm Purvis + -- Fix: restore memory usage stats (fix regexp). -- Marcus Crestani + -- Fix: synch widget-move-and-invoke, used by Gnus. -- Jerry James + -- Fix: uncomment-region in C files. -- Jerry James + -- Fix: use set-text-properties, not remove-list-of-text-properties. -- Jerry James + -- Improve: convert decode-coding-region, encode-coding-region to interactive commands. -- Stephen Turnbull + -- Improve: synch regex failure limits with GNU Emacs, avoiding asserts. -- Malcolm Purvis + + Build Infrastructure + + -- Fix: eliminate configure idioms obsolete in Autoconf 2.59. -- Jerry James, Ilya Golubev + -- Improve: merge mc-alloc features into --with-newgc. -- Marcus Crestani + + Documentation + + -- Fix: document dependence of `run-lisp' on os-utils package. -- Mike Sperber + -- Improve: move historical READMEs, etc, to internals.texi. -- Stephen Turnbull + + Lisp API + + -- Improve: remove dead API (lisp-send-defun). -- Mike Sperber + + Internal API and Implementation + + -- Fix: add missing do to RETURN_UNGCPRO_EXIT_PROFILING. -- Jerry James + -- Fix: avoid malloc in vdb signal handler. -- Marcus Crestani + -- Fix: broken use of memset in vdb_install_signal_handler. -- Mike Fabian + -- Fix: eliminate bogus pointer to nowhere. -- Stephen Turnbull, Jerry James + -- Fix: malloc size in Dynarr_realloc. -- Marcus Crestani + -- Improve: add internal API to zero uninitialized string. -- Marcus Crestani + -- Improve: dynamic array cleanup, remove duplicate code. -- Marcus Crestani + -- Improve: handle memory shortage in mc-alloc properly. -- Marcus Crestani + -- Improve: mc-alloc APIs now return number of pages processed. -- Marcus Crestani + to 21.5.25 "eggplant" Major Features and Backward Incompatible Changes diff -c 'xemacs-21.5.25/ChangeLog' 'xemacs-21.5.26/ChangeLog' Index: ./ChangeLog *** ./ChangeLog Sun Feb 26 22:14:12 2006 --- ./ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,69 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + + 2006-03-31 Stephen J. Turnbull + + Miscellaneous doc cleanup, parts 2-4: move CHANGES-msw, + TODO.ben-mule-21-5, README.ben-mule-21-5, and + README.ben-separate-stderr to Internals Manual. + + * CHANGES-msw: Removed. + * TODO.ben-mule-21-5: Removed. + * README.ben-mule-21-5: Removed. + * README.ben-separate-stderr: Removed. + + 2006-03-29 Stephen J. Turnbull + + Miscellaneous doc cleanup, part 1: move CHANGES-ben-mule to + Internals Manual. + + * CHANGES-ben-mule: Removed. + + * ChangeLog: + * lib-src/ChangeLog: + * lisp/ChangeLog: + * lwlib/ChangeLog: + * man/ChangeLog: + * man/internals/internals.texi: + * modules/ChangeLog: + * netinstall/ChangeLog: + * nt/ChangeLog: + * nt/installer/Wise/ChangeLog: + * src/ChangeLog: + * tests/ChangeLog: + Update the Great Mule Merge placeholders to point to Internals + Manual node "The Great Mule Merge of March 2002". + N.B. Self-referencing log entries were *not* added to other logs. + + 2006-03-30 Jerry James + + * configure.ac: Fix for -Kalloca detection, also broken by the + recent autoconf updates. Thanks to Ilya Golubev. + + 2006-03-30 Jerry James + + * configure.ac: Fix FOR_MSW XPM test, broken by previous update. + + 2006-03-27 Jerry James + + * aclocal.m4: Updates for autoconf 2.59. + * configure.ac: Ditto. Also, don't bother checking for inttypes.h + and unistd.h explicitly, since AC_HEADER_STDC does that. + + 2006-03-27 Jerry James + + * configure.ac: Repair ALSA detection. + + 2006-03-24 Jerry James + + * configure.ac: Autodetect ALSA support and report it if detected. + + 2006-02-22 Marcus Crestani + + * configure.ac: Remove mc-alloc, replace it with newgc, adjust + output and comments. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 1536,1542 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: See CHANGES-ben-mule. 2002-03-05 Stephen J. Turnbull --- 1602,1609 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/MANIFEST' 'xemacs-21.5.26/MANIFEST' Index: ./MANIFEST *** ./MANIFEST Tue May 16 12:58:02 2006 --- ./MANIFEST Mon May 15 14:08:43 2006 *************** *** 1,9 **** ./aclocal.m4 ./build-msw-release.sh ./ChangeLog - ./CHANGES-ben-mule ./CHANGES-beta - ./CHANGES-msw ./config.guess ./config.sub ./configure --- 1,7 ---- *************** *** 1460,1473 **** ./nt/xpm.mak ./PROBLEMS ./README - ./README.ben-mule-21-5 - ./README.ben-separate-stderr ./src/.dbxrc.in ./src/.gdbinit.in ./src/abbrev.c ./src/alloc.c ./src/alloca.c ./src/alloca.s ./src/backtrace.h ./src/balloon-x.c ./src/balloon_help.c --- 1458,1470 ---- ./nt/xpm.mak ./PROBLEMS ./README ./src/.dbxrc.in ./src/.gdbinit.in ./src/abbrev.c ./src/alloc.c ./src/alloca.c ./src/alloca.s + ./src/alsaplay.c ./src/backtrace.h ./src/balloon-x.c ./src/balloon_help.c diff -c 'xemacs-21.5.25/aclocal.m4' 'xemacs-21.5.26/aclocal.m4' Index: ./aclocal.m4 *** ./aclocal.m4 Fri Mar 11 20:18:45 2005 --- ./aclocal.m4 Wed Mar 29 00:55:49 2006 *************** *** 42,48 **** xehost=$ac_cv_build xealias=$ac_cv_build_alias ! AC_CHECKING([how to build dynamic libraries for ${xehost}]) # Transform *-*-linux* to *-*-linux-gnu*, to support old configure scripts. case "$xehost" in *-*-linux-gnu*) ;; --- 42,49 ---- xehost=$ac_cv_build xealias=$ac_cv_build_alias ! AC_MSG_CHECKING([how to build dynamic libraries for ${xehost}]) ! AC_MSG_RESULT() # Transform *-*-linux* to *-*-linux-gnu*, to support old configure scripts. case "$xehost" in *-*-linux-gnu*) ;; *************** *** 184,190 **** AC_MSG_CHECKING([if PIC flag ${dll_cflags} really works]) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $dll_cflags -DPIC" ! AC_TRY_COMPILE(,[int x=0;],[ # On HP-UX, the stripped-down bundled CC doesn't accept +Z, but also # reports no error. So, we need to grep stderr for (Bundled). if grep '(Bundled)' config.log >/dev/null; then --- 185,191 ---- AC_MSG_CHECKING([if PIC flag ${dll_cflags} really works]) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $dll_cflags -DPIC" ! AC_COMPILE_IFELSE([AC_LANG_SOURCE([int x=0;])],[ # On HP-UX, the stripped-down bundled CC doesn't accept +Z, but also # reports no error. So, we need to grep stderr for (Bundled). if grep '(Bundled)' config.log >/dev/null; then *************** *** 300,311 **** LDFLAGS="$xcldf $LDFLAGS" LIBS= xe_libs= ! ac_link='${CC-cc} -o conftest $CFLAGS '"$xe_cppflags $xe_ldflags"' conftest.$ac_ext '"$xe_libs"' 1>&AC_FD_CC' ! AC_TRY_LINK(,[int x=0;],cc_produces_so=yes,cc_produces_so=no) LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS xe_libs=$save_xe_libs ! ac_link='${CC-cc} -o conftest $CFLAGS '"$xe_cppflags $xe_ldflags"' conftest.$ac_ext '"$xe_libs"' 1>&AC_FD_CC' else cc_produces_so=no fi --- 301,313 ---- LDFLAGS="$xcldf $LDFLAGS" LIBS= xe_libs= ! ac_link='${CC-cc} -o conftest $CFLAGS '"$xe_cppflags $xe_ldflags"' conftest.$ac_ext '"$xe_libs"' 1>&AS_MESSAGE_LOG_FD' ! AC_LINK_IFELSE([AC_LANG_SOURCE([int x=0;])], ! [cc_produces_so=yes],[cc_produces_so=no]) LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS xe_libs=$save_xe_libs ! ac_link='${CC-cc} -o conftest $CFLAGS '"$xe_cppflags $xe_ldflags"' conftest.$ac_ext '"$xe_libs"' 1>&AS_MESSAGE_LOG_FD' else cc_produces_so=no fi diff -c 'xemacs-21.5.25/configure' 'xemacs-21.5.26/configure' Index: ./configure *** ./configure Sun Feb 26 22:14:12 2006 --- ./configure Sat Apr 1 03:46:15 2006 *************** *** 1090,1102 **** ------------- --with-sound=TYPE Compile with sound support. Valid types are ! `native', `nas' and `esd'. Prefix a type with 'no' ! to disable. The first type can be `none' or `all'. ! `none' means `nonative,nonas,noesd'. `all' means ! `native,nas,esd'. Later options override earlier ! ones for the same TYPE. The default is to autodetect ! all sound support except for ESD which defaults to ! off. --with-native-sound-lib Path to sound library (for systems with name conflicts). --- 1090,1103 ---- ------------- --with-sound=TYPE Compile with sound support. Valid types are ! `native', `alsa', `nas' and `esd'. Prefix a type ! with 'no' to disable. The first type can be `none' ! or `all'. `none' means ! `nonative,noalsa,nonas,noesd'. `all' means ! `native,alsa,nas,esd'. Later options override ! earlier ones for the same TYPE. The default is to ! autodetect all sound support except for ESD which ! defaults to off. --with-native-sound-lib Path to sound library (for systems with name conflicts). *************** *** 1174,1183 **** --with-pdump Enable portable LISP preloader. --with-dump-in-exec Enable dumping into executable (enabled by default for `pdump', not enabled by default in combination ! with `mc-alloc'). ! --with-kkcc Enable experimental new GC algorithms. ! --with-mc-alloc Enable experimental new allocator. ! --with-newgc Enable new incremental garbage collector. --with-vdb=TYPE Override auto-detection of virtual-dirty-bit write-barrier implementation for the new garbage collector. TYPE must be one of "auto" (for --- 1175,1184 ---- --with-pdump Enable portable LISP preloader. --with-dump-in-exec Enable dumping into executable (enabled by default for `pdump', not enabled by default in combination ! with `newgc'). ! --with-kkcc Enable experimental new GC mark algorithms. ! --with-newgc Enable new incremental garbage collector and new ! allocator. --with-vdb=TYPE Override auto-detection of virtual-dirty-bit write-barrier implementation for the new garbage collector. TYPE must be one of "auto" (for *************** *** 2926,2935 **** _sound_notfirst="" _sound_native_default="" _sound_nas_default="" _sound_esd_default=no ! _sound_types="native nas esd" ! _sound_default="native,nas,noesd" # If --with-sound or --without-sound were given then copy the value to the # equivalent enable_sound variable. --- 2927,2937 ---- _sound_notfirst="" _sound_native_default="" + _sound_alsa_default="" _sound_nas_default="" _sound_esd_default=no ! _sound_types="native alsa nas esd" ! _sound_default="native,alsa,nas,noesd" # If --with-sound or --without-sound were given then copy the value to the # equivalent enable_sound variable. *************** *** 3575,3598 **** else enable_kkcc=yes fi; - # If --with-mc-alloc or --without-mc-alloc were given then copy the value to the - # equivalent enable_mc-alloc variable. - if test "${with_mc_alloc+set}" = set; then - enable_mc_alloc="$with_mc_alloc" - fi; - # If -enable-mc-alloc or --disable-mc-alloc were given then copy the value to the - # equivalent with_mc-alloc variable. - if test "${enable_mc_alloc+set}" = set; then - with_mc_alloc="$enable_mc_alloc" - fi; - # Check whether --with-mc-alloc or --without-mc-alloc was given. - if test "${with_mc_alloc+set}" = set; then - enableval="$with_mc_alloc" - withval="$with_mc_alloc" - else - enable_mc_alloc=yes - fi; # If --with-newgc or --without-newgc were given then copy the value to the # equivalent enable_newgc variable. if test "${with_newgc+set}" = set; then --- 3577,3583 ---- *************** *** 8996,9006 **** fi test -z "$enable_kkcc" && enable_kkcc=yes - test -z "$enable_mc_alloc" && enable_mc_alloc=yes if test -z "$enable_dump_in_exec"; then if test "$enable_pdump" = "yes"; then ! if test "$enable_mc_alloc" = "yes"; then enable_dump_in_exec=no else enable_dump_in_exec=yes --- 8981,8990 ---- fi test -z "$enable_kkcc" && enable_kkcc=yes if test -z "$enable_dump_in_exec"; then if test "$enable_pdump" = "yes"; then ! if test "$enable_newgc" = "yes"; then enable_dump_in_exec=no else enable_dump_in_exec=yes *************** *** 9009,9015 **** fi if test "$enable_newgc" = "yes"; then - enable_mc_alloc=yes enable_kkcc=yes fi --- 8993,8998 ---- *************** *** 9745,9752 **** fi if test "$add_runtime_path" = "yes"; then ! echo "$as_me:$LINENO: checking \"for runtime libraries flag\"" >&5 ! echo $ECHO_N "checking \"for runtime libraries flag\"... $ECHO_C" >&6 case "$opsys" in sol2 ) dash_r="-R" ;; decosf* | linux* | irix*) dash_r="-rpath " ;; --- 9728,9735 ---- fi if test "$add_runtime_path" = "yes"; then ! echo "$as_me:$LINENO: checking for runtime libraries flag" >&5 ! echo $ECHO_N "checking for runtime libraries flag... $ECHO_C" >&6 case "$opsys" in sol2 ) dash_r="-R" ;; decosf* | linux* | irix*) dash_r="-rpath " ;; *************** *** 9767,9788 **** shift done fi ! cat >conftest.$ac_ext <<_ACEOF ! /* confdefs.h. */ ! _ACEOF ! cat confdefs.h >>conftest.$ac_ext ! cat >>conftest.$ac_ext <<_ACEOF ! /* end confdefs.h. */ ! ! int ! main () ! { ! ! ; ! return 0; ! } ! _ACEOF ! rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? --- 9750,9756 ---- shift done fi ! rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? *************** *** 9811,9824 **** fi rm -f conftest.err conftest.$ac_objext \ ! conftest$ac_exeext conftest.$ac_ext xe_check_libs="" test -n "$dash_r" && break done ;; esac if test -n "$dash_r"; ! then echo "$as_me:$LINENO: result: "\"${dash_r}\""" >&5 ! echo "${ECHO_T}"\"${dash_r}\""" >&6 else echo "$as_me:$LINENO: result: NONE" >&5 echo "${ECHO_T}NONE" >&6 fi --- 9779,9792 ---- fi rm -f conftest.err conftest.$ac_objext \ ! conftest$ac_exeext xe_check_libs="" test -n "$dash_r" && break done ;; esac if test -n "$dash_r"; ! then echo "$as_me:$LINENO: result: \"${dash_r}\"" >&5 ! echo "${ECHO_T}\"${dash_r}\"" >&6 else echo "$as_me:$LINENO: result: NONE" >&5 echo "${ECHO_T}NONE" >&6 fi *************** *** 10541,10549 **** ! ! ! for ac_header in a.out.h elf.h cygwin/version.h fcntl.h inttypes.h libgen.h locale.h wchar.h mach/mach.h sys/param.h sys/pstat.h sys/resource.h sys/time.h sys/timeb.h sys/times.h sys/un.h sys/vlimit.h ulimit.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then --- 10509,10515 ---- ! for ac_header in a.out.h elf.h cygwin/version.h fcntl.h libgen.h locale.h wchar.h mach/mach.h sys/param.h sys/pstat.h sys/resource.h sys/time.h sys/timeb.h sys/times.h sys/un.h sys/vlimit.h ulimit.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then *************** *** 11682,11694 **** #include intptr_t x; - int - main () - { - - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 --- 11648,11653 ---- *************** *** 11740,11752 **** #include socklen_t x; - int - main () - { - - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 --- 11699,11704 ---- *************** *** 11787,11799 **** #include int accept (int, struct sockaddr *, size_t *); - int - main () - { - - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 --- 11739,11744 ---- *************** *** 15391,15398 **** done ! { echo "$as_me:$LINENO: checking type of mail spool file locking..." >&5 ! echo "$as_me: checking type of mail spool file locking..." >&6;} for ac_func in lockf flock --- 15336,15345 ---- done ! echo "$as_me:$LINENO: checking type of mail spool file locking" >&5 ! echo $ECHO_N "checking type of mail spool file locking... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 for ac_func in lockf flock *************** *** 15644,15651 **** fi ! { echo "$as_me:$LINENO: checking for specified window system..." >&5 ! echo "$as_me: checking for specified window system..." >&6;} GNOME_CONFIG=no --- 15591,15600 ---- fi ! echo "$as_me:$LINENO: checking for specified window system" >&5 ! echo $ECHO_N "checking for specified window system... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 GNOME_CONFIG=no *************** *** 18135,18142 **** _ACEOF ! { echo "$as_me:$LINENO: checking for X defines extracted by xmkmf..." >&5 ! echo "$as_me: checking for X defines extracted by xmkmf..." >&6;} rm -fr conftestdir if mkdir conftestdir; then cd conftestdir --- 18084,18093 ---- _ACEOF ! echo "$as_me:$LINENO: checking for X defines extracted by xmkmf" >&5 ! echo $ECHO_N "checking for X defines extracted by xmkmf... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 rm -fr conftestdir if mkdir conftestdir; then cd conftestdir *************** *** 19031,19043 **** extern Bool XRegisterIMInstantiateCallback( Display*, struct _XrmHashBucketRec*, char*, char*, XIMProc, XPointer*); - int - main () - { - - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 --- 18982,18987 ---- *************** *** 19236,19243 **** if test "$with_xft_emacs" = "yes"; then ! { echo "$as_me:$LINENO: checking for Xrender, fontconfig, and Xft..." >&5 ! echo "$as_me: checking for Xrender, fontconfig, and Xft..." >&6;} xft_includes_found=no for ac_header in freetype/config/ftheader.h --- 19180,19187 ---- if test "$with_xft_emacs" = "yes"; then ! echo "$as_me:$LINENO: checking for Xrender, fontconfig, and Xft" >&5 ! echo $ECHO_N "checking for Xrender, fontconfig, and Xft... $ECHO_C" >&6 xft_includes_found=no for ac_header in freetype/config/ftheader.h *************** *** 19391,19398 **** "/usr/include/freetype2" do if test -d $freetype_include_top; then ! { echo "$as_me:$LINENO: checking in ${freetype_include_top}/freetype2..." >&5 ! echo "$as_me: checking in ${freetype_include_top}/freetype2..." >&6;} unset "$as_ac_Header" save_c_switch_site="$c_switch_site" c_switch_site="$c_switch_site -I${freetype_include_top}" --- 19335,19342 ---- "/usr/include/freetype2" do if test -d $freetype_include_top; then ! echo "$as_me:$LINENO: checking in ${freetype_include_top}/freetype2" >&5 ! echo $ECHO_N "checking in ${freetype_include_top}/freetype2... $ECHO_C" >&6 unset "$as_ac_Header" save_c_switch_site="$c_switch_site" c_switch_site="$c_switch_site -I${freetype_include_top}" *************** *** 19777,19784 **** fi if test "$with_msw" != "no"; then ! { echo "$as_me:$LINENO: checking for MS-Windows..." >&5 ! echo "$as_me: checking for MS-Windows..." >&6;} echo "$as_me:$LINENO: checking for main in -lgdi32" >&5 echo $ECHO_N "checking for main in -lgdi32... $ECHO_C" >&6 if test "${ac_cv_lib_gdi32_main+set}" = set; then --- 19721,19730 ---- fi if test "$with_msw" != "no"; then ! echo "$as_me:$LINENO: checking for MS-Windows" >&5 ! echo $ECHO_N "checking for MS-Windows... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 echo "$as_me:$LINENO: checking for main in -lgdi32" >&5 echo $ECHO_N "checking for main in -lgdi32... $ECHO_C" >&6 if test "${ac_cv_lib_gdi32_main+set}" = set; then *************** *** 20033,20045 **** test "$opsys" = "hpux9-shr" && opsysfile="s/hpux9shxr4.h" esac ! { echo "$as_me:$LINENO: checking for WM_COMMAND option..." >&5 ! echo "$as_me: checking for WM_COMMAND option..." >&6;} if test "$with_wmcommand" != "no"; then cat >>confdefs.h <<\_ACEOF #define HAVE_WMCOMMAND 1 _ACEOF fi test -z "$with_xauth" && test "$window_system" = "none" && with_xauth=no --- 19979,19996 ---- test "$opsys" = "hpux9-shr" && opsysfile="s/hpux9shxr4.h" esac ! echo "$as_me:$LINENO: checking for WM_COMMAND option" >&5 ! echo $ECHO_N "checking for WM_COMMAND option... $ECHO_C" >&6 if test "$with_wmcommand" != "no"; then cat >>confdefs.h <<\_ACEOF #define HAVE_WMCOMMAND 1 _ACEOF + echo "$as_me:$LINENO: result: yes" >&5 + echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 + echo "${ECHO_T}no" >&6 fi test -z "$with_xauth" && test "$window_system" = "none" && with_xauth=no *************** *** 20282,20289 **** if test "$enable_modules" != "no"; then ! { echo "$as_me:$LINENO: checking for module support..." >&5 ! echo "$as_me: checking for module support..." >&6;} case "$opsys" in mingw* | cygwin* ) have_dl=yes ;; --- 20233,20242 ---- if test "$enable_modules" != "no"; then ! echo "$as_me:$LINENO: checking for module support" >&5 ! echo $ECHO_N "checking for module support... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 case "$opsys" in mingw* | cygwin* ) have_dl=yes ;; *************** *** 20445,20451 **** int main () { ! dlopen ("", 0); ; return 0; } --- 20398,20404 ---- int main () { ! dlopen ("", 0); ; return 0; } *************** *** 20495,20501 **** int main () { ! dlopen ("", 0); ; return 0; } --- 20448,20454 ---- int main () { ! dlopen ("", 0); ; return 0; } *************** *** 20544,20550 **** int main () { ! dlopen ("", 0); ; return 0; } --- 20497,20503 ---- int main () { ! dlopen ("", 0); ; return 0; } *************** *** 20748,20754 **** int main () { ! shl_load ("", 0, 0); ; return 0; } --- 20701,20707 ---- int main () { ! shl_load ("", 0, 0); ; return 0; } *************** *** 20798,20804 **** int main () { ! shl_load ("", 0, 0); ; return 0; } --- 20751,20757 ---- int main () { ! shl_load ("", 0, 0); ; return 0; } *************** *** 21000,21006 **** int main () { ! lt_dlinit (); ; return 0; } --- 20953,20959 ---- int main () { ! lt_dlinit (); ; return 0; } *************** *** 21063,21070 **** xehost=$ac_cv_build xealias=$ac_cv_build_alias ! { echo "$as_me:$LINENO: checking how to build dynamic libraries for ${xehost}..." >&5 ! echo "$as_me: checking how to build dynamic libraries for ${xehost}..." >&6;} # Transform *-*-linux* to *-*-linux-gnu*, to support old configure scripts. case "$xehost" in *-*-linux-gnu*) ;; --- 21016,21025 ---- xehost=$ac_cv_build xealias=$ac_cv_build_alias ! echo "$as_me:$LINENO: checking how to build dynamic libraries for ${xehost}" >&5 ! echo $ECHO_N "checking how to build dynamic libraries for ${xehost}... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 # Transform *-*-linux* to *-*-linux-gnu*, to support old configure scripts. case "$xehost" in *-*-linux-gnu*) ;; *************** *** 21232,21245 **** cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - - int - main () - { int x=0; - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 --- 21187,21193 ---- *************** *** 21360,21373 **** cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - - int - main () - { int x=0; - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 --- 21308,21314 ---- *************** *** 22401,22408 **** fi fi ! { echo "$as_me:$LINENO: checking for LDAP..." >&5 ! echo "$as_me: checking for LDAP..." >&6;} ldap_libs= test -z "$with_ldap" && { if test "${ac_cv_header_ldap_h+set}" = set; then echo "$as_me:$LINENO: checking for ldap.h" >&5 --- 22342,22351 ---- fi fi ! echo "$as_me:$LINENO: checking for LDAP" >&5 ! echo $ECHO_N "checking for LDAP... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 ldap_libs= test -z "$with_ldap" && { if test "${ac_cv_header_ldap_h+set}" = set; then echo "$as_me:$LINENO: checking for ldap.h" >&5 *************** *** 23166,23173 **** postgresql_libs= if test "$with_postgresql" != "no"; then ! { echo "$as_me:$LINENO: checking for PostgreSQL..." >&5 ! echo "$as_me: checking for PostgreSQL..." >&6;} for header_dir in "" "pgsql/" "postgresql/"; do as_ac_Header=`echo "ac_cv_header_${header_dir}libpq-fe.h" | $as_tr_sh` --- 23109,23118 ---- postgresql_libs= if test "$with_postgresql" != "no"; then ! echo "$as_me:$LINENO: checking for PostgreSQL" >&5 ! echo $ECHO_N "checking for PostgreSQL... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 for header_dir in "" "pgsql/" "postgresql/"; do as_ac_Header=`echo "ac_cv_header_${header_dir}libpq-fe.h" | $as_tr_sh` *************** *** 23563,23570 **** if test "$window_system" != "none"; then ! { echo "$as_me:$LINENO: checking for graphics libraries..." >&5 ! echo "$as_me: checking for graphics libraries..." >&6;} libpath_xpm= incpath_xpm= --- 23508,23517 ---- if test "$window_system" != "none"; then ! echo "$as_me:$LINENO: checking for graphics libraries" >&5 ! echo $ECHO_N "checking for graphics libraries... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 libpath_xpm= incpath_xpm= *************** *** 23677,23683 **** int main () { ! XpmCreatePixmapFromData() ; return 0; } --- 23624,23630 ---- int main () { ! XpmCreatePixmapFromData(); ; return 0; } *************** *** 25223,25232 **** fi - if test "$with_x11" = "yes"; then ! { echo "$as_me:$LINENO: checking for X11 graphics libraries..." >&5 ! echo "$as_me: checking for X11 graphics libraries..." >&6;} fi case "$enable_widgets" in --- 25170,25180 ---- fi if test "$with_x11" = "yes"; then ! echo "$as_me:$LINENO: checking for X11 graphics libraries" >&5 ! echo $ECHO_N "checking for X11 graphics libraries... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 fi case "$enable_widgets" in *************** *** 25239,25246 **** esac if test "$with_x11" = "yes" -a "$detect_athena" = "yes" ; then ! { echo "$as_me:$LINENO: checking for the Athena widgets..." >&5 ! echo "$as_me: checking for the Athena widgets..." >&6;} case "$with_athena" in "xaw" | "") athena_variant=Xaw athena_3d=no ;; --- 25187,25196 ---- esac if test "$with_x11" = "yes" -a "$detect_athena" = "yes" ; then ! echo "$as_me:$LINENO: checking for the Athena widgets" >&5 ! echo $ECHO_N "checking for the Athena widgets... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 case "$with_athena" in "xaw" | "") athena_variant=Xaw athena_3d=no ;; *************** *** 27244,27251 **** wnn_libs= if test "$enable_mule" = "yes" ; then ! { echo "$as_me:$LINENO: checking for Mule-related features..." >&5 ! echo "$as_me: checking for Mule-related features..." >&6;} cat >>confdefs.h <<\_ACEOF #define MULE 1 _ACEOF --- 27194,27201 ---- wnn_libs= if test "$enable_mule" = "yes" ; then ! echo "$as_me:$LINENO: checking for Mule-related features" >&5 ! echo $ECHO_N "checking for Mule-related features... $ECHO_C" >&6 cat >>confdefs.h <<\_ACEOF #define MULE 1 _ACEOF *************** *** 27476,27486 **** fi ! { echo "$as_me:$LINENO: checking for Mule input methods..." >&5 ! echo "$as_me: checking for Mule input methods..." >&6;} case "$with_xim" in "" | "yes" ) ! { echo "$as_me:$LINENO: checking for XIM..." >&5 ! echo "$as_me: checking for XIM..." >&6;} echo "$as_me:$LINENO: checking for XOpenIM in -lX11" >&5 echo $ECHO_N "checking for XOpenIM in -lX11... $ECHO_C" >&6 if test "${ac_cv_lib_X11_XOpenIM+set}" = set; then --- 27426,27436 ---- fi ! echo "$as_me:$LINENO: checking for Mule input methods" >&5 ! echo $ECHO_N "checking for Mule input methods... $ECHO_C" >&6 case "$with_xim" in "" | "yes" ) ! echo "$as_me:$LINENO: checking for XIM" >&5 ! echo $ECHO_N "checking for XIM... $ECHO_C" >&6 echo "$as_me:$LINENO: checking for XOpenIM in -lX11" >&5 echo $ECHO_N "checking for XOpenIM in -lX11... $ECHO_C" >&6 if test "${ac_cv_lib_X11_XOpenIM+set}" = set; then *************** *** 27721,27728 **** fi if test "$with_xfs" = "yes" ; then ! { echo "$as_me:$LINENO: checking for XFontSet..." >&5 ! echo "$as_me: checking for XFontSet..." >&6;} echo "$as_me:$LINENO: checking for XmbDrawString in -lX11" >&5 echo $ECHO_N "checking for XmbDrawString in -lX11... $ECHO_C" >&6 if test "${ac_cv_lib_X11_XmbDrawString+set}" = set; then --- 27671,27678 ---- fi if test "$with_xfs" = "yes" ; then ! echo "$as_me:$LINENO: checking for XFontSet" >&5 ! echo $ECHO_N "checking for XFontSet... $ECHO_C" >&6 echo "$as_me:$LINENO: checking for XmbDrawString in -lX11" >&5 echo $ECHO_N "checking for XmbDrawString in -lX11... $ECHO_C" >&6 if test "${ac_cv_lib_X11_XmbDrawString+set}" = set; then *************** *** 32389,32402 **** cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - - int - main () - { int i; __typeof__(i) j; - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 --- 32339,32345 ---- *************** *** 32431,32444 **** cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ - - int - main () - { int i; typeof(i) j; - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 --- 32374,32380 ---- *************** *** 34045,34052 **** #define HAVE_SOCKETS 1 _ACEOF ! echo "$as_me:$LINENO: checking \"for sun_len member in struct sockaddr_un\"" >&5 ! echo $ECHO_N "checking \"for sun_len member in struct sockaddr_un\"... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF --- 33981,33988 ---- #define HAVE_SOCKETS 1 _ACEOF ! echo "$as_me:$LINENO: checking for sun_len member in struct sockaddr_un" >&5 ! echo $ECHO_N "checking for sun_len member in struct sockaddr_un... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF *************** *** 34102,34109 **** fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ! echo "$as_me:$LINENO: checking \"for ip_mreq struct in netinet/in.h\"" >&5 ! echo $ECHO_N "checking \"for ip_mreq struct in netinet/in.h\"... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF --- 34038,34045 ---- fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ! echo "$as_me:$LINENO: checking for ip_mreq struct in netinet/in.h" >&5 ! echo $ECHO_N "checking for ip_mreq struct in netinet/in.h... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF *************** *** 34987,34995 **** - { echo "$as_me:$LINENO: checking for sound support..." >&5 - echo "$as_me: checking for sound support..." >&6;} test -n "$with_native_sound_lib" && enable_sound_native=yes if test "$enable_sound_native" != "no"; then --- 34923,34933 ---- + echo "$as_me:$LINENO: checking for sound support" >&5 + echo $ECHO_N "checking for sound support... $ECHO_C" >&6 + echo "$as_me:$LINENO: result: " >&5 + echo "${ECHO_T}" >&6 test -n "$with_native_sound_lib" && enable_sound_native=yes if test "$enable_sound_native" != "no"; then *************** *** 35600,35605 **** --- 35538,35771 ---- test -n "$with_native_sound_lib" && LIBS="$with_native_sound_lib $LIBS" && if test "$verbose" = "yes"; then echo " Prepending \"$with_native_sound_lib\" to \$LIBS"; fi fi + if test "$enable_sound_alsa" != "no"; then + if test "${ac_cv_header_alsa_input_h+set}" = set; then + echo "$as_me:$LINENO: checking for alsa/input.h" >&5 + echo $ECHO_N "checking for alsa/input.h... $ECHO_C" >&6 + if test "${ac_cv_header_alsa_input_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + fi + echo "$as_me:$LINENO: result: $ac_cv_header_alsa_input_h" >&5 + echo "${ECHO_T}$ac_cv_header_alsa_input_h" >&6 + else + # Is the header compilable? + echo "$as_me:$LINENO: checking alsa/input.h usability" >&5 + echo $ECHO_N "checking alsa/input.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 { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no + fi + rm -f 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 alsa/input.h presence" >&5 + echo $ECHO_N "checking alsa/input.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 { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi + else + ac_cpp_err=yes + fi + if test -z "$ac_cpp_err"; then + ac_header_preproc=yes + else + echo "$as_me: failed program was:" >&5 + 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: alsa/input.h: accepted by the compiler, rejected by the preprocessor!" >&5 + echo "$as_me: WARNING: alsa/input.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/input.h: proceeding with the compiler's result" >&5 + echo "$as_me: WARNING: alsa/input.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: alsa/input.h: present but cannot be compiled" >&5 + echo "$as_me: WARNING: alsa/input.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/input.h: check for missing prerequisite headers?" >&5 + echo "$as_me: WARNING: alsa/input.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/input.h: see the Autoconf documentation" >&5 + echo "$as_me: WARNING: alsa/input.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/input.h: section \"Present But Cannot Be Compiled\"" >&5 + echo "$as_me: WARNING: alsa/input.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/input.h: proceeding with the preprocessor's result" >&5 + echo "$as_me: WARNING: alsa/input.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: alsa/input.h: in the future, the compiler will take precedence" >&5 + echo "$as_me: WARNING: alsa/input.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX + ## ------------------------------------- ## + ## Report this to xemacs-beta@xemacs.org ## + ## ------------------------------------- ## + _ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + esac + echo "$as_me:$LINENO: checking for alsa/input.h" >&5 + echo $ECHO_N "checking for alsa/input.h... $ECHO_C" >&6 + if test "${ac_cv_header_alsa_input_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + ac_cv_header_alsa_input_h=$ac_header_preproc + fi + echo "$as_me:$LINENO: result: $ac_cv_header_alsa_input_h" >&5 + echo "${ECHO_T}$ac_cv_header_alsa_input_h" >&6 + + fi + if test $ac_cv_header_alsa_input_h = yes; then + + echo "$as_me:$LINENO: checking for snd_pcm_open in -lasound" >&5 + echo $ECHO_N "checking for snd_pcm_open in -lasound... $ECHO_C" >&6 + if test "${ac_cv_lib_asound_snd_pcm_open+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + ac_check_lib_save_LIBS=$LIBS + LIBS="-lasound $LIBS" + cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ + _ACEOF + cat confdefs.h >>conftest.$ac_ext + cat >>conftest.$ac_ext <<_ACEOF + /* end confdefs.h. */ + + /* Override any gcc2 internal prototype to avoid an error. */ + #ifdef __cplusplus + extern "C" + #endif + /* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ + char snd_pcm_open (); + int + main () + { + snd_pcm_open (); + ; + return 0; + } + _ACEOF + rm -f conftest.$ac_objext conftest$ac_exeext + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_asound_snd_pcm_open=yes + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_asound_snd_pcm_open=no + fi + rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_check_lib_save_LIBS + fi + echo "$as_me:$LINENO: result: $ac_cv_lib_asound_snd_pcm_open" >&5 + echo "${ECHO_T}$ac_cv_lib_asound_snd_pcm_open" >&6 + if test $ac_cv_lib_asound_snd_pcm_open = yes; then + have_alsa_sound=yes + fi + + fi + + + if test "$have_alsa_sound" = "yes"; then + enable_sound_alsa=yes + cat >>confdefs.h <<\_ACEOF + #define HAVE_ALSA_SOUND 1 + _ACEOF + + extra_objs="$extra_objs alsaplay.o" && if test "$verbose" = "yes"; then + echo " xemacs will be linked with \"alsaplay.o\"" + fi + LIBS="-lasound $LIBS" && if test "$verbose" = "yes"; then echo " Prepending \"-lasound\" to \$LIBS"; fi + else + test "$enable_sound_alsa" = "yes" && \ + { echo "Error:" "Required ALSA sound support cannot be provided." >&2; exit 1; } + enable_sound_alsa=no + fi + fi + if test "$enable_sound_nas" != "no"; then if test "${ac_cv_header_audio_audiolib_h+set}" = set; then echo "$as_me:$LINENO: checking for audio/audiolib.h" >&5 *************** *** 36012,36019 **** test -z "$with_tty" && with_tty=yes if test "$with_tty" = "yes" ; then ! { echo "$as_me:$LINENO: checking for TTY-related features..." >&5 ! echo "$as_me: checking for TTY-related features..." >&6;} cat >>confdefs.h <<\_ACEOF #define HAVE_TTY 1 _ACEOF --- 36178,36187 ---- test -z "$with_tty" && with_tty=yes if test "$with_tty" = "yes" ; then ! echo "$as_me:$LINENO: checking for TTY-related features" >&5 ! echo $ECHO_N "checking for TTY-related features... $ECHO_C" >&6 ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 cat >>confdefs.h <<\_ACEOF #define HAVE_TTY 1 _ACEOF *************** *** 37010,37017 **** fi test "$enable_database_gdbm $enable_database_dbm $enable_database_berkdb" \ ! != "no no no" && { echo "$as_me:$LINENO: checking for database support..." >&5 ! echo "$as_me: checking for database support..." >&6;} if test "$enable_database_gdbm $enable_database_dbm" != "no no"; then if test "${ac_cv_header_ndbm_h+set}" = set; then --- 37178,37187 ---- fi test "$enable_database_gdbm $enable_database_dbm $enable_database_berkdb" \ ! != "no no no" && echo "$as_me:$LINENO: checking for database support" >&5 ! echo $ECHO_N "checking for database support... $ECHO_C" >&6 && \ ! echo "$as_me:$LINENO: result: " >&5 ! echo "${ECHO_T}" >&6 if test "$enable_database_gdbm $enable_database_dbm" != "no no"; then if test "${ac_cv_header_ndbm_h+set}" = set; then *************** *** 37448,37460 **** #endif #include <$header> - int - main () - { - - ; - return 0; - } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 --- 37618,37623 ---- *************** *** 39163,39172 **** #define USE_KKCC 1 _ACEOF - test "$enable_mc_alloc" = "yes" && cat >>confdefs.h <<\_ACEOF - #define MC_ALLOC 1 - _ACEOF - test "$enable_newgc" = "yes" && cat >>confdefs.h <<\_ACEOF #define NEW_GC 1 _ACEOF --- 39326,39331 ---- *************** *** 39424,39429 **** --- 39583,39589 ---- echo " Sound:" test "$enable_sound_native" = yes && echo " Compiling in support for sound (native)." + test "$enable_sound_alsa" = yes && echo " Compiling in support for ALSA (Advanced Linux Sound Architecture)." test "$enable_sound_nas" = yes && echo " Compiling in support for NAS (network audio system)." test "$old_nas" = yes && echo " - NAS library lacks error trapping; will play synchronously." test "$enable_sound_esd" = yes && echo " Compiling in support for ESD (Enlightened Sound Daemon)." *************** *** 39481,39502 **** echo " WARNING: ---------------------------------------------------------" fi if test "$enable_kkcc" = yes ; then ! echo " Using the new GC algorithms." echo " WARNING: ---------------------------------------------------------" echo " WARNING: The new algorithms are experimental. They are enabled by" echo " WARNING: default for this release. Use \`--disable-kkcc' to" echo " WARNING: turn it off." echo " WARNING: ---------------------------------------------------------" fi ! if test "$enable_mc_alloc" = yes ; then ! echo " Using the new allocator." ! echo " WARNING: ---------------------------------------------------------" ! echo " WARNING: The new allocator is experimental. It is enabled by" ! echo " WARNING: default for this release. Use \`--disable-mc-alloc' to" ! echo " WARNING: turn it off." ! echo " WARNING: ---------------------------------------------------------" ! fi ! test "$enable_newgc" = yes && echo " Using the new incremental garbage collector." if test "$have_vdb_posix" = yes ; then if test "$have_vdb_sigaction" = yes ; then echo " Using POSIX sigaction() to install fault handler." --- 39641,39654 ---- echo " WARNING: ---------------------------------------------------------" fi if test "$enable_kkcc" = yes ; then ! echo " Using the new GC mark algorithms (KKCC)." echo " WARNING: ---------------------------------------------------------" echo " WARNING: The new algorithms are experimental. They are enabled by" echo " WARNING: default for this release. Use \`--disable-kkcc' to" echo " WARNING: turn it off." echo " WARNING: ---------------------------------------------------------" fi ! test "$enable_newgc" = yes && echo " Using the new incremental garbage collector and the new allocator." if test "$have_vdb_posix" = yes ; then if test "$have_vdb_sigaction" = yes ; then echo " Using POSIX sigaction() to install fault handler." diff -c 'xemacs-21.5.25/configure.ac' 'xemacs-21.5.26/configure.ac' Index: ./configure.ac *** ./configure.ac Tue Feb 21 00:58:24 2006 --- ./configure.ac Fri Mar 31 03:11:17 2006 *************** *** 497,503 **** dnl #### This doesn't read so well for alternative libraries like sound. dnl define([XE_COMPLEX_OPTION_HELP_STRING], ! [AC_HELP_STRING([$1],[Compile with support for $2. Components that can use $3 are $4. Prefix component with `no' to disable its use of $3. Requires $5 support. Default is $6.])])dnl dnl --- 497,503 ---- dnl #### This doesn't read so well for alternative libraries like sound. dnl define([XE_COMPLEX_OPTION_HELP_STRING], ! [AS_HELP_STRING([$1],[Compile with support for $2. Components that can use $3 are $4. Prefix component with `no' to disable its use of $3. Requires $5 support. Default is $6.])])dnl dnl *************** *** 528,534 **** with_dragndrop_default="no" dnl ------------------------------------------------------------------------- dnl Command line argument processing. ! dnl Note that AC_HELP_STRING compresses whitespace, wraps, and indents the dnl string to fit the --help display; there's no need to preformat. dnl dnl I think these will be caught by autoconf internal checks, --- 528,534 ---- with_dragndrop_default="no" dnl ------------------------------------------------------------------------- dnl Command line argument processing. ! dnl Note that AS_HELP_STRING compresses whitespace, wraps, and indents the dnl string to fit the --help display; there's no need to preformat. dnl dnl I think these will be caught by autoconf internal checks, *************** *** 549,671 **** dnl parse flags XE_HELP_SUBSECTION([Compilation options]) XE_MERGED_ARG([compiler], ! AC_HELP_STRING([--with-compiler],[C compiler to use]), [], []) XE_MERGED_ARG([xemacs-compiler], ! AC_HELP_STRING([--with-xemacs-compiler], [compiler to use to compile just the xemacs executable and C modules. If you want to compile XEmacs as C++, use e.g. `--with-xemacs-compiler=g++'. This turns on a lot of additional error-checking.]), [], []) XE_MERGED_ARG([gcc], ! AC_HELP_STRING([--with-gcc],[Use GCC to compile XEmacs.]), [], []) XE_MERGED_ARG([cflags], ! AC_HELP_STRING([--with-cflags=FLAGS], [Compiler flags. These flags will be placed after any flags inserted for warnings, debugging or optimization; setting this does not disable the insertion of those flags. Use configure settings such as `--with-optimization=no' or `enable-debug=no' to turn them off, or override them with `--with-cflags-optimization', `--with-cflags-debugging', or `with-cflags-warning'.]), [], []) XE_MERGED_ARG([cflags-warning], ! AC_HELP_STRING([--with-cflags-warning=FLAGS],[Override compiler flags used to control warnings. Normally, don't set this, as XEmacs already turns on the maximum safe warning level.]), [], []) XE_MERGED_ARG([optimization], ! AC_HELP_STRING([--with-optimization],[Control whether compilation is optimized. By default, optimization is on in release versions and off in beta versions, since it can interfere with proper stack backtraces.]), [], []) XE_MERGED_ARG([cflags-optimization], ! AC_HELP_STRING([--with-cflags-optimization=FLAGS], [Override compiler flags used to control optimization. If blank, forces no optimization; if non-blank, forces optimization. Normally, don't set this; XEmacs automatically sets the maximum safe optimization flags appropriate for the compiler being invoked. If you just want to turn optimization on or off, use `with-optimization' instead.]), [], []) XE_MERGED_ARG([cflags-debugging], ! AC_HELP_STRING([--with-cflags-debugging=FLAGS], [Override compiler flags used to add debugging information to the executable. Normally, debugging information is added whenever possible (i.e. unless optimization is turned on and the compiler does not permit debugging and optimization simultaneously).]), [], []) XE_MERGED_ARG([cpp], ! AC_HELP_STRING([--with-cpp],[C preprocessor to use (e.g. /usr/ccs/lib/cpp or cc -E)]), [CPP="$with_cpp"], []) XE_MERGED_ARG([cppflags], ! AC_HELP_STRING([--with-cppflags],[C preprocessor flags (e.g. -I/foo or -Dfoo=bar)]), [CPPFLAGS="$with_cppflags"], []) XE_MERGED_ARG([libs=LIBS], ! AC_HELP_STRING([--with-libs],[Additional libraries (e.g. -lfoo)]), [LIBS="$with_libs"], []) XE_MERGED_ARG([ldflags=FLAGS], ! AC_HELP_STRING([--with-ldflags],[Additional linker flags (e.g. -L/foo)]), [LDFLAGS="$with_ldflags"], []) XE_MERGED_ARG([site-includes], ! AC_HELP_STRING([--with-site-includes=PATHS],[Prepend to include search path.]), [], []) XE_MERGED_ARG([site-libraries], ! AC_HELP_STRING([--with-site-libraries=PATHS],[Prepend to library search path.]), [], []) XE_MERGED_ARG([site-prefixes], ! AC_HELP_STRING([--with-site-prefixes=PATHS],[Prepend to include and library search paths, with /include and /lib added. Comes after site-includes and site-libraries, if any.]), [], []) XE_MERGED_ARG([site-runtime-libraries], ! AC_HELP_STRING([--with-site-runtime-libraries=PATHS],[Prepend to the runtime library search path]), [], []) XE_MERGED_ARG([dynamic], ! AC_HELP_STRING([--with-dynamic],[Link dynamically if supported by system. 'No' forces static linking.]), [], []) dnl XE_HELP_SUBSECTION([Installation options]) XE_MERGED_ARG([prefix], ! AC_HELP_STRING([--with-prefix=no],[Don't compile the value for `prefix' into the executable.]), [true], [with_prefix=yes]) XE_MERGED_ARG([netinstall], ! AC_HELP_STRING([--with-netinstall],[Support for installation over the internet. Only functional on the MS Windows platforms.]), [], [with_netinstall="no"]) XE_MERGED_ARG([statedir], ! AC_HELP_STRING([--with-statedir=DIR],[]), [], [with_statedir='${prefix}/lib']) XE_MERGED_ARG([lispdir], ! AC_HELP_STRING([--with-lispdir=DIR],[]), [AC_DEFINE(LISPDIR_USER_DEFINED)], [with_lispdir='${datadir}/${instvardir}/lisp']) XE_MERGED_ARG([archlibdir], ! AC_HELP_STRING([--with-archlibdir=DIR],[]), [AC_DEFINE(ARCHLIBDIR_USER_DEFINED)], [with_archlibdir='${libdir}/${instvardir}/${configuration}']) XE_MERGED_ARG([moduledir], ! AC_HELP_STRING([--with-moduledir=DIR],[]), [AC_DEFINE(MODULEDIR_USER_DEFINED)], [with_moduledir='${libdir}/${instvardir}/${configuration}/modules']) XE_MERGED_ARG([etcdir], ! AC_HELP_STRING([--with-etcdir=DIR],[]), [AC_DEFINE(ETCDIR_USER_DEFINED)], [with_etcdir='${datadir}/${instvardir}/etc']) XE_MERGED_ARG([docdir], ! AC_HELP_STRING([--with-docdir=DIR],[]), [AC_DEFINE(DOCDIR_USER_DEFINED)], [with_docdir='${archlibdir}']) dnl XE_HELP_SUBSECTION([Run-time path-searching options]) XE_MERGED_ARG([site-lisp], ! AC_HELP_STRING([--with-site-lisp=no],[Allow for a site-lisp directory in the XEmacs hierarchy searched before the installation packages.]), [true], [with_site_lisp=no]) XE_MERGED_ARG([site-modules], ! AC_HELP_STRING([--with-site-modules=no],[Disable site-modules directory in the XEmacs hierarchy, which is searched before the installation modules.]), [], []) XE_MERGED_ARG([early-packages], ! AC_HELP_STRING([--with-early-packages=DIR],[Specify location of early/user packages (instead of ~/.xemacs; same as --with-user-packages).]), [AC_DEFINE(EARLY_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([user-packages], ! AC_HELP_STRING([--with-user-packages=DIR],[Specify location of early/user packages (instead of ~/.xemacs; same as --with-early-packages).]), [AC_DEFINE(EARLY_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([late-packages], ! AC_HELP_STRING([--with-late-packages=DIR],[Specify location of late/system packages (instead of default location; same as --with-system-packages).]), [AC_DEFINE(LATE_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([system-packages], ! AC_HELP_STRING([--with-late-packages=DIR],[Specify location of late/system packages (instead of default location; same as --with-late-packages).]), [AC_DEFINE(LATE_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([last-packages], ! AC_HELP_STRING([--with-last-packages=DIR],[Specify location of last/legacy packages (instead of default location; same as --with-legacy-packages).]), [AC_DEFINE(LAST_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([legacy-packages], ! AC_HELP_STRING([--with-late-packages=DIR],[Specify location of late/legacy packages (instead of default location; same as --with-late-packages).]), [AC_DEFINE(LATE_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([package-path], ! AC_HELP_STRING([--with-package-path=PATH],[Search path for package directories.]), [AC_DEFINE(PACKAGE_PATH_USER_DEFINED)], []) XE_MERGED_ARG([infopath], ! AC_HELP_STRING([--with-infopath=PATH],[Location of info directories]), [AC_DEFINE(INFOPATH_USER_DEFINED)], []) dnl XE_HELP_SUBSECTION([Window-system options]) --- 549,671 ---- dnl parse flags XE_HELP_SUBSECTION([Compilation options]) XE_MERGED_ARG([compiler], ! AS_HELP_STRING([--with-compiler],[C compiler to use]), [], []) XE_MERGED_ARG([xemacs-compiler], ! AS_HELP_STRING([--with-xemacs-compiler], [compiler to use to compile just the xemacs executable and C modules. If you want to compile XEmacs as C++, use e.g. `--with-xemacs-compiler=g++'. This turns on a lot of additional error-checking.]), [], []) XE_MERGED_ARG([gcc], ! AS_HELP_STRING([--with-gcc],[Use GCC to compile XEmacs.]), [], []) XE_MERGED_ARG([cflags], ! AS_HELP_STRING([--with-cflags=FLAGS], [Compiler flags. These flags will be placed after any flags inserted for warnings, debugging or optimization; setting this does not disable the insertion of those flags. Use configure settings such as `--with-optimization=no' or `enable-debug=no' to turn them off, or override them with `--with-cflags-optimization', `--with-cflags-debugging', or `with-cflags-warning'.]), [], []) XE_MERGED_ARG([cflags-warning], ! AS_HELP_STRING([--with-cflags-warning=FLAGS],[Override compiler flags used to control warnings. Normally, don't set this, as XEmacs already turns on the maximum safe warning level.]), [], []) XE_MERGED_ARG([optimization], ! AS_HELP_STRING([--with-optimization],[Control whether compilation is optimized. By default, optimization is on in release versions and off in beta versions, since it can interfere with proper stack backtraces.]), [], []) XE_MERGED_ARG([cflags-optimization], ! AS_HELP_STRING([--with-cflags-optimization=FLAGS], [Override compiler flags used to control optimization. If blank, forces no optimization; if non-blank, forces optimization. Normally, don't set this; XEmacs automatically sets the maximum safe optimization flags appropriate for the compiler being invoked. If you just want to turn optimization on or off, use `with-optimization' instead.]), [], []) XE_MERGED_ARG([cflags-debugging], ! AS_HELP_STRING([--with-cflags-debugging=FLAGS], [Override compiler flags used to add debugging information to the executable. Normally, debugging information is added whenever possible (i.e. unless optimization is turned on and the compiler does not permit debugging and optimization simultaneously).]), [], []) XE_MERGED_ARG([cpp], ! AS_HELP_STRING([--with-cpp],[C preprocessor to use (e.g. /usr/ccs/lib/cpp or cc -E)]), [CPP="$with_cpp"], []) XE_MERGED_ARG([cppflags], ! AS_HELP_STRING([--with-cppflags],[C preprocessor flags (e.g. -I/foo or -Dfoo=bar)]), [CPPFLAGS="$with_cppflags"], []) XE_MERGED_ARG([libs=LIBS], ! AS_HELP_STRING([--with-libs],[Additional libraries (e.g. -lfoo)]), [LIBS="$with_libs"], []) XE_MERGED_ARG([ldflags=FLAGS], ! AS_HELP_STRING([--with-ldflags],[Additional linker flags (e.g. -L/foo)]), [LDFLAGS="$with_ldflags"], []) XE_MERGED_ARG([site-includes], ! AS_HELP_STRING([--with-site-includes=PATHS],[Prepend to include search path.]), [], []) XE_MERGED_ARG([site-libraries], ! AS_HELP_STRING([--with-site-libraries=PATHS],[Prepend to library search path.]), [], []) XE_MERGED_ARG([site-prefixes], ! AS_HELP_STRING([--with-site-prefixes=PATHS],[Prepend to include and library search paths, with /include and /lib added. Comes after site-includes and site-libraries, if any.]), [], []) XE_MERGED_ARG([site-runtime-libraries], ! AS_HELP_STRING([--with-site-runtime-libraries=PATHS],[Prepend to the runtime library search path]), [], []) XE_MERGED_ARG([dynamic], ! AS_HELP_STRING([--with-dynamic],[Link dynamically if supported by system. 'No' forces static linking.]), [], []) dnl XE_HELP_SUBSECTION([Installation options]) XE_MERGED_ARG([prefix], ! AS_HELP_STRING([--with-prefix=no],[Don't compile the value for `prefix' into the executable.]), [true], [with_prefix=yes]) XE_MERGED_ARG([netinstall], ! AS_HELP_STRING([--with-netinstall],[Support for installation over the internet. Only functional on the MS Windows platforms.]), [], [with_netinstall="no"]) XE_MERGED_ARG([statedir], ! AS_HELP_STRING([--with-statedir=DIR],[]), [], [with_statedir='${prefix}/lib']) XE_MERGED_ARG([lispdir], ! AS_HELP_STRING([--with-lispdir=DIR],[]), [AC_DEFINE(LISPDIR_USER_DEFINED)], [with_lispdir='${datadir}/${instvardir}/lisp']) XE_MERGED_ARG([archlibdir], ! AS_HELP_STRING([--with-archlibdir=DIR],[]), [AC_DEFINE(ARCHLIBDIR_USER_DEFINED)], [with_archlibdir='${libdir}/${instvardir}/${configuration}']) XE_MERGED_ARG([moduledir], ! AS_HELP_STRING([--with-moduledir=DIR],[]), [AC_DEFINE(MODULEDIR_USER_DEFINED)], [with_moduledir='${libdir}/${instvardir}/${configuration}/modules']) XE_MERGED_ARG([etcdir], ! AS_HELP_STRING([--with-etcdir=DIR],[]), [AC_DEFINE(ETCDIR_USER_DEFINED)], [with_etcdir='${datadir}/${instvardir}/etc']) XE_MERGED_ARG([docdir], ! AS_HELP_STRING([--with-docdir=DIR],[]), [AC_DEFINE(DOCDIR_USER_DEFINED)], [with_docdir='${archlibdir}']) dnl XE_HELP_SUBSECTION([Run-time path-searching options]) XE_MERGED_ARG([site-lisp], ! AS_HELP_STRING([--with-site-lisp=no],[Allow for a site-lisp directory in the XEmacs hierarchy searched before the installation packages.]), [true], [with_site_lisp=no]) XE_MERGED_ARG([site-modules], ! AS_HELP_STRING([--with-site-modules=no],[Disable site-modules directory in the XEmacs hierarchy, which is searched before the installation modules.]), [], []) XE_MERGED_ARG([early-packages], ! AS_HELP_STRING([--with-early-packages=DIR],[Specify location of early/user packages (instead of ~/.xemacs; same as --with-user-packages).]), [AC_DEFINE(EARLY_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([user-packages], ! AS_HELP_STRING([--with-user-packages=DIR],[Specify location of early/user packages (instead of ~/.xemacs; same as --with-early-packages).]), [AC_DEFINE(EARLY_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([late-packages], ! AS_HELP_STRING([--with-late-packages=DIR],[Specify location of late/system packages (instead of default location; same as --with-system-packages).]), [AC_DEFINE(LATE_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([system-packages], ! AS_HELP_STRING([--with-late-packages=DIR],[Specify location of late/system packages (instead of default location; same as --with-late-packages).]), [AC_DEFINE(LATE_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([last-packages], ! AS_HELP_STRING([--with-last-packages=DIR],[Specify location of last/legacy packages (instead of default location; same as --with-legacy-packages).]), [AC_DEFINE(LAST_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([legacy-packages], ! AS_HELP_STRING([--with-late-packages=DIR],[Specify location of late/legacy packages (instead of default location; same as --with-late-packages).]), [AC_DEFINE(LATE_PACKAGE_DIRECTORIES_USER_DEFINED)], []) XE_MERGED_ARG([package-path], ! AS_HELP_STRING([--with-package-path=PATH],[Search path for package directories.]), [AC_DEFINE(PACKAGE_PATH_USER_DEFINED)], []) XE_MERGED_ARG([infopath], ! AS_HELP_STRING([--with-infopath=PATH],[Location of info directories]), [AC_DEFINE(INFOPATH_USER_DEFINED)], []) dnl XE_HELP_SUBSECTION([Window-system options]) *************** *** 683,739 **** XE_COMPLEX_OPTION([tabs],[no]), XE_COMPLEX_OPTION([gauges],[no])]) XE_MERGED_ARG([gtk], ! AC_HELP_STRING([--with-gtk],[Support GTK on the X Window System. (EXPERIMENTAL)]), [true], [with_gtk=no]) XE_MERGED_ARG([gnome], ! AC_HELP_STRING([--with-gnome],[Support GNOME on the X Window System. (EXPERIMENTAL)]), [true], [with_gnome=no]) XE_MERGED_ARG([msw], ! AC_HELP_STRING([--with-msw],[Support MS Windows as a window system (only under Cygwin and MinGW). `--with-msw=no' may be needed on *nix systems with Wine installed.]), [], []) XE_MERGED_ARG([toolbars], ! AC_HELP_STRING([--enable-toolbars],[Enable toolbar support. Default: yes.]), [], []) XE_MERGED_ARG([wmcommand], ! AC_HELP_STRING([--with-wmcommand],[Compile without realized leader window which will keep the WM_COMMAND property.]), [], []) XE_KEYWORD_ARG([athena], ! AC_HELP_STRING([--with-athena=TYPE],[Use TYPE Athena widgets (`xaw', `3d', `next', `95', or `xpm').]), [],[],[xaw,3d,next,95,xpm])dnl XE_KEYWORD_ARG([menubars], ! AC_HELP_STRING([--enable-menubars=TYPE],[Use TYPE menubars ('yes', '`no', `lucid', `motif', `athena', `gtk', or `msw'). The Lucid widgets emulate Motif (mostly) but are faster. *WARNING* The Motif menubar is currently broken. Lucid menubars are the default.]), [], [],[yes,no,lucid,motif,athena,gtk,msw]) XE_KEYWORD_ARG([scrollbars], ! AC_HELP_STRING([--enable-scrollbars=TYPE],[Use TYPE scrollbars 'yes', '`no', `lucid', `motif', `athena', `gtk', or `msw'). Lucid scrollbars are the default.]), [], [],[yes,no,lucid,motif,athena,gtk,msw]) XE_KEYWORD_ARG([dialogs], ! AC_HELP_STRING([--enable-dialogs=TYPE],[Use TYPE dialog boxes 'yes', '`no', `lucid', `motif', `athena', `gtk', or `msw'). There are no true Lucid dialogs; Motif dialogs will be used if Motif can be found, else Athena is used.]), [], [],[yes,no,lucid,motif,athena,gtk,msw]) XE_KEYWORD_ARG([widgets], ! AC_HELP_STRING([--enable-widgets=TYPE],[Use TYPE native widgets ('yes', '`no', `lucid', `motif', `athena', `gtk', or `msw'). Other widget types are currently unsupported. There are no true Lucid widgets; Motif widgets will be used if Motif can be found, else Athena is used.]), [], [],[yes,no,lucid,motif,athena,gtk,msw]) XE_MERGED_ARG([dragndrop], ! AC_HELP_STRING([--with-dragndrop],[Compile in the generic drag and drop API. This is automatically added if one of the drag and drop protocols is found (currently CDE, OffiX, MSWindows, and GTK). *WARNING* The Drag'n'drop support is under development and is considered experimental.]), [], []) XE_MERGED_ARG([cde], ! AC_HELP_STRING([--with-cde],[Compile in support for CDE drag and drop.]), [], []) XE_MERGED_ARG([offix], ! AC_HELP_STRING([--with-offix],[Compile in support for OffiX drag and drop. *WARNING* If you compile in OffiX, you may not be able to use multiple X displays success- fully. If the two servers are from --- 683,739 ---- XE_COMPLEX_OPTION([tabs],[no]), XE_COMPLEX_OPTION([gauges],[no])]) XE_MERGED_ARG([gtk], ! AS_HELP_STRING([--with-gtk],[Support GTK on the X Window System. (EXPERIMENTAL)]), [true], [with_gtk=no]) XE_MERGED_ARG([gnome], ! AS_HELP_STRING([--with-gnome],[Support GNOME on the X Window System. (EXPERIMENTAL)]), [true], [with_gnome=no]) XE_MERGED_ARG([msw], ! AS_HELP_STRING([--with-msw],[Support MS Windows as a window system (only under Cygwin and MinGW). `--with-msw=no' may be needed on *nix systems with Wine installed.]), [], []) XE_MERGED_ARG([toolbars], ! AS_HELP_STRING([--enable-toolbars],[Enable toolbar support. Default: yes.]), [], []) XE_MERGED_ARG([wmcommand], ! AS_HELP_STRING([--with-wmcommand],[Compile without realized leader window which will keep the WM_COMMAND property.]), [], []) XE_KEYWORD_ARG([athena], ! AS_HELP_STRING([--with-athena=TYPE],[Use TYPE Athena widgets (`xaw', `3d', `next', `95', or `xpm').]), [],[],[xaw,3d,next,95,xpm])dnl XE_KEYWORD_ARG([menubars], ! AS_HELP_STRING([--enable-menubars=TYPE],[Use TYPE menubars ('yes', '`no', `lucid', `motif', `athena', `gtk', or `msw'). The Lucid widgets emulate Motif (mostly) but are faster. *WARNING* The Motif menubar is currently broken. Lucid menubars are the default.]), [], [],[yes,no,lucid,motif,athena,gtk,msw]) XE_KEYWORD_ARG([scrollbars], ! AS_HELP_STRING([--enable-scrollbars=TYPE],[Use TYPE scrollbars 'yes', '`no', `lucid', `motif', `athena', `gtk', or `msw'). Lucid scrollbars are the default.]), [], [],[yes,no,lucid,motif,athena,gtk,msw]) XE_KEYWORD_ARG([dialogs], ! AS_HELP_STRING([--enable-dialogs=TYPE],[Use TYPE dialog boxes 'yes', '`no', `lucid', `motif', `athena', `gtk', or `msw'). There are no true Lucid dialogs; Motif dialogs will be used if Motif can be found, else Athena is used.]), [], [],[yes,no,lucid,motif,athena,gtk,msw]) XE_KEYWORD_ARG([widgets], ! AS_HELP_STRING([--enable-widgets=TYPE],[Use TYPE native widgets ('yes', '`no', `lucid', `motif', `athena', `gtk', or `msw'). Other widget types are currently unsupported. There are no true Lucid widgets; Motif widgets will be used if Motif can be found, else Athena is used.]), [], [],[yes,no,lucid,motif,athena,gtk,msw]) XE_MERGED_ARG([dragndrop], ! AS_HELP_STRING([--with-dragndrop],[Compile in the generic drag and drop API. This is automatically added if one of the drag and drop protocols is found (currently CDE, OffiX, MSWindows, and GTK). *WARNING* The Drag'n'drop support is under development and is considered experimental.]), [], []) XE_MERGED_ARG([cde], ! AS_HELP_STRING([--with-cde],[Compile in support for CDE drag and drop.]), [], []) XE_MERGED_ARG([offix], ! AS_HELP_STRING([--with-offix],[Compile in support for OffiX drag and drop. *WARNING* If you compile in OffiX, you may not be able to use multiple X displays success- fully. If the two servers are from *************** *** 741,856 **** unpredictable.]), [], []) XE_MERGED_ARG([xmu], ! AC_HELP_STRING([--with-xmu],[Use Xmu utilities. Default: yes.]), [], []) XE_MERGED_ARG([external-widget], ! AC_HELP_STRING([--enable-external-widget],[Support XEmacs server for text widgets in other applications.]), [], []) dnl XE_HELP_SUBSECTION([TTY (character terminal) options]) XE_MERGED_ARG([tty], ! AC_HELP_STRING([--with-tty],[Enable TTY support. Default: yes.]), [], []) XE_MERGED_ARG([ncurses], ! AC_HELP_STRING([--with-ncurses],[Use the ncurses library for tty support.]), [], []) XE_MERGED_ARG([gpm], ! AC_HELP_STRING([--with-gpm],[Compile in GPM mouse support for ttys.]), [], []) dnl XE_HELP_SUBSECTION([Image options]) XE_MERGED_ARG([xpm], ! AC_HELP_STRING([--with-xpm],[Compile with support for XPM images. PRACTICALLY REQUIRED. Although this library is nonstandard and a real hassle to build, many basic things (e.g. toolbars) depend on it, and you will run into many problems without it.]), [], []) XE_MERGED_ARG([png], ! AC_HELP_STRING([--with-png],[Compile with support for PNG images. Recommended because the images on the About page are not viewable without it.]), [], []) XE_MERGED_ARG([jpeg], ! AC_HELP_STRING([--with-jpeg],[Compile with support for JPEG images. Useful if you are using a mail, news reader, or web browser in XEmacs, so that JPEG images can be displayed.]), [], []) XE_MERGED_ARG([tiff], ! AC_HELP_STRING([--with-tiff],[Compile with support for TIFF images. Possibly useful, for the same reason as JPEG images.]), [], []) XE_MERGED_ARG([xface], ! AC_HELP_STRING([--with-xface],[Compile with support for X-Face mail headers. Requires the compface package.]), [], []) XE_MERGED_ARG([gif], ! AC_HELP_STRING([--with-gif],[Compile without the (builtin) support for GIF images.]), [], []) dnl XE_HELP_SUBSECTION([Sound options]) XE_COMPLEX_ARG([sound], ! AC_HELP_STRING([--enable-sound=TYPE],[Compile with sound support. ! Valid types are `native', `nas' and `esd'. Prefix a type with 'no' to disable. The first type can be `none' or `all'. `none' means ! `nonative,nonas,noesd'. `all' means `native,nas,esd'. ! Later options override earlier ones for the same TYPE. ! The default is to autodetect all sound support except ! for ESD which defaults to off.]), [], [enable_sound_nas=""], [XE_COMPLEX_OPTION([native],[""]), XE_COMPLEX_OPTION([nas],[""]), XE_COMPLEX_OPTION([esd],[no])]) XE_MERGED_ARG([native-sound-lib], ! AC_HELP_STRING([--with-native-sound-lib],[Path to sound library (for systems with name conflicts).]), [], []) dnl XE_HELP_SUBSECTION([Internationalization options]) XE_MERGED_ARG([mule], ! AC_HELP_STRING([--enable-mule],[Compile with Mule (Multi-Lingual Emacs) support, needed to support non-Latin-1 (including Asian) languages.]), [], []) XE_KEYWORD_ARG([xim], ! AC_HELP_STRING([--with-xim==TYPE],[Enable XIM support. TYPE is `yes', `no', `xlib', or `motif']), [],[],[yes,no,xlib,motif])dnl XE_MERGED_ARG([canna], ! AC_HELP_STRING([--with-canna],[Support the Canna Japanese input method. Requires Mule.]), [], []) XE_MERGED_ARG([wnn], ! AC_HELP_STRING([--with-wnn],[Support the Wnn Asian language input method. Requires Mule.]), [], []) XE_MERGED_ARG([wnn6], ! AC_HELP_STRING([--with-wnn6],[Support the Wnn6 Asian language input method (proprietary). Requires Mule.]), [], []) XE_MERGED_ARG([xfs], ! AC_HELP_STRING([--with-xfs],[Enable XFontSet support for internationalized menubar. Incompatible with `--with-xim=motif' and `--with-xft'. `--enable-menubars=lucid' (the default) is desirable.]), [], []) dnl XE_HELP_SUBSECTION([File-related options]) XE_MERGED_ARG([default-eol-detection], ! AC_HELP_STRING([--enable-default-eol-detection],[Turns on by default auto-detection of end-of-line type when reading a file. Applies to those platforms where auto-detection is off by default (non-Mule Unix). Has no effect otherwise.]), [], []) XE_MERGED_ARG([clash-detection], ! AC_HELP_STRING([--enable-clash-detection],[Disable use of lock files to detect multiple edits of the same file.]), [], []) XE_MERGED_ARG([zlib], ! AC_HELP_STRING([--with-zlib],[Support inflate (de)compression internally.]), [], []) dnl XE_HELP_SUBSECTION([Database options]) XE_COMPLEX_ARG([database], ! AC_HELP_STRING([--enable-database=TYPE],[Compile with database support. Valid types are `no' or a comma-separated list of one or more of `berkdb' and either `dbm' or `gnudbm'.]), [ --- 741,858 ---- unpredictable.]), [], []) XE_MERGED_ARG([xmu], ! AS_HELP_STRING([--with-xmu],[Use Xmu utilities. Default: yes.]), [], []) XE_MERGED_ARG([external-widget], ! AS_HELP_STRING([--enable-external-widget],[Support XEmacs server for text widgets in other applications.]), [], []) dnl XE_HELP_SUBSECTION([TTY (character terminal) options]) XE_MERGED_ARG([tty], ! AS_HELP_STRING([--with-tty],[Enable TTY support. Default: yes.]), [], []) XE_MERGED_ARG([ncurses], ! AS_HELP_STRING([--with-ncurses],[Use the ncurses library for tty support.]), [], []) XE_MERGED_ARG([gpm], ! AS_HELP_STRING([--with-gpm],[Compile in GPM mouse support for ttys.]), [], []) dnl XE_HELP_SUBSECTION([Image options]) XE_MERGED_ARG([xpm], ! AS_HELP_STRING([--with-xpm],[Compile with support for XPM images. PRACTICALLY REQUIRED. Although this library is nonstandard and a real hassle to build, many basic things (e.g. toolbars) depend on it, and you will run into many problems without it.]), [], []) XE_MERGED_ARG([png], ! AS_HELP_STRING([--with-png],[Compile with support for PNG images. Recommended because the images on the About page are not viewable without it.]), [], []) XE_MERGED_ARG([jpeg], ! AS_HELP_STRING([--with-jpeg],[Compile with support for JPEG images. Useful if you are using a mail, news reader, or web browser in XEmacs, so that JPEG images can be displayed.]), [], []) XE_MERGED_ARG([tiff], ! AS_HELP_STRING([--with-tiff],[Compile with support for TIFF images. Possibly useful, for the same reason as JPEG images.]), [], []) XE_MERGED_ARG([xface], ! AS_HELP_STRING([--with-xface],[Compile with support for X-Face mail headers. Requires the compface package.]), [], []) XE_MERGED_ARG([gif], ! AS_HELP_STRING([--with-gif],[Compile without the (builtin) support for GIF images.]), [], []) dnl XE_HELP_SUBSECTION([Sound options]) XE_COMPLEX_ARG([sound], ! AS_HELP_STRING([--enable-sound=TYPE],[Compile with sound support. ! Valid types are `native', `alsa', `nas' and `esd'. Prefix a type with 'no' to disable. The first type can be `none' or `all'. `none' means ! `nonative,noalsa,nonas,noesd'. `all' means ! `native,alsa,nas,esd'. Later options override earlier ! ones for the same TYPE. The default is to autodetect ! all sound support except for ESD which defaults to ! off.]), [], [enable_sound_nas=""], [XE_COMPLEX_OPTION([native],[""]), + XE_COMPLEX_OPTION([alsa],[""]), XE_COMPLEX_OPTION([nas],[""]), XE_COMPLEX_OPTION([esd],[no])]) XE_MERGED_ARG([native-sound-lib], ! AS_HELP_STRING([--with-native-sound-lib],[Path to sound library (for systems with name conflicts).]), [], []) dnl XE_HELP_SUBSECTION([Internationalization options]) XE_MERGED_ARG([mule], ! AS_HELP_STRING([--enable-mule],[Compile with Mule (Multi-Lingual Emacs) support, needed to support non-Latin-1 (including Asian) languages.]), [], []) XE_KEYWORD_ARG([xim], ! AS_HELP_STRING([--with-xim==TYPE],[Enable XIM support. TYPE is `yes', `no', `xlib', or `motif']), [],[],[yes,no,xlib,motif])dnl XE_MERGED_ARG([canna], ! AS_HELP_STRING([--with-canna],[Support the Canna Japanese input method. Requires Mule.]), [], []) XE_MERGED_ARG([wnn], ! AS_HELP_STRING([--with-wnn],[Support the Wnn Asian language input method. Requires Mule.]), [], []) XE_MERGED_ARG([wnn6], ! AS_HELP_STRING([--with-wnn6],[Support the Wnn6 Asian language input method (proprietary). Requires Mule.]), [], []) XE_MERGED_ARG([xfs], ! AS_HELP_STRING([--with-xfs],[Enable XFontSet support for internationalized menubar. Incompatible with `--with-xim=motif' and `--with-xft'. `--enable-menubars=lucid' (the default) is desirable.]), [], []) dnl XE_HELP_SUBSECTION([File-related options]) XE_MERGED_ARG([default-eol-detection], ! AS_HELP_STRING([--enable-default-eol-detection],[Turns on by default auto-detection of end-of-line type when reading a file. Applies to those platforms where auto-detection is off by default (non-Mule Unix). Has no effect otherwise.]), [], []) XE_MERGED_ARG([clash-detection], ! AS_HELP_STRING([--enable-clash-detection],[Disable use of lock files to detect multiple edits of the same file.]), [], []) XE_MERGED_ARG([zlib], ! AS_HELP_STRING([--with-zlib],[Support inflate (de)compression internally.]), [], []) dnl XE_HELP_SUBSECTION([Database options]) XE_COMPLEX_ARG([database], ! AS_HELP_STRING([--enable-database=TYPE],[Compile with database support. Valid types are `no' or a comma-separated list of one or more of `berkdb' and either `dbm' or `gnudbm'.]), [ *************** *** 864,937 **** XE_COMPLEX_OPTION([dbm],[""]), XE_COMPLEX_OPTION([gdbm],[""])]) XE_MERGED_ARG([ldap], ! AC_HELP_STRING([--with-ldap],[Support the LDAP protocol.]), [], []) XE_MERGED_ARG([postgresql], ! AC_HELP_STRING([--with-postgresql],[Support the PostgreSQL RDBMS.]), [], []) dnl XE_HELP_SUBSECTION([Mail options]) XE_KEYWORD_ARG([mail-locking], ! AC_HELP_STRING([--with-mail-locking=TYPE],[Specify the locking to be used by movemail to prevent concurrent updates of mail spool files. Valid types are `lockf', `flock', `file', `locking', `mmdf' or `pop'.]), [],[],[lockf,flock,file,locking,mmdf,pop])dnl XE_MERGED_ARG([pop], ! AC_HELP_STRING([--with-pop],[Support POP for mail retrieval.]), [], []) XE_MERGED_ARG([kerberos], ! AC_HELP_STRING([--with-kerberos],[Support Kerberos-authenticated POP.]), [], []) XE_MERGED_ARG([hesiod], ! AC_HELP_STRING([--with-hesiod],[Support Hesiod to get the POP server host.]), [], []) dnl XE_HELP_SUBSECTION([Networking options]) XE_MERGED_ARG([tooltalk], ! AC_HELP_STRING([--with-tooltalk],[Support the ToolTalk IPC protocol.]), [], []) XE_MERGED_ARG([socks], ! AC_HELP_STRING([--with-socks],[Compile with support for SOCKS (an Internet proxy).]), [], []) XE_MERGED_ARG([dnet], ! AC_HELP_STRING([--with-dnet],[Compile with support for DECnet.]), [], []) XE_MERGED_ARG([ipv6-cname], ! AC_HELP_STRING([--with-ipv6-cname],[Try IPv6 information first when canonicalizing host names. This option has no effect unless system supports getaddrinfo(3) and getnameinfo(3).]), [], [with_ipv6_cname="no"]) dnl XE_HELP_SUBSECTION([Memory allocation options]) XE_MERGED_ARG([rel-alloc], ! AC_HELP_STRING([--with-rel-alloc],[Enable the relocating allocator.]), [], [with_rel_alloc='default']) XE_MERGED_ARG([dlmalloc], ! AC_HELP_STRING([--with-dlmalloc],[Use Doug Lea's malloc implementation.]), [], [with_dlmalloc='default']) XE_MERGED_ARG([system-malloc], ! AC_HELP_STRING([--with-system-malloc],[Use the system malloc, not the one distributed with XEmacs.]), [], [with_system_malloc='default']) XE_MERGED_ARG([debug-malloc], ! AC_HELP_STRING([--with-debug-malloc],[Use a debugging malloc.]), [], []) XE_MERGED_ARG([pdump], ! AC_HELP_STRING([--enable-pdump],[Enable portable LISP preloader.]), [], []) XE_MERGED_ARG([dump-in-exec], ! AC_HELP_STRING([--enable-dump-in-exec],[Enable dumping into executable (enabled by default for `pdump', not enabled by default in combination ! with `mc-alloc').]), [], []) XE_MERGED_ARG([kkcc], ! AC_HELP_STRING([--enable-kkcc],[Enable experimental new GC algorithms.]), [], [enable_kkcc=yes]) ! XE_MERGED_ARG([mc-alloc], ! AC_HELP_STRING([--enable-mc-alloc],[Enable experimental new allocator.]), ! [], [enable_mc_alloc=yes]) XE_MERGED_ARG([newgc], ! AC_HELP_STRING([--enable-newgc],[Enable new incremental garbage collector.]), [], []) XE_COMPLEX_ARG([vdb], ! AC_HELP_STRING([--enable-vdb=TYPE],[Override auto-detection of virtual-dirty-bit write-barrier implementation for the new garbage collector. TYPE must be one of "auto" (for auto-detection), "posix", "win32", "mach", or "fake" --- 866,937 ---- XE_COMPLEX_OPTION([dbm],[""]), XE_COMPLEX_OPTION([gdbm],[""])]) XE_MERGED_ARG([ldap], ! AS_HELP_STRING([--with-ldap],[Support the LDAP protocol.]), [], []) XE_MERGED_ARG([postgresql], ! AS_HELP_STRING([--with-postgresql],[Support the PostgreSQL RDBMS.]), [], []) dnl XE_HELP_SUBSECTION([Mail options]) XE_KEYWORD_ARG([mail-locking], ! AS_HELP_STRING([--with-mail-locking=TYPE],[Specify the locking to be used by movemail to prevent concurrent updates of mail spool files. Valid types are `lockf', `flock', `file', `locking', `mmdf' or `pop'.]), [],[],[lockf,flock,file,locking,mmdf,pop])dnl XE_MERGED_ARG([pop], ! AS_HELP_STRING([--with-pop],[Support POP for mail retrieval.]), [], []) XE_MERGED_ARG([kerberos], ! AS_HELP_STRING([--with-kerberos],[Support Kerberos-authenticated POP.]), [], []) XE_MERGED_ARG([hesiod], ! AS_HELP_STRING([--with-hesiod],[Support Hesiod to get the POP server host.]), [], []) dnl XE_HELP_SUBSECTION([Networking options]) XE_MERGED_ARG([tooltalk], ! AS_HELP_STRING([--with-tooltalk],[Support the ToolTalk IPC protocol.]), [], []) XE_MERGED_ARG([socks], ! AS_HELP_STRING([--with-socks],[Compile with support for SOCKS (an Internet proxy).]), [], []) XE_MERGED_ARG([dnet], ! AS_HELP_STRING([--with-dnet],[Compile with support for DECnet.]), [], []) XE_MERGED_ARG([ipv6-cname], ! AS_HELP_STRING([--with-ipv6-cname],[Try IPv6 information first when canonicalizing host names. This option has no effect unless system supports getaddrinfo(3) and getnameinfo(3).]), [], [with_ipv6_cname="no"]) dnl XE_HELP_SUBSECTION([Memory allocation options]) XE_MERGED_ARG([rel-alloc], ! AS_HELP_STRING([--with-rel-alloc],[Enable the relocating allocator.]), [], [with_rel_alloc='default']) XE_MERGED_ARG([dlmalloc], ! AS_HELP_STRING([--with-dlmalloc],[Use Doug Lea's malloc implementation.]), [], [with_dlmalloc='default']) XE_MERGED_ARG([system-malloc], ! AS_HELP_STRING([--with-system-malloc],[Use the system malloc, not the one distributed with XEmacs.]), [], [with_system_malloc='default']) XE_MERGED_ARG([debug-malloc], ! AS_HELP_STRING([--with-debug-malloc],[Use a debugging malloc.]), [], []) XE_MERGED_ARG([pdump], ! AS_HELP_STRING([--enable-pdump],[Enable portable LISP preloader.]), [], []) XE_MERGED_ARG([dump-in-exec], ! AS_HELP_STRING([--enable-dump-in-exec],[Enable dumping into executable (enabled by default for `pdump', not enabled by default in combination ! with `newgc').]), [], []) XE_MERGED_ARG([kkcc], ! AS_HELP_STRING([--enable-kkcc],[Enable experimental new GC mark algorithms.]), [], [enable_kkcc=yes]) ! XE_MERGED_ARG([newgc], ! AS_HELP_STRING([--enable-newgc],[Enable new incremental garbage collector and new allocator.]), [], []) XE_COMPLEX_ARG([vdb], ! AS_HELP_STRING([--enable-vdb=TYPE],[Override auto-detection of virtual-dirty-bit write-barrier implementation for the new garbage collector. TYPE must be one of "auto" (for auto-detection), "posix", "win32", "mach", or "fake" *************** *** 942,974 **** dnl XE_HELP_SUBSECTION([Emacs Lisp options]) XE_MERGED_ARG([modules], ! AC_HELP_STRING([--enable-modules],[Compile in experimental support for dynamically loaded libraries (Dynamic Shared Objects).]), [], []) XE_KEYWORD_ARG([bignum], ! AC_HELP_STRING([--enable-bignum=TYPE],[Compile in support for bignums, ratios, or bigfloats using library support. TYPE must be one of "gmp" (for GNU MP), "mp" (for BSD MP), or "no" (disabled).]), [], [enable_bignum="no"],[no,gmp,mp]) dnl XE_HELP_SUBSECTION([Platform Specific options]) XE_MERGED_ARG([workshop], ! AC_HELP_STRING([--with-workshop],[Support the Sun WorkShop (formerly Sparcworks) development environment.]), [], []) XE_MERGED_ARG([sparcworks], ! AC_HELP_STRING([--with-sparcworks],[Alias for --with-workshop]), [], []) XE_MERGED_ARG([infodock], ! AC_HELP_STRING([--with-infodock],[Support the Infodock version of XEmacs. Infodock is a SourceForge project).]), [], []) dnl XE_HELP_SUBSECTION([Debugging options]) XE_MERGED_ARG([debug], ! AC_HELP_STRING([--enable-debug],[Enable additional debugging information. No time cost.]), [], []) XE_COMPLEX_ARG([error-checking], ! AC_HELP_STRING([--enable-error-checking=TESTS],[Compile with internal error-checking added. Causes noticeable loss of speed. Valid TESTS are `extents', `bufpos', `malloc', `gc', `types', `text', `byte_code', `glyphs', `display', `structures'.]), [], [], --- 942,974 ---- dnl XE_HELP_SUBSECTION([Emacs Lisp options]) XE_MERGED_ARG([modules], ! AS_HELP_STRING([--enable-modules],[Compile in experimental support for dynamically loaded libraries (Dynamic Shared Objects).]), [], []) XE_KEYWORD_ARG([bignum], ! AS_HELP_STRING([--enable-bignum=TYPE],[Compile in support for bignums, ratios, or bigfloats using library support. TYPE must be one of "gmp" (for GNU MP), "mp" (for BSD MP), or "no" (disabled).]), [], [enable_bignum="no"],[no,gmp,mp]) dnl XE_HELP_SUBSECTION([Platform Specific options]) XE_MERGED_ARG([workshop], ! AS_HELP_STRING([--with-workshop],[Support the Sun WorkShop (formerly Sparcworks) development environment.]), [], []) XE_MERGED_ARG([sparcworks], ! AS_HELP_STRING([--with-sparcworks],[Alias for --with-workshop]), [], []) XE_MERGED_ARG([infodock], ! AS_HELP_STRING([--with-infodock],[Support the Infodock version of XEmacs. Infodock is a SourceForge project).]), [], []) dnl XE_HELP_SUBSECTION([Debugging options]) XE_MERGED_ARG([debug], ! AS_HELP_STRING([--enable-debug],[Enable additional debugging information. No time cost.]), [], []) XE_COMPLEX_ARG([error-checking], ! AS_HELP_STRING([--enable-error-checking=TESTS],[Compile with internal error-checking added. Causes noticeable loss of speed. Valid TESTS are `extents', `bufpos', `malloc', `gc', `types', `text', `byte_code', `glyphs', `display', `structures'.]), [], [], *************** *** 982,994 **** XE_COMPLEX_OPTION([display],[""]), XE_COMPLEX_OPTION([structures],[""])]) XE_MERGED_ARG([assertions], ! AC_HELP_STRING([--enable-assertions],[Compile in runtime assertions.]), [], []) XE_MERGED_ARG([memory-usage-stats], ! AC_HELP_STRING([--enable-memory-usage-stats],[Enable LISP memory usage API.]), [], []) XE_MERGED_ARG([quick-build], ! AC_HELP_STRING([--enable-quick-build],[Speed up the build cycle by leaving out steps where XEmacs will still work (more or less) without them. Potentially dangerous if you don't know what you're doing. This (1) doesn't garbage-collect after loading --- 982,994 ---- XE_COMPLEX_OPTION([display],[""]), XE_COMPLEX_OPTION([structures],[""])]) XE_MERGED_ARG([assertions], ! AS_HELP_STRING([--enable-assertions],[Compile in runtime assertions.]), [], []) XE_MERGED_ARG([memory-usage-stats], ! AS_HELP_STRING([--enable-memory-usage-stats],[Enable LISP memory usage API.]), [], []) XE_MERGED_ARG([quick-build], ! AS_HELP_STRING([--enable-quick-build],[Speed up the build cycle by leaving out steps where XEmacs will still work (more or less) without them. Potentially dangerous if you don't know what you're doing. This (1) doesn't garbage-collect after loading *************** *** 1000,1012 **** to be rebuilt.]), [], []) XE_MERGED_ARG([union-type], ! AC_HELP_STRING([--enable-union-type],[Use union definition of Lisp_Object type. Known to trigger bugs in some compilers.]), [], []) XE_MERGED_ARG([quantify], ! AC_HELP_STRING([--with-quantify],[Support performance debugging using Quantify.]), [], []) XE_MERGED_ARG([purify], ! AC_HELP_STRING([--with-purify],[Support memory debugging using Purify.]), [], []) dnl ------------------------------------------------------------------------- dnl Final command line argument checks. --- 1000,1012 ---- to be rebuilt.]), [], []) XE_MERGED_ARG([union-type], ! AS_HELP_STRING([--enable-union-type],[Use union definition of Lisp_Object type. Known to trigger bugs in some compilers.]), [], []) XE_MERGED_ARG([quantify], ! AS_HELP_STRING([--with-quantify],[Support performance debugging using Quantify.]), [], []) XE_MERGED_ARG([purify], ! AS_HELP_STRING([--with-purify],[Support memory debugging using Purify.]), [], []) dnl ------------------------------------------------------------------------- dnl Final command line argument checks. *************** *** 1925,1936 **** dnl the compilation environment at configure time and compile time agree. AC_MSG_CHECKING(for GNU libc) ! AC_TRY_COMPILE([#include ],[ #if ! (defined __GLIBC__ || defined __GNU_LIBRARY__) #error Not a GNU libc system :-( ******* ======= ******** &&&&&&&& #endif ! ], have_glibc=yes, have_glibc=no) AC_MSG_RESULT($have_glibc) dnl I'm tired of pop being broken with GLIBC -slb dnl Well. then why not fix fucking pop? --- 1925,1936 ---- dnl the compilation environment at configure time and compile time agree. AC_MSG_CHECKING(for GNU libc) ! AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ],[ #if ! (defined __GLIBC__ || defined __GNU_LIBRARY__) #error Not a GNU libc system :-( ******* ======= ******** &&&&&&&& #endif ! ])], have_glibc=yes, have_glibc=no) AC_MSG_RESULT($have_glibc) dnl I'm tired of pop being broken with GLIBC -slb dnl Well. then why not fix fucking pop? *************** *** 2128,2141 **** lib_gcc= fi ! dnl Enable KKCC and MC-ALLOC by default test -z "$enable_kkcc" && enable_kkcc=yes - test -z "$enable_mc_alloc" && enable_mc_alloc=yes dnl Dump into executable if test -z "$enable_dump_in_exec"; then if test "$enable_pdump" = "yes"; then ! if test "$enable_mc_alloc" = "yes"; then enable_dump_in_exec=no else enable_dump_in_exec=yes --- 2128,2140 ---- lib_gcc= fi ! dnl Enable KKCC by default test -z "$enable_kkcc" && enable_kkcc=yes dnl Dump into executable if test -z "$enable_dump_in_exec"; then if test "$enable_pdump" = "yes"; then ! if test "$enable_newgc" = "yes"; then enable_dump_in_exec=no else enable_dump_in_exec=yes *************** *** 2145,2151 **** dnl New incremental garbage collector if test "$enable_newgc" = "yes"; then - enable_mc_alloc=yes enable_kkcc=yes fi --- 2144,2149 ---- *************** *** 2186,2195 **** if test "$__USLC__" = yes; then AC_MSG_CHECKING(for whether the -Kalloca compiler flag is needed) need_kalloca=no ! AC_TRY_LINK([], [void *x = alloca(4);], [:], [ xe_save_c_switch_system="$c_switch_system" c_switch_system="$c_switch_system -Kalloca" ! AC_TRY_LINK([], [void *x = alloca(4);], [ need_kalloca=yes ]) c_switch_system="$xe_save_c_switch_system"]) AC_MSG_RESULT($need_kalloca) test "$need_kalloca" = "yes" && XE_APPEND(-Kalloca,c_switch_system) --- 2184,2194 ---- if test "$__USLC__" = yes; then AC_MSG_CHECKING(for whether the -Kalloca compiler flag is needed) need_kalloca=no ! AC_LINK_IFELSE([AC_LANG_PROGRAM([], [void *x = alloca(4);])], [:], [ xe_save_c_switch_system="$c_switch_system" c_switch_system="$c_switch_system -Kalloca" ! AC_LINK_IFELSE([AC_LANG_PROGRAM([], [void *x = alloca(4);])], ! [ need_kalloca=yes ]) c_switch_system="$xe_save_c_switch_system"]) AC_MSG_RESULT($need_kalloca) test "$need_kalloca" = "yes" && XE_APPEND(-Kalloca,c_switch_system) *************** *** 2441,2447 **** dnl #### Should make this Solaris-friendly. dnl Link with -z nocombreloc for now. if test "$enable_pdump" != "yes"; then ! AC_MSG_CHECKING(for \"-z nocombreloc\" linker flag) case "`ld --help 2>&1`" in *-z\ nocombreloc* ) AC_MSG_RESULT(yes) XE_PREPEND(-z nocombreloc, ld_switch_site) ;; --- 2440,2446 ---- dnl #### Should make this Solaris-friendly. dnl Link with -z nocombreloc for now. if test "$enable_pdump" != "yes"; then ! AC_MSG_CHECKING([for "-z nocombreloc" linker flag]) case "`ld --help 2>&1`" in *-z\ nocombreloc* ) AC_MSG_RESULT(yes) XE_PREPEND(-z nocombreloc, ld_switch_site) ;; *************** *** 2740,2746 **** if test "$add_runtime_path" = "yes"; then dnl Try to autodetect runtime library flag (usually -R), dnl and whether it works (or at least does no harm) ! AC_MSG_CHECKING("for runtime libraries flag") case "$opsys" in sol2 ) dash_r="-R" ;; decosf* | linux* | irix*) dash_r="-rpath " ;; --- 2739,2745 ---- if test "$add_runtime_path" = "yes"; then dnl Try to autodetect runtime library flag (usually -R), dnl and whether it works (or at least does no harm) ! AC_MSG_CHECKING([for runtime libraries flag]) case "$opsys" in sol2 ) dash_r="-R" ;; decosf* | linux* | irix*) dash_r="-rpath " ;; *************** *** 2749,2761 **** for try_dash_r in "-R" "-R " "-rpath "; do xe_check_libs="${try_dash_r}/no/such/file-or-directory" XE_PROTECT_LINKER_FLAGS(xe_check_libs) ! AC_TRY_LINK(, , dash_r="$try_dash_r") xe_check_libs="" test -n "$dash_r" && break done ;; esac if test -n "$dash_r"; ! then AC_MSG_RESULT("\"${dash_r}\"") else AC_MSG_RESULT(NONE) fi fi --- 2748,2760 ---- for try_dash_r in "-R" "-R " "-rpath "; do xe_check_libs="${try_dash_r}/no/such/file-or-directory" XE_PROTECT_LINKER_FLAGS(xe_check_libs) ! AC_LINK_IFELSE([], dash_r="$try_dash_r") xe_check_libs="" test -n "$dash_r" && break done ;; esac if test -n "$dash_r"; ! then AC_MSG_RESULT(["${dash_r}"]) else AC_MSG_RESULT(NONE) fi fi *************** *** 2788,2794 **** after_morecore_hook_exists=yes AC_CHECK_FUNC(malloc_set_state, ,doug_lea_malloc=no) AC_MSG_CHECKING(whether __after_morecore_hook exists) ! AC_TRY_LINK([extern void (* __after_morecore_hook)();],[__after_morecore_hook = 0], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) after_morecore_hook_exists=no]) --- 2787,2794 ---- after_morecore_hook_exists=yes AC_CHECK_FUNC(malloc_set_state, ,doug_lea_malloc=no) AC_MSG_CHECKING(whether __after_morecore_hook exists) ! AC_LINK_IFELSE([AC_LANG_PROGRAM([extern void (* __after_morecore_hook)();], ! [__after_morecore_hook = 0])], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) after_morecore_hook_exists=no]) *************** *** 2848,2854 **** elf.h dnl cygwin/version.h dnl fcntl.h dnl - inttypes.h dnl libgen.h dnl locale.h dnl wchar.h dnl --- 2848,2853 ---- *************** *** 2862,2868 **** sys/un.h dnl sys/vlimit.h dnl ulimit.h dnl - unistd.h dnl ) AC_HEADER_SYS_WAIT AC_HEADER_STDC --- 2861,2866 ---- *************** *** 2883,2891 **** dnl so we use a more sophisticated test for utime than AC_CHECK_FUNCS. dnl ---------------------------------------------------------------- AC_MSG_CHECKING(for utime) ! AC_TRY_COMPILE([#include #include ], ! [struct utimbuf x; x.actime = x.modtime = 0; utime ("/", &x);], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_UTIME)], [AC_MSG_RESULT(no) --- 2881,2889 ---- dnl so we use a more sophisticated test for utime than AC_CHECK_FUNCS. dnl ---------------------------------------------------------------- AC_MSG_CHECKING(for utime) ! AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include #include ], ! [struct utimbuf x; x.actime = x.modtime = 0; utime ("/", &x);])], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_UTIME)], [AC_MSG_RESULT(no) *************** *** 2906,2935 **** dnl not AC_CHECK_TYPE; lisp.h does hairy conditional typedef if test "$ac_cv_header_inttypes_h" != "yes"; then AC_MSG_CHECKING(for intptr_t in sys/types.h) ! AC_TRY_COMPILE([#include intptr_t x; ! ],[],[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_INTPTR_T_IN_SYS_TYPES_H,1)], [AC_MSG_RESULT(no)]) fi dnl check for Unix98 socklen_t AC_MSG_CHECKING(for socklen_t) ! AC_TRY_COMPILE([#include #include socklen_t x; ! ],[],[AC_MSG_RESULT(yes)],[ ! AC_TRY_COMPILE([#include #include int accept (int, struct sockaddr *, size_t *); ! ],[],[ AC_MSG_RESULT(size_t) AC_DEFINE(socklen_t,size_t)], [ AC_MSG_RESULT(int) AC_DEFINE(socklen_t,int)])]) AC_MSG_CHECKING(for struct timeval) ! AC_TRY_COMPILE([#ifdef TIME_WITH_SYS_TIME #include #include #else --- 2904,2933 ---- dnl not AC_CHECK_TYPE; lisp.h does hairy conditional typedef if test "$ac_cv_header_inttypes_h" != "yes"; then AC_MSG_CHECKING(for intptr_t in sys/types.h) ! AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include intptr_t x; ! ])],[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_INTPTR_T_IN_SYS_TYPES_H,1)], [AC_MSG_RESULT(no)]) fi dnl check for Unix98 socklen_t AC_MSG_CHECKING(for socklen_t) ! AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include #include socklen_t x; ! ])],[AC_MSG_RESULT(yes)],[ ! AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include #include int accept (int, struct sockaddr *, size_t *); ! ])],[ AC_MSG_RESULT(size_t) AC_DEFINE(socklen_t,size_t)], [ AC_MSG_RESULT(int) AC_DEFINE(socklen_t,int)])]) AC_MSG_CHECKING(for struct timeval) ! AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#ifdef TIME_WITH_SYS_TIME #include #include #else *************** *** 2938,2944 **** #else #include #endif ! #endif], [static struct timeval x; x.tv_sec = x.tv_usec;], [AC_MSG_RESULT(yes) HAVE_TIMEVAL=yes AC_DEFINE(HAVE_TIMEVAL)], --- 2936,2942 ---- #else #include #endif ! #endif], [static struct timeval x; x.tv_sec = x.tv_usec;])], [AC_MSG_RESULT(yes) HAVE_TIMEVAL=yes AC_DEFINE(HAVE_TIMEVAL)], *************** *** 2978,2992 **** dnl -lm is required for floating point support, among other things AC_CHECK_FUNC(sin, ,AC_CHECK_LIB(m, sin)) ! AC_TRY_LINK([#include ], ! [return atanh(1.0) + asinh(1.0) + acosh(1.0); ], AC_DEFINE(HAVE_INVERSE_HYPERBOLIC)) dnl See if mkstemp is available AC_CHECK_FUNCS(mkstemp) dnl Determine type of mail locking from configure args and s&m headers ! AC_CHECKING([type of mail spool file locking]) AC_CHECK_FUNCS(lockf flock) dnl The mail_use_xxx variables are set according to the s&m headers. test -z "$with_mail_locking" -a "$mail_use_flock" = "yes" && with_mail_locking=flock --- 2976,2991 ---- dnl -lm is required for floating point support, among other things AC_CHECK_FUNC(sin, ,AC_CHECK_LIB(m, sin)) ! AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ! [return atanh(1.0) + asinh(1.0) + acosh(1.0); ])], AC_DEFINE(HAVE_INVERSE_HYPERBOLIC)) dnl See if mkstemp is available AC_CHECK_FUNCS(mkstemp) dnl Determine type of mail locking from configure args and s&m headers ! AC_MSG_CHECKING([type of mail spool file locking]) ! AC_MSG_RESULT() AC_CHECK_FUNCS(lockf flock) dnl The mail_use_xxx variables are set according to the s&m headers. test -z "$with_mail_locking" -a "$mail_use_flock" = "yes" && with_mail_locking=flock *************** *** 3036,3042 **** dnl Link with "-z ignore" on Solaris if supported if test "$opsys" = "sol2"; then if test "$os_release" -ge 506; then ! AC_MSG_CHECKING(for \"-z ignore\" linker flag) case "`ld -h 2>&1`" in *-z\ ignore\|record* ) AC_MSG_RESULT(yes) XE_PREPEND(-z ignore, ld_switch_site) ;; --- 3035,3041 ---- dnl Link with "-z ignore" on Solaris if supported if test "$opsys" = "sol2"; then if test "$os_release" -ge 506; then ! AC_MSG_CHECKING([for "-z ignore" linker flag]) case "`ld -h 2>&1`" in *-z\ ignore\|record* ) AC_MSG_RESULT(yes) XE_PREPEND(-z ignore, ld_switch_site) ;; *************** *** 3049,3055 **** dnl Choose a window system dnl ---------------------- ! AC_CHECKING([for specified window system]) dnl Autodetection of Gdk libraries and includes dnl ------------------------------------------- --- 3048,3055 ---- dnl Choose a window system dnl ---------------------- ! AC_MSG_CHECKING([for specified window system]) ! AC_MSG_RESULT() dnl Autodetection of Gdk libraries and includes dnl ------------------------------------------- *************** *** 3309,3315 **** test ! -z "$bitmapdirs" && AC_DEFINE_UNQUOTED(BITMAPDIR, "$bitmapdirs") dnl Autodetect defines extracted from X config by xmkmf, e.g. NARROWPROTO ! AC_CHECKING([for X defines extracted by xmkmf]) rm -fr conftestdir if mkdir conftestdir; then cd conftestdir --- 3309,3316 ---- test ! -z "$bitmapdirs" && AC_DEFINE_UNQUOTED(BITMAPDIR, "$bitmapdirs") dnl Autodetect defines extracted from X config by xmkmf, e.g. NARROWPROTO ! AC_MSG_CHECKING([for X defines extracted by xmkmf]) ! AC_MSG_RESULT() rm -fr conftestdir if mkdir conftestdir; then cd conftestdir *************** *** 3387,3398 **** dnl XFree86 has a non-standard prototype for this X11R6 function AC_CHECK_FUNCS(XRegisterIMInstantiateCallback) AC_MSG_CHECKING(for standard XRegisterIMInstantiateCallback prototype) ! AC_TRY_COMPILE([ #define NeedFunctionPrototypes 1 #include extern Bool XRegisterIMInstantiateCallback( Display*, struct _XrmHashBucketRec*, char*, char*, XIMProc, XPointer*); ! ], [], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) AC_DEFINE(XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE)]) --- 3388,3399 ---- dnl XFree86 has a non-standard prototype for this X11R6 function AC_CHECK_FUNCS(XRegisterIMInstantiateCallback) AC_MSG_CHECKING(for standard XRegisterIMInstantiateCallback prototype) ! AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #define NeedFunctionPrototypes 1 #include extern Bool XRegisterIMInstantiateCallback( Display*, struct _XrmHashBucketRec*, char*, char*, XIMProc, XPointer*); ! ])], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) AC_DEFINE(XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE)]) *************** *** 3430,3436 **** dnl #### need to check for includes here (especially, freetype.h for v.2) if test "$with_xft_emacs" = "yes"; then ! AC_CHECKING([for Xrender, fontconfig, and Xft]) xft_includes_found=no AC_CHECK_HEADERS([freetype/config/ftheader.h], [xft_includes_found=yes], --- 3431,3437 ---- dnl #### need to check for includes here (especially, freetype.h for v.2) if test "$with_xft_emacs" = "yes"; then ! AC_MSG_CHECKING([for Xrender, fontconfig, and Xft]) xft_includes_found=no AC_CHECK_HEADERS([freetype/config/ftheader.h], [xft_includes_found=yes], *************** *** 3441,3447 **** "/usr/include/freetype2" do if test -d $freetype_include_top; then ! AC_CHECKING([in ${freetype_include_top}/freetype2]) dnl disable autoconf's fucking cache; why these fuckheads think it dnl is better to be broken than to be slow, I don't know! dnl #### there's gotta be a better-looking way to do this!! --- 3442,3448 ---- "/usr/include/freetype2" do if test -d $freetype_include_top; then ! AC_MSG_CHECKING([in ${freetype_include_top}/freetype2]) dnl disable autoconf's fucking cache; why these fuckheads think it dnl is better to be broken than to be slow, I don't know! dnl #### there's gotta be a better-looking way to do this!! *************** *** 3472,3478 **** fi dnl $with_x11 = yes if test "$with_msw" != "no"; then ! AC_CHECKING([for MS-Windows]) AC_CHECK_LIB(gdi32,main,with_msw=yes) if test "$with_msw" = "yes"; then AC_DEFINE(HAVE_MS_WINDOWS) --- 3473,3480 ---- fi dnl $with_x11 = yes if test "$with_msw" != "no"; then ! AC_MSG_CHECKING([for MS-Windows]) ! AC_MSG_RESULT() AC_CHECK_LIB(gdi32,main,with_msw=yes) if test "$with_msw" = "yes"; then AC_DEFINE(HAVE_MS_WINDOWS) *************** *** 3585,3594 **** esac dnl Enable or disable proper handling of WM_COMMAND ! AC_CHECKING([for WM_COMMAND option]) dnl if test "$with_wmcommand" = "yes"; then if test "$with_wmcommand" != "no"; then AC_DEFINE(HAVE_WMCOMMAND) fi dnl Autodetect Xauth --- 3587,3599 ---- esac dnl Enable or disable proper handling of WM_COMMAND ! AC_MSG_CHECKING([for WM_COMMAND option]) dnl if test "$with_wmcommand" = "yes"; then if test "$with_wmcommand" != "no"; then AC_DEFINE(HAVE_WMCOMMAND) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) fi dnl Autodetect Xauth *************** *** 3621,3627 **** dnl This must come before the detection code for anything that is in a module if test "$enable_modules" != "no"; then ! AC_CHECKING([for module support]) case "$opsys" in mingw* | cygwin* ) have_dl=yes ;; --- 3626,3633 ---- dnl This must come before the detection code for anything that is in a module if test "$enable_modules" != "no"; then ! AC_MSG_CHECKING([for module support]) ! AC_MSG_RESULT() case "$opsys" in mingw* | cygwin* ) have_dl=yes ;; *************** *** 3632,3650 **** dnl Check for the ELFish dlopen() AC_CHECK_HEADER(dlfcn.h, [ AC_MSG_CHECKING([for dlopen in -lc]) ! AC_TRY_LINK([#include ],dnl ! [dlopen ("", 0);], [ have_dl=yes ; AC_MSG_RESULT($have_dl)], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([for dlopen in -ldl]) ac_save_LIBS="$LIBS" LIBS="$LIBS -ldl" ! AC_TRY_LINK([#include ],dnl ! [dlopen ("", 0);], [ have_dl=yes; AC_MSG_RESULT($have_dl)], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([for dlopen in -lsvld]) LIBS="$ac_save_LIBS -lsvld" ! AC_TRY_LINK([#include ],dnl ! [dlopen ("", 0);], [ have_dl=yes; AC_MSG_RESULT($have_dl) ], [LIBS="$ac_save_LIBS" ; AC_MSG_RESULT([no])])])])]) if test "$have_dl" = "yes"; then AC_DEFINE(HAVE_DLOPEN) --- 3638,3656 ---- dnl Check for the ELFish dlopen() AC_CHECK_HEADER(dlfcn.h, [ AC_MSG_CHECKING([for dlopen in -lc]) ! AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ! [dlopen ("", 0);])], [ have_dl=yes ; AC_MSG_RESULT($have_dl)], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([for dlopen in -ldl]) ac_save_LIBS="$LIBS" LIBS="$LIBS -ldl" ! AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ! [dlopen ("", 0);])], [ have_dl=yes; AC_MSG_RESULT($have_dl)], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([for dlopen in -lsvld]) LIBS="$ac_save_LIBS -lsvld" ! AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ! [dlopen ("", 0);])], [ have_dl=yes; AC_MSG_RESULT($have_dl) ], [LIBS="$ac_save_LIBS" ; AC_MSG_RESULT([no])])])])]) if test "$have_dl" = "yes"; then AC_DEFINE(HAVE_DLOPEN) *************** *** 3652,3665 **** dnl Check for HP/UX shl_load AC_CHECK_HEADER(dl.h, [ AC_MSG_CHECKING([for shl_load in -lc]) ! AC_TRY_LINK([#include ],dnl ! [shl_load ("", 0, 0);], [have_dl=yes; AC_MSG_RESULT($have_dl)], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([for shl_load in -ldl]) ac_save_LIBS="$LIBS" LIBS="$LIBS -ldld" ! AC_TRY_LINK([#include ],dnl ! [shl_load ("", 0, 0);], [have_dl=yes], [LIBS="$ac_save_LIBS"; AC_MSG_RESULT([no])])])]) if test "$have_dl" = "yes"; then AC_DEFINE(HAVE_SHL_LOAD) --- 3658,3671 ---- dnl Check for HP/UX shl_load AC_CHECK_HEADER(dl.h, [ AC_MSG_CHECKING([for shl_load in -lc]) ! AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ! [shl_load ("", 0, 0);])], [have_dl=yes; AC_MSG_RESULT($have_dl)], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([for shl_load in -ldl]) ac_save_LIBS="$LIBS" LIBS="$LIBS -ldld" ! AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ! [shl_load ("", 0, 0);])], [have_dl=yes], [LIBS="$ac_save_LIBS"; AC_MSG_RESULT([no])])])]) if test "$have_dl" = "yes"; then AC_DEFINE(HAVE_SHL_LOAD) *************** *** 3669,3676 **** AC_MSG_CHECKING([for lt_dlinit in -lltdl]) ac_save_LIBS="$LIBS" LIBS="$LIBS -lltdl" ! AC_TRY_LINK([#include ],dnl ! [lt_dlinit ();], [have_dl=yes], [LIBS="$ac_save_LIBS"])]) AC_MSG_RESULT($have_dl) if test "$have_dl" = "yes"; then AC_DEFINE(HAVE_LTDL) --- 3675,3682 ---- AC_MSG_CHECKING([for lt_dlinit in -lltdl]) ac_save_LIBS="$LIBS" LIBS="$LIBS -lltdl" ! AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ! [lt_dlinit ();])], [have_dl=yes], [LIBS="$ac_save_LIBS"])]) AC_MSG_RESULT($have_dl) if test "$have_dl" = "yes"; then AC_DEFINE(HAVE_LTDL) *************** *** 3768,3774 **** test -z "$with_cde" && { AC_CHECK_LIB(DtSvc, DtDndDragStart, [:], with_cde=no) } if test "$with_dragndrop" = "no" ; then if test "$with_cde" = "yes" ; then ! AC_MSG_WARN([--with-cde forced to \`no'; no generic Drag'n'Drop support]) fi with_cde=no fi --- 3774,3780 ---- test -z "$with_cde" && { AC_CHECK_LIB(DtSvc, DtDndDragStart, [:], with_cde=no) } if test "$with_dragndrop" = "no" ; then if test "$with_cde" = "yes" ; then ! AC_MSG_WARN([--with-cde forced to `no'; no generic Drag'n'Drop support]) fi with_cde=no fi *************** *** 3789,3807 **** test "$window_system" != "x11" && with_offix=no if test "$with_xmu" != yes -a "$with_x11" = yes; then if test "$with_offix" = "yes" ; then ! AC_MSG_WARN([--with-offix forced to \`no'; no real Xmu support]) fi with_offix=no fi if test "$with_dragndrop" = no; then if test "$with_offix" = "yes" ; then ! AC_MSG_WARN([--with-offix forced to \`no'; no generic Drag'n'Drop support]) fi with_offix=no fi if test "$with_cde" = yes; then if test "$with_offix" = "yes" ; then ! AC_MSG_WARN([--with-offix forced to \`no'; CDE already found]) fi with_offix=no fi --- 3795,3813 ---- test "$window_system" != "x11" && with_offix=no if test "$with_xmu" != yes -a "$with_x11" = yes; then if test "$with_offix" = "yes" ; then ! AC_MSG_WARN([--with-offix forced to `no'; no real Xmu support]) fi with_offix=no fi if test "$with_dragndrop" = no; then if test "$with_offix" = "yes" ; then ! AC_MSG_WARN([--with-offix forced to `no'; no generic Drag'n'Drop support]) fi with_offix=no fi if test "$with_cde" = yes; then if test "$with_offix" = "yes" ; then ! AC_MSG_WARN([--with-offix forced to `no'; CDE already found]) fi with_offix=no fi *************** *** 3831,3837 **** fi dnl Autodetect LDAP ! AC_CHECKING([for LDAP]) ldap_libs= test -z "$with_ldap" && { AC_CHECK_HEADER(ldap.h, ,with_ldap=no) } test -z "$with_ldap" && { AC_CHECK_HEADER(lber.h, ,with_ldap=no) } --- 3837,3844 ---- fi dnl Autodetect LDAP ! AC_MSG_CHECKING([for LDAP]) ! AC_MSG_RESULT() ldap_libs= test -z "$with_ldap" && { AC_CHECK_HEADER(ldap.h, ,with_ldap=no) } test -z "$with_ldap" && { AC_CHECK_HEADER(lber.h, ,with_ldap=no) } *************** *** 3881,3887 **** dnl that prefix must be specified using the --with-site-prefixes flag. postgresql_libs= if test "$with_postgresql" != "no"; then ! AC_CHECKING([for PostgreSQL]) dnl Look for these standard header file locations, known to be used on Linux for header_dir in "" "pgsql/" "postgresql/"; do --- 3888,3895 ---- dnl that prefix must be specified using the --with-site-prefixes flag. postgresql_libs= if test "$with_postgresql" != "no"; then ! AC_MSG_CHECKING([for PostgreSQL]) ! AC_MSG_RESULT() dnl Look for these standard header file locations, known to be used on Linux for header_dir in "" "pgsql/" "postgresql/"; do *************** *** 3930,3936 **** dnl ---------------------- if test "$window_system" != "none"; then ! AC_CHECKING([for graphics libraries]) dnl add special code to handle xpm-nox on Cygwin (csw) dnl -- should only happen if CYGWIN && WITH_XPM && WITH_MSW && !WITH_X --- 3938,3945 ---- dnl ---------------------- if test "$window_system" != "none"; then ! AC_MSG_CHECKING([for graphics libraries]) ! AC_MSG_RESULT() dnl add special code to handle xpm-nox on Cygwin (csw) dnl -- should only happen if CYGWIN && WITH_XPM && WITH_MSW && !WITH_X *************** *** 4003,4011 **** XE_PREPEND(-lXpm, libs_x) XE_PREPEND("$incpath_xpm", CFLAGS) XE_PREPEND("$incpath_xpm", XE_CFLAGS) ! AC_MSG_CHECKING(for \"FOR_MSW\" xpm) xe_check_libs=-lXpm ! AC_TRY_LINK(, [XpmCreatePixmapFromData()], [xpm_for_msw=no], [xpm_for_msw=yes]) xe_check_libs= --- 4012,4020 ---- XE_PREPEND(-lXpm, libs_x) XE_PREPEND("$incpath_xpm", CFLAGS) XE_PREPEND("$incpath_xpm", XE_CFLAGS) ! AC_MSG_CHECKING([for "FOR_MSW" xpm]) xe_check_libs=-lXpm ! AC_LINK_IFELSE([AC_LANG_PROGRAM([],[XpmCreatePixmapFromData();])], [xpm_for_msw=no], [xpm_for_msw=yes]) xe_check_libs= *************** *** 4112,4124 **** fi fi - dnl ---------------------- dnl X-Specific Graphics libraries dnl ---------------------- if test "$with_x11" = "yes"; then ! AC_CHECKING([for X11 graphics libraries]) fi case "$enable_widgets" in --- 4121,4133 ---- fi fi dnl ---------------------- dnl X-Specific Graphics libraries dnl ---------------------- if test "$with_x11" = "yes"; then ! AC_MSG_CHECKING([for X11 graphics libraries]) ! AC_MSG_RESULT() fi case "$enable_widgets" in *************** *** 4131,4137 **** esac if test "$with_x11" = "yes" -a "$detect_athena" = "yes" ; then ! AC_CHECKING([for the Athena widgets]) dnl What in heck did the user actually want? case "$with_athena" in --- 4140,4147 ---- esac if test "$with_x11" = "yes" -a "$detect_athena" = "yes" ; then ! AC_MSG_CHECKING([for the Athena widgets]) ! AC_MSG_RESULT() dnl What in heck did the user actually want? case "$with_athena" in *************** *** 4463,4479 **** wnn_libs= if test "$enable_mule" = "yes" ; then ! AC_CHECKING([for Mule-related features]) AC_DEFINE(MULE) dnl Use -lintl to get internationalized strerror for Mule AC_CHECK_HEADERS(libintl.h) AC_CHECK_LIB(intl, strerror) ! AC_CHECKING([for Mule input methods]) dnl Do we have the XmIm* routines? And if so, do we want to use them? case "$with_xim" in "" | "yes" ) ! AC_CHECKING([for XIM]) AC_CHECK_LIB(X11, XOpenIM, with_xim=xlib, with_xim=no) dnl XIM + Lesstif is not (yet?) usable dnl Only use Motif if linking Motif anyway, or don't have xlib XIM --- 4473,4489 ---- wnn_libs= if test "$enable_mule" = "yes" ; then ! AC_MSG_CHECKING([for Mule-related features]) AC_DEFINE(MULE) dnl Use -lintl to get internationalized strerror for Mule AC_CHECK_HEADERS(libintl.h) AC_CHECK_LIB(intl, strerror) ! AC_MSG_CHECKING([for Mule input methods]) dnl Do we have the XmIm* routines? And if so, do we want to use them? case "$with_xim" in "" | "yes" ) ! AC_MSG_CHECKING([for XIM]) AC_CHECK_LIB(X11, XOpenIM, with_xim=xlib, with_xim=no) dnl XIM + Lesstif is not (yet?) usable dnl Only use Motif if linking Motif anyway, or don't have xlib XIM *************** *** 4503,4509 **** dnl "with_xfs" = "yes" if test "$with_xfs" = "yes" ; then ! AC_CHECKING([for XFontSet]) AC_CHECK_LIB(X11, XmbDrawString, [:], with_xfs=no) if test "$with_xfs" = "yes" && test "$enable_menubars" = "lucid"; then AC_DEFINE(USE_XFONTSET) --- 4513,4519 ---- dnl "with_xfs" = "yes" if test "$with_xfs" = "yes" ; then ! AC_MSG_CHECKING([for XFontSet]) AC_CHECK_LIB(X11, XmbDrawString, [:], with_xfs=no) if test "$with_xfs" = "yes" && test "$enable_menubars" = "lucid"; then AC_DEFINE(USE_XFONTSET) *************** *** 4713,4727 **** dnl If netdb.h does not declare h_errno, we must declare it by hand. AC_MSG_CHECKING(whether netdb declares h_errno) ! AC_TRY_LINK([#include ], ! [return h_errno;], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_H_ERRNO)], [AC_MSG_RESULT(no)]) AC_MSG_CHECKING(for sigsetjmp) ! AC_TRY_COMPILE([#include ], ! [sigjmp_buf bar; sigsetjmp (bar, 0);], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_SIGSETJMP)], [AC_MSG_RESULT(no)]) --- 4723,4737 ---- dnl If netdb.h does not declare h_errno, we must declare it by hand. AC_MSG_CHECKING(whether netdb declares h_errno) ! AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ! [return h_errno;])], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_H_ERRNO)], [AC_MSG_RESULT(no)]) AC_MSG_CHECKING(for sigsetjmp) ! AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], ! [sigjmp_buf bar; sigsetjmp (bar, 0);])], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_SIGSETJMP)], [AC_MSG_RESULT(no)]) *************** *** 4775,4781 **** if test "$HAVE_TIMEVAL" = "yes"; then AC_MSG_CHECKING(whether gettimeofday accepts one or two arguments) ! AC_TRY_LINK([ #ifdef TIME_WITH_SYS_TIME #include #include --- 4785,4791 ---- if test "$HAVE_TIMEVAL" = "yes"; then AC_MSG_CHECKING(whether gettimeofday accepts one or two arguments) ! AC_LINK_IFELSE([AC_LANG_PROGRAM([ #ifdef TIME_WITH_SYS_TIME #include #include *************** *** 4790,4796 **** [ struct timeval time; gettimeofday (&time, 0); ! ], [AC_MSG_RESULT(two)], [AC_MSG_RESULT(one) AC_DEFINE(GETTIMEOFDAY_ONE_ARGUMENT)]) --- 4800,4806 ---- [ struct timeval time; gettimeofday (&time, 0); ! ])], [AC_MSG_RESULT(two)], [AC_MSG_RESULT(one) AC_DEFINE(GETTIMEOFDAY_ONE_ARGUMENT)]) *************** *** 4802,4809 **** dnl check for the typeof extension AC_MSG_CHECKING(for typeof) ! AC_TRY_COMPILE(, [int i; __typeof__(i) j;], typeofname="__typeof__", ! [AC_TRY_COMPILE(, [int i; typeof(i) j;], typeofname="typeof", typeofname=no)]) AC_MSG_RESULT($typeofname) if test "$typeofname" != "no"; then --- 4812,4821 ---- dnl check for the typeof extension AC_MSG_CHECKING(for typeof) ! AC_COMPILE_IFELSE([AC_LANG_SOURCE([int i; __typeof__(i) j;])], ! typeofname="__typeof__", ! [AC_COMPILE_IFELSE([AC_LANG_SOURCE([int i; typeof(i) j;])], ! typeofname="typeof", typeofname=no)]) AC_MSG_RESULT($typeofname) if test "$typeofname" != "no"; then *************** *** 4952,4963 **** if test "$doug_lea_malloc" = "yes"; then dnl Check if malloc() calls mmap(), making rel_alloc pointless. AC_MSG_CHECKING(for M_MMAP_THRESHOLD) ! AC_TRY_COMPILE([#include ],[ #ifndef M_MMAP_THRESHOLD #error No M_MMAP_THRESHOLD :-( !@+$%^&*_)(_ - unlikely to compile... #endif ! ], [with_rel_alloc=no; AC_MSG_RESULT(yes);], [with_rel_alloc=yes; AC_MSG_RESULT(no);]) else with_rel_alloc=yes fi --- 4964,4976 ---- if test "$doug_lea_malloc" = "yes"; then dnl Check if malloc() calls mmap(), making rel_alloc pointless. AC_MSG_CHECKING(for M_MMAP_THRESHOLD) ! AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ],[ #ifndef M_MMAP_THRESHOLD #error No M_MMAP_THRESHOLD :-( !@+$%^&*_)(_ - unlikely to compile... #endif ! ])], [with_rel_alloc=no; AC_MSG_RESULT(yes);], ! [with_rel_alloc=yes; AC_MSG_RESULT(no);]) else with_rel_alloc=yes fi *************** *** 4978,4998 **** [AC_CHECK_HEADER(netinet/in.h, [AC_CHECK_HEADER(arpa/inet.h, [ AC_DEFINE(HAVE_SOCKETS) ! AC_MSG_CHECKING("for sun_len member in struct sockaddr_un") ! AC_TRY_LINK([ #include #include #include ], ! [static struct sockaddr_un x; x.sun_len = 1;], [AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SOCKADDR_SUN_LEN)], [AC_MSG_RESULT(no)]) ! AC_MSG_CHECKING("for ip_mreq struct in netinet/in.h") ! AC_TRY_LINK([ #include #include ], ! [static struct ip_mreq x;], [AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MULTICAST)], [AC_MSG_RESULT(no)])])])]) --- 4991,5011 ---- [AC_CHECK_HEADER(netinet/in.h, [AC_CHECK_HEADER(arpa/inet.h, [ AC_DEFINE(HAVE_SOCKETS) ! AC_MSG_CHECKING([for sun_len member in struct sockaddr_un]) ! AC_LINK_IFELSE([AC_LANG_PROGRAM([ #include #include #include ], ! [static struct sockaddr_un x; x.sun_len = 1;])], [AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SOCKADDR_SUN_LEN)], [AC_MSG_RESULT(no)]) ! AC_MSG_CHECKING([for ip_mreq struct in netinet/in.h]) ! AC_LINK_IFELSE([AC_LANG_PROGRAM([ #include #include ], ! [static struct ip_mreq x;])], [AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MULTICAST)], [AC_MSG_RESULT(no)])])])]) *************** *** 5010,5018 **** AC_CHECK_HEADER(nlist.h, AC_DEFINE(NLIST_STRUCT), ) dnl Check for sound of various sorts. dnl Autodetect native sound - AC_CHECKING([for sound support]) test -n "$with_native_sound_lib" && enable_sound_native=yes if test "$enable_sound_native" != "no"; then --- 5023,5032 ---- AC_CHECK_HEADER(nlist.h, AC_DEFINE(NLIST_STRUCT), ) dnl Check for sound of various sorts. + AC_MSG_CHECKING([for sound support]) + AC_MSG_RESULT() dnl Autodetect native sound test -n "$with_native_sound_lib" && enable_sound_native=yes if test "$enable_sound_native" != "no"; then *************** *** 5131,5136 **** --- 5145,5166 ---- test -n "$with_native_sound_lib" && XE_PREPEND($with_native_sound_lib, LIBS) fi + dnl ALSA sound support + if test "$enable_sound_alsa" != "no"; then + AC_CHECK_HEADER([alsa/input.h], [ + AC_CHECK_LIB(asound, snd_pcm_open, have_alsa_sound=yes)]) + if test "$have_alsa_sound" = "yes"; then + enable_sound_alsa=yes + AC_DEFINE(HAVE_ALSA_SOUND) + XE_ADD_OBJS(alsaplay.o) + XE_PREPEND(-lasound, LIBS) + else + test "$enable_sound_alsa" = "yes" && \ + XE_DIE("Required ALSA sound support cannot be provided.") + enable_sound_alsa=no + fi + fi + dnl NAS Sound support if test "$enable_sound_nas" != "no"; then AC_CHECK_HEADER(audio/audiolib.h, [ *************** *** 5183,5189 **** test -z "$with_tty" && with_tty=yes if test "$with_tty" = "yes" ; then ! AC_CHECKING([for TTY-related features]) AC_DEFINE(HAVE_TTY) dnl Autodetect ncurses. --- 5213,5220 ---- test -z "$with_tty" && with_tty=yes if test "$with_tty" = "yes" ; then ! AC_MSG_CHECKING([for TTY-related features]) ! AC_MSG_RESULT() AC_DEFINE(HAVE_TTY) dnl Autodetect ncurses. *************** *** 5268,5274 **** dnl By default, we check for DBM support in libgdbm, then libc, then libdbm. test "$enable_database_gdbm $enable_database_dbm $enable_database_berkdb" \ ! != "no no no" && AC_CHECKING([for database support]) dnl Check for ndbm.h, required for either kind of DBM support. if test "$enable_database_gdbm $enable_database_dbm" != "no no"; then --- 5299,5306 ---- dnl By default, we check for DBM support in libgdbm, then libc, then libdbm. test "$enable_database_gdbm $enable_database_dbm $enable_database_berkdb" \ ! != "no no no" && AC_MSG_CHECKING([for database support]) && \ ! AC_MSG_RESULT() dnl Check for ndbm.h, required for either kind of DBM support. if test "$enable_database_gdbm $enable_database_dbm" != "no no"; then *************** *** 5308,5314 **** if test "$enable_database_berkdb" != "no"; then AC_MSG_CHECKING(for Berkeley db.h) for header in "db/db.h" "db.h"; do ! AC_TRY_COMPILE([ #include #if !(defined __GLIBC__ && __GLIBC_MINOR__ >= 1) #ifdef HAVE_INTTYPES_H --- 5340,5346 ---- if test "$enable_database_berkdb" != "no"; then AC_MSG_CHECKING(for Berkeley db.h) for header in "db/db.h" "db.h"; do ! AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #if !(defined __GLIBC__ && __GLIBC_MINOR__ >= 1) #ifdef HAVE_INTTYPES_H *************** *** 5323,5329 **** #endif #endif #include <$header> ! ],[], db_h_file="$header"; break) done if test -z "$db_h_file" then AC_MSG_RESULT(no); enable_database_berkdb=no --- 5355,5361 ---- #endif #endif #include <$header> ! ])], db_h_file="$header"; break) done if test -z "$db_h_file" then AC_MSG_RESULT(no); enable_database_berkdb=no *************** *** 5830,5836 **** test "$GCC" = "yes" && AC_DEFINE(USE_GCC) test "$enable_external_widget" = "yes" && AC_DEFINE(EXTERNAL_WIDGET) test "$enable_kkcc" = "yes" && AC_DEFINE(USE_KKCC) - test "$enable_mc_alloc" = "yes" && AC_DEFINE(MC_ALLOC) test "$enable_newgc" = "yes" && AC_DEFINE(NEW_GC) test "$have_vdb_posix" = "yes" && AC_DEFINE(VDB_POSIX) test "$have_vdb_fake" = "yes" && AC_DEFINE(VDB_FAKE) --- 5862,5867 ---- *************** *** 6058,6063 **** --- 6089,6095 ---- echo " Sound:" test "$enable_sound_native" = yes && echo " Compiling in support for sound (native)." + test "$enable_sound_alsa" = yes && echo " Compiling in support for ALSA (Advanced Linux Sound Architecture)." test "$enable_sound_nas" = yes && echo " Compiling in support for NAS (network audio system)." test "$old_nas" = yes && echo " - NAS library lacks error trapping; will play synchronously." test "$enable_sound_esd" = yes && echo " Compiling in support for ESD (Enlightened Sound Daemon)." *************** *** 6115,6136 **** echo " WARNING: ---------------------------------------------------------" fi if test "$enable_kkcc" = yes ; then ! echo " Using the new GC algorithms." echo " WARNING: ---------------------------------------------------------" echo " WARNING: The new algorithms are experimental. They are enabled by" echo " WARNING: default for this release. Use \`--disable-kkcc' to" echo " WARNING: turn it off." echo " WARNING: ---------------------------------------------------------" fi ! if test "$enable_mc_alloc" = yes ; then ! echo " Using the new allocator." ! echo " WARNING: ---------------------------------------------------------" ! echo " WARNING: The new allocator is experimental. It is enabled by" ! echo " WARNING: default for this release. Use \`--disable-mc-alloc' to" ! echo " WARNING: turn it off." ! echo " WARNING: ---------------------------------------------------------" ! fi ! test "$enable_newgc" = yes && echo " Using the new incremental garbage collector." if test "$have_vdb_posix" = yes ; then if test "$have_vdb_sigaction" = yes ; then echo " Using POSIX sigaction() to install fault handler." --- 6147,6160 ---- echo " WARNING: ---------------------------------------------------------" fi if test "$enable_kkcc" = yes ; then ! echo " Using the new GC mark algorithms (KKCC)." echo " WARNING: ---------------------------------------------------------" echo " WARNING: The new algorithms are experimental. They are enabled by" echo " WARNING: default for this release. Use \`--disable-kkcc' to" echo " WARNING: turn it off." echo " WARNING: ---------------------------------------------------------" fi ! test "$enable_newgc" = yes && echo " Using the new incremental garbage collector and the new allocator." if test "$have_vdb_posix" = yes ; then if test "$have_vdb_sigaction" = yes ; then echo " Using POSIX sigaction() to install fault handler." diff -c 'xemacs-21.5.25/etc/ChangeLog' 'xemacs-21.5.26/etc/ChangeLog' Index: ./etc/ChangeLog *** ./etc/ChangeLog Sun Feb 26 22:14:12 2006 --- ./etc/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,7 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. diff -c 'xemacs-21.5.25/info/internals.info' 'xemacs-21.5.26/info/internals.info' Index: ./info/internals.info *** ./info/internals.info Sun Feb 26 22:31:24 2006 --- ./info/internals.info Sat Apr 1 04:05:23 2006 *************** *** 48,350 ****  Indirect: internals.info-1: 2060 ! internals.info-2: 298225 ! internals.info-3: 596419 ! internals.info-4: 889791 ! internals.info-5: 1172181  Tag Table: (Indirect) Node: Top2060 ! Node: Introduction12842 ! Node: Authorship of XEmacs17539 ! Node: A History of Emacs22958 ! Node: Through Version 1825444 ! Node: Epoch33499 ! Node: Lucid Emacs33946 ! Node: GNU Emacs 1936926 ! Node: GNU Emacs 2039473 ! Node: XEmacs40293 ! Node: The XEmacs Split55506 ! Node: XEmacs from the Outside67918 ! Node: The Lisp Language69684 ! Node: XEmacs from the Perspective of Building79228 ! Node: Build-Time Dependencies85670 ! Node: The Modules of XEmacs88353 ! Node: A Summary of the Various XEmacs Modules88887 ! Node: Modules for Building XEmacs114716 ! Node: Modules for Build Configuration115054 ! Node: Modules for Compiling XEmacs115486 ! Node: Modules for Preloading Lisp115874 ! Node: Low-Level Modules116257 ! Node: Basic Lisp Modules120616 ! Node: Modules for Standard Editing Operations127236 ! Node: Modules for Interfacing with the File System133159 ! Node: Modules for Other Aspects of the Lisp Interpreter and Object System136867 ! Node: Modules for Interfacing with the Operating System144902 ! Node: The Build Configuration System152465 ! Node: The version.sh Script153015 ! Node: Adding Configurable Features157310 ! Node: The configure Script158136 ! Node: The Makefile Precursors172391 ! Node: Rules When Writing New C Code173400 ! Node: Introduction to Writing C Code174361 ! Node: Writing New Modules178807 ! Node: Working with Lisp Objects183866 ! Node: Writing Lisp Primitives194779 ! Node: Writing Good Comments205933 ! Node: Adding Global Lisp Variables209554 ! Node: Writing Macros213478 ! Node: Proper Use of Unsigned Types219427 ! Node: Major Textual Changes220675 ! Node: Great Integral Type Renaming221409 ! Node: Text/Char Type Renaming230188 ! Node: Debugging and Testing233596 ! Node: Regression Testing XEmacs237335 ! Node: How to Regression-Test237595 ! Node: Modules for Regression Testing246837 ! Node: CVS Techniques247633 ! Node: Creating a Branch247860 ! Node: Merging a Branch into the Trunk251029 ! Node: XEmacs from the Inside254678 ! Node: Basic Types262998 ! Node: Low-Level Allocation263164 ! Node: Basic Heap Allocation263479 ! Node: Stack Allocation263669 ! Node: Dynamic Arrays263843 ! Node: Allocation by Blocks268503 ! Node: Modules for Allocation270204 ! Node: The XEmacs Object System (Abstractly Speaking)273346 ! Node: How Lisp Objects Are Represented in C287988 ! Node: Allocation of Objects in XEmacs Lisp292822 ! Node: Introduction to Allocation293368 ! Node: Garbage Collection297061 ! Node: GCPROing298225 ! Node: Garbage Collection - Step by Step306180 ! Node: Invocation306582 ! Node: garbage_collect_1309606 ! Node: mark_object319099 ! Node: gc_sweep320922 ! Node: sweep_lcrecords_1325997 ! Node: compact_string_chars327003 ! Node: sweep_strings329194 ! Node: sweep_bit_vectors_1330170 ! Node: Integers and Characters330857 ! Node: Allocation from Frob Blocks331616 ! Node: lrecords333227 ! Node: Low-level allocation345460 ! Node: Cons349574 ! Node: Vector350307 ! Node: Bit Vector350894 ! Node: Symbol351396 ! Node: Marker351759 ! Node: String352323 ! Node: Compiled Function355944 ! Node: The Lisp Reader and Compiler356122 ! Node: Evaluation; Stack Frames; Bindings356367 ! Node: Evaluation356737 ! Node: Dynamic Binding; The specbinding Stack; Unwind-Protects363299 ! Node: Simple Special Forms365693 ! Node: Catch and Throw366483 ! Node: Error Trapping369091 ! Node: Symbols and Variables375914 ! Node: Introduction to Symbols376157 ! Node: Obarrays377232 ! Node: Symbol Values380772 ! Node: Buffers383067 ! Node: Introduction to Buffers383476 ! Node: Buffer Lists386127 ! Node: Markers and Extents388061 ! Node: The Buffer Object390306 ! Node: Text393763 ! Node: The Text in a Buffer394118 ! Node: Ibytes and Ichars401225 ! Node: Byte-Char Position Conversion401421 ! Node: Searching and Matching409492 ! Node: Multilingual Support416748 ! Node: Introduction to Multilingual Issues #1418644 ! Node: Introduction to Multilingual Issues #2419222 ! Node: Introduction to Multilingual Issues #3437282 ! Node: Introduction to Multilingual Issues #4454070 ! Node: Character Sets454483 ! Node: Encodings457969 ! Node: Japanese EUC (Extended Unix Code)459030 ! Node: JIS7460111 ! Node: Internal Mule Encodings461427 ! Node: Internal String Encoding463422 ! Node: Internal Character Encoding465579 ! Node: Byte/Character Types; Buffer Positions; Other Typedefs467868 ! Node: Byte Types468356 ! Node: Different Ways of Seeing Internal Text470805 ! Node: Buffer Positions478830 ! Node: Other Typedefs480777 ! Node: Usage of the Various Representations481527 ! Node: Working With the Various Representations483277 ! Node: Internal Text APIs483750 ! Node: Basic internal-format APIs484179 ! Node: The DFC API485642 ! Node: The Eistring API497132 ! Node: Coding for Mule519794 ! Node: Character-Related Data Types520754 ! Node: Working With Character and Byte Positions525419 ! Node: Conversion to and from External Data529414 ! Node: General Guidelines for Writing Mule-Aware Code537971 ! Node: An Example of Mule-Aware Code541429 ! Node: Mule-izing Code543426 ! Node: CCL544454 ! Node: Microsoft Windows-Related Multilingual Issues549552 ! Node: Microsoft Documentation550077 ! Node: Locales552354 ! Node: More about code pages558402 ! Node: More about locales563936 ! Node: Unicode support under Windows565368 ! Node: The golden rules of writing Unicode-safe code577617 ! Node: The format of the locale in setlocale()579351 ! Node: Random other Windows I18N docs585306 ! Node: Modules for Internationalization593103 ! Node: Consoles; Devices; Frames; Windows596035 ! Node: Introduction to Consoles; Devices; Frames; Windows596419 ! Node: Point598959 ! Node: Window Hierarchy600245 ! Node: The Window Object604704 ! Node: Modules for the Basic Displayable Lisp Objects608203 ! Node: The Redisplay Mechanism614038 ! Node: Critical Redisplay Sections614924 ! Node: Line Start Cache637782 ! Node: Redisplay Piece by Piece641025 ! Node: Modules for the Redisplay Mechanism643113 ! Node: Modules for other Display-Related Lisp Objects645483 ! Node: Extents646841 ! Node: Introduction to Extents647381 ! Node: Extent Ordering648530 ! Node: Format of the Extent Info649778 ! Node: Zero-Length Extents652767 ! Node: Mathematics of Extent Ordering654173 ! Node: Extent Fragments658585 ! Node: Faces659678 ! Node: Glyphs659797 ! Node: Specifiers666464 ! Node: Menus666758 ! Node: Events and the Event Loop669032 ! Node: Introduction to Events669573 ! Node: Main Loop671529 ! Node: Specifics of the Event Gathering Mechanism675111 ! Node: Specifics About the Emacs Event687612 ! Node: Event Queues687855 ! Node: Event Stream Callback Routines690767 ! Node: Other Event Loop Functions696166 ! Node: Stream Pairs697304 ! Node: Converting Events699865 ! Node: Dispatching Events; The Command Builder700467 ! Node: Focus Handling700734 ! Node: Editor-Level Control Flow Modules704763 ! Node: Asynchronous Events; Quit Checking708222 ! Node: Signal Handling708539 ! Node: Control-G (Quit) Checking708748 ! Node: Profiling729256 ! Node: Asynchronous Timeouts733472 ! Node: Exiting733656 ! Node: Lstreams736111 ! Node: Creating an Lstream737129 ! Node: Lstream Types738363 ! Node: Lstream Functions738626 ! Node: Lstream Methods742230 ! Node: Subprocesses745400 ! Node: Interface to MS Windows747383 ! Node: Different kinds of Windows environments747718 ! Node: Windows Build Flags761494 ! Node: Windows I18N Introduction763447 ! Node: Modules for Interfacing with MS Windows773108 ! Node: Interface to the X Window System775156 ! Node: Lucid Widget Library775496 ! Node: Generic Widget Interface776882 ! Node: Scrollbars780471 ! Node: Menubars780628 ! Node: Checkboxes and Radio Buttons780785 ! Node: Progress Bars780985 ! Node: Tab Controls781159 ! Node: Modules for Interfacing with X Windows781294 ! Node: Dumping784710 ! Node: Dumping Justification784974 ! Node: Overview787025 ! Node: Data descriptions787756 ! Node: Dumping phase789828 ! Node: Object inventory790244 ! Node: Address allocation794367 ! Node: The header795767 ! Node: Data dumping796223 ! Node: Pointers dumping796895 ! Node: Reloading phase798294 ! Node: Remaining issues799920 ! Node: Future Work800953 ! Node: Future Work -- General Suggestions802084 ! Node: Future Work -- Elisp Compatibility Package823328 ! Node: Future Work -- Drag-n-Drop831361 ! Node: Future Work -- Standard Interface for Enabling Extensions838567 ! Node: Future Work -- Better Initialization File Scheme843430 ! Node: Future Work -- Keyword Parameters853398 ! Node: Future Work -- Property Interface Changes861149 ! Node: Future Work -- Toolbars865117 ! Node: Future Work -- Easier Toolbar Customization865441 ! Node: Future Work -- Toolbar Interface Changes868792 ! Node: Future Work -- Menu API Changes877594 ! Node: Future Work -- Removal of Misc-User Event Type880632 ! Node: Future Work -- Mouse Pointer882879 ! Node: Future Work -- Abstracted Mouse Pointer Interface883209 ! Node: Future Work -- Busy Pointer885002 ! Node: Future Work -- Extents887340 ! Node: Future Work -- Everything should obey duplicable extents887650 ! Node: Future Work -- Version Number and Development Tree Organization889791 ! Node: Future Work -- Improvements to the `xemacs.org' Website905929 ! Node: Future Work -- Keybindings911602 ! Node: Future Work -- Keybinding Schemes912005 ! Node: Future Work -- Better Support for Windows Style Key Bindings913110 ! Node: Future Work -- Misc Key Binding Ideas917433 ! Node: Future Work -- Byte Code Snippets918901 ! Node: Future Work -- Autodetection919979 ! Node: Future Work -- Conversion Error Detection958048 ! Node: Future Work -- Unicode968947 ! Node: Future Work -- BIDI Support973937 ! Node: Future Work -- Localized Text/Messages975462 ! Node: Future Work -- Lisp Stream API988915 ! Node: Future Work -- Multiple Values999834 ! Node: Future Work -- Macros1001723 ! Node: Future Work -- Specifiers1002487 ! Node: Future Work -- Display Tables1009507 ! Node: Future Work -- Making Elisp Function Calls Faster1011417 ! Node: Future Work -- Lisp Engine Replacement1022293 ! Node: Future Work -- Lisp Engine Discussion1022747 ! Node: Future Work -- Lisp Engine Replacement -- Implementation1031799 ! Node: Future Work -- Startup File Modification by Packages1052041 ! Node: Future Work -- Better Rendering Support1055160 ! Node: Better Rendering Support -- Review Criteria1057004 ! Node: Better Rendering Support -- Implementation1059090 ! Node: Better Rendering Support -- Current Status1069283 ! Node: Better Rendering Support -- Configuration with the Interim Patches1071294 ! Node: Better Rendering Support -- Modern Font Support1074923 ! Node: Modern Font Support -- Font Concepts1077065 ! Node: Modern Font Support -- fontconfig1082198 ! Node: Modern Font Support -- Xft1094116 ! Node: Future Work Discussion1094427 ! Node: Discussion -- Garbage Collection1095187 ! Node: Discussion -- Pure Space1095541 ! Node: Discussion -- Hashtable-Based Marking and Cleanup1098845 ! Node: Discussion -- The Anti-Cons1101483 ! Node: Discussion -- Glyphs1105425 ! Node: Discussion -- Dialog Boxes1114359 ! Node: Discussion -- Multilingual Issues1134224 ! Node: Discussion -- Instantiators and Generic Property Accessors1172181 ! Node: Discussion -- Switching to C++1194866 ! Node: Discussion -- Windows External Widget1209746 ! Node: Discussion -- Packages1217130 ! Node: Discussion -- Distribution Layout1218849 ! Node: Old Future Work1232544 ! Node: Old Future Work -- A Portable Unexec Replacement1233354 ! Node: Old Future Work -- Indirect Buffers1239129 ! Node: Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X1244118 ! Node: Old Future Work -- RTF Clipboard Support1245939 ! Node: Old Future Work -- xemacs.org Mailing Address Changes1248025 ! Node: Old Future Work -- Lisp callbacks from critical areas of the C code1252439 ! Node: Index1258320  End Tag Table --- 48,365 ----  Indirect: internals.info-1: 2060 ! internals.info-2: 298914 ! internals.info-3: 598211 ! internals.info-4: 896008 ! internals.info-5: 1194044  Tag Table: (Indirect) Node: Top2060 ! Node: Introduction13531 ! Node: Authorship of XEmacs18228 ! Node: A History of Emacs23647 ! Node: Through Version 1826133 ! Node: Epoch34188 ! Node: Lucid Emacs34635 ! Node: GNU Emacs 1937615 ! Node: GNU Emacs 2040162 ! Node: XEmacs40982 ! Node: The XEmacs Split56195 ! Node: XEmacs from the Outside68607 ! Node: The Lisp Language70373 ! Node: XEmacs from the Perspective of Building79917 ! Node: Build-Time Dependencies86359 ! Node: The Modules of XEmacs89042 ! Node: A Summary of the Various XEmacs Modules89576 ! Node: Modules for Building XEmacs115405 ! Node: Modules for Build Configuration115743 ! Node: Modules for Compiling XEmacs116175 ! Node: Modules for Preloading Lisp116563 ! Node: Low-Level Modules116946 ! Node: Basic Lisp Modules121305 ! Node: Modules for Standard Editing Operations127925 ! Node: Modules for Interfacing with the File System133848 ! Node: Modules for Other Aspects of the Lisp Interpreter and Object System137556 ! Node: Modules for Interfacing with the Operating System145591 ! Node: The Build Configuration System153154 ! Node: The version.sh Script153704 ! Node: Adding Configurable Features157999 ! Node: The configure Script158825 ! Node: The Makefile Precursors173080 ! Node: Rules When Writing New C Code174089 ! Node: Introduction to Writing C Code175050 ! Node: Writing New Modules179496 ! Node: Working with Lisp Objects184555 ! Node: Writing Lisp Primitives195468 ! Node: Writing Good Comments206622 ! Node: Adding Global Lisp Variables210243 ! Node: Writing Macros214167 ! Node: Proper Use of Unsigned Types220116 ! Node: Major Textual Changes221364 ! Node: Great Integral Type Renaming222098 ! Node: Text/Char Type Renaming230877 ! Node: Debugging and Testing234285 ! Node: Regression Testing XEmacs238024 ! Node: How to Regression-Test238284 ! Node: Modules for Regression Testing247526 ! Node: CVS Techniques248322 ! Node: Creating a Branch248549 ! Node: Merging a Branch into the Trunk251718 ! Node: XEmacs from the Inside255367 ! Node: Basic Types263687 ! Node: Low-Level Allocation263853 ! Node: Basic Heap Allocation264168 ! Node: Stack Allocation264358 ! Node: Dynamic Arrays264532 ! Node: Allocation by Blocks269192 ! Node: Modules for Allocation270893 ! Node: The XEmacs Object System (Abstractly Speaking)274035 ! Node: How Lisp Objects Are Represented in C288677 ! Node: Allocation of Objects in XEmacs Lisp293511 ! Node: Introduction to Allocation294057 ! Node: Garbage Collection297750 ! Node: GCPROing298914 ! Node: Garbage Collection - Step by Step306869 ! Node: Invocation307271 ! Node: garbage_collect_1310295 ! Node: mark_object319788 ! Node: gc_sweep321611 ! Node: sweep_lcrecords_1326686 ! Node: compact_string_chars327692 ! Node: sweep_strings329883 ! Node: sweep_bit_vectors_1330859 ! Node: Integers and Characters331546 ! Node: Allocation from Frob Blocks332305 ! Node: lrecords333916 ! Node: Low-level allocation346149 ! Node: Cons350263 ! Node: Vector350996 ! Node: Bit Vector351583 ! Node: Symbol352085 ! Node: Marker352448 ! Node: String353012 ! Node: Compiled Function356633 ! Node: The Lisp Reader and Compiler356811 ! Node: Evaluation; Stack Frames; Bindings357056 ! Node: Evaluation357426 ! Node: Dynamic Binding; The specbinding Stack; Unwind-Protects363988 ! Node: Simple Special Forms366382 ! Node: Catch and Throw367172 ! Node: Error Trapping369780 ! Node: Symbols and Variables376603 ! Node: Introduction to Symbols376846 ! Node: Obarrays377921 ! Node: Symbol Values381461 ! Node: Buffers383756 ! Node: Introduction to Buffers384165 ! Node: Buffer Lists386816 ! Node: Markers and Extents388750 ! Node: The Buffer Object390995 ! Node: Text394452 ! Node: The Text in a Buffer394807 ! Node: Ibytes and Ichars401914 ! Node: Byte-Char Position Conversion402110 ! Node: Searching and Matching410181 ! Node: Multilingual Support417437 ! Node: Introduction to Multilingual Issues #1419372 ! Node: Introduction to Multilingual Issues #2419950 ! Node: Introduction to Multilingual Issues #3438010 ! Node: Introduction to Multilingual Issues #4454798 ! Node: Character Sets455211 ! Node: Encodings458697 ! Node: Japanese EUC (Extended Unix Code)459758 ! Node: JIS7460839 ! Node: Internal Mule Encodings462155 ! Node: Internal String Encoding464150 ! Node: Internal Character Encoding466307 ! Node: Byte/Character Types; Buffer Positions; Other Typedefs468596 ! Node: Byte Types469084 ! Node: Different Ways of Seeing Internal Text471533 ! Node: Buffer Positions479558 ! Node: Other Typedefs481505 ! Node: Usage of the Various Representations482255 ! Node: Working With the Various Representations484005 ! Node: Internal Text APIs484478 ! Node: Basic internal-format APIs484907 ! Node: The DFC API486370 ! Node: The Eistring API497860 ! Node: Coding for Mule520522 ! Node: Character-Related Data Types521482 ! Node: Working With Character and Byte Positions526147 ! Node: Conversion to and from External Data530142 ! Node: General Guidelines for Writing Mule-Aware Code538699 ! Node: An Example of Mule-Aware Code542157 ! Node: Mule-izing Code544154 ! Node: CCL545182 ! Node: Microsoft Windows-Related Multilingual Issues550280 ! Node: Microsoft Documentation550805 ! Node: Locales553082 ! Node: More about code pages559130 ! Node: More about locales564664 ! Node: Unicode support under Windows566096 ! Node: The golden rules of writing Unicode-safe code578345 ! Node: The format of the locale in setlocale()580079 ! Node: Random other Windows I18N docs586034 ! Node: Modules for Internationalization593831 ! Node: The Great Mule Merge of March 2002596806 ! Node: List of changed files in new Mule workspace598211 ! Node: Changes to the MULE subsystems600244 ! Node: Pervasive changes throughout XEmacs sources601734 ! Node: Changes to specific subsystems603053 ! Node: Mule changes by theme603830 ! Node: File-coding rewrite613631 ! Node: General User-Visible Changes615609 ! Node: General Lisp-Visible Changes618648 ! Node: User documentation619400 ! Node: General internal changes620562 ! Node: Ben's TODO list625610 ! Node: Ben's README632861 ! Node: Consoles; Devices; Frames; Windows715686 ! Node: Introduction to Consoles; Devices; Frames; Windows716070 ! Node: Point718610 ! Node: Window Hierarchy719896 ! Node: The Window Object724355 ! Node: Modules for the Basic Displayable Lisp Objects727854 ! Node: The Redisplay Mechanism733689 ! Node: Critical Redisplay Sections734575 ! Node: Line Start Cache757433 ! Node: Redisplay Piece by Piece760676 ! Node: Modules for the Redisplay Mechanism762764 ! Node: Modules for other Display-Related Lisp Objects765134 ! Node: Extents766492 ! Node: Introduction to Extents767032 ! Node: Extent Ordering768181 ! Node: Format of the Extent Info769429 ! Node: Zero-Length Extents772418 ! Node: Mathematics of Extent Ordering773824 ! Node: Extent Fragments778236 ! Node: Faces779329 ! Node: Glyphs779448 ! Node: Specifiers786115 ! Node: Menus786409 ! Node: Events and the Event Loop788683 ! Node: Introduction to Events789224 ! Node: Main Loop791180 ! Node: Specifics of the Event Gathering Mechanism794762 ! Node: Specifics About the Emacs Event807263 ! Node: Event Queues807506 ! Node: Event Stream Callback Routines810418 ! Node: Other Event Loop Functions815817 ! Node: Stream Pairs816955 ! Node: Converting Events819516 ! Node: Dispatching Events; The Command Builder820118 ! Node: Focus Handling820385 ! Node: Editor-Level Control Flow Modules824414 ! Node: Asynchronous Events; Quit Checking827873 ! Node: Signal Handling828190 ! Node: Control-G (Quit) Checking828399 ! Node: Profiling848907 ! Node: Asynchronous Timeouts853123 ! Node: Exiting853307 ! Node: Lstreams855762 ! Node: Creating an Lstream856780 ! Node: Lstream Types858014 ! Node: Lstream Functions858277 ! Node: Lstream Methods861881 ! Node: Subprocesses865051 ! Node: Ben's separate stderr notes867110 ! Node: Interface to MS Windows868121 ! Node: Different kinds of Windows environments868529 ! Node: Windows Build Flags882305 ! Node: Windows I18N Introduction884258 ! Node: Modules for Interfacing with MS Windows893919 ! Node: CHANGES from 21.4-windows branch896008 ! Node: Interface to the X Window System899917 ! Node: Lucid Widget Library900257 ! Node: Generic Widget Interface901643 ! Node: Scrollbars905232 ! Node: Menubars905389 ! Node: Checkboxes and Radio Buttons905546 ! Node: Progress Bars905746 ! Node: Tab Controls905920 ! Node: Modules for Interfacing with X Windows906055 ! Node: Dumping909471 ! Node: Dumping Justification909735 ! Node: Overview911786 ! Node: Data descriptions912517 ! Node: Dumping phase914589 ! Node: Object inventory915005 ! Node: Address allocation919128 ! Node: The header920528 ! Node: Data dumping920984 ! Node: Pointers dumping921656 ! Node: Reloading phase923055 ! Node: Remaining issues924681 ! Node: Future Work925714 ! Node: Future Work -- General Suggestions926845 ! Node: Future Work -- Elisp Compatibility Package948089 ! Node: Future Work -- Drag-n-Drop956122 ! Node: Future Work -- Standard Interface for Enabling Extensions963328 ! Node: Future Work -- Better Initialization File Scheme968191 ! Node: Future Work -- Keyword Parameters978159 ! Node: Future Work -- Property Interface Changes985910 ! Node: Future Work -- Toolbars989878 ! Node: Future Work -- Easier Toolbar Customization990202 ! Node: Future Work -- Toolbar Interface Changes993553 ! Node: Future Work -- Menu API Changes1002355 ! Node: Future Work -- Removal of Misc-User Event Type1005393 ! Node: Future Work -- Mouse Pointer1007640 ! Node: Future Work -- Abstracted Mouse Pointer Interface1007970 ! Node: Future Work -- Busy Pointer1009763 ! Node: Future Work -- Extents1012101 ! Node: Future Work -- Everything should obey duplicable extents1012411 ! Node: Future Work -- Version Number and Development Tree Organization1014552 ! Node: Future Work -- Improvements to the `xemacs.org' Website1030690 ! Node: Future Work -- Keybindings1036363 ! Node: Future Work -- Keybinding Schemes1036766 ! Node: Future Work -- Better Support for Windows Style Key Bindings1037871 ! Node: Future Work -- Misc Key Binding Ideas1042194 ! Node: Future Work -- Byte Code Snippets1043662 ! Node: Future Work -- Autodetection1044740 ! Node: Future Work -- Conversion Error Detection1082809 ! Node: Future Work -- Unicode1093708 ! Node: Future Work -- BIDI Support1098698 ! Node: Future Work -- Localized Text/Messages1100223 ! Node: Future Work -- Lisp Stream API1113676 ! Node: Future Work -- Multiple Values1124595 ! Node: Future Work -- Macros1126484 ! Node: Future Work -- Specifiers1127248 ! Node: Future Work -- Display Tables1134268 ! Node: Future Work -- Making Elisp Function Calls Faster1136178 ! Node: Future Work -- Lisp Engine Replacement1147054 ! Node: Future Work -- Lisp Engine Discussion1147508 ! Node: Future Work -- Lisp Engine Replacement -- Implementation1156560 ! Node: Future Work -- Startup File Modification by Packages1176802 ! Node: Future Work -- Better Rendering Support1179921 ! Node: Better Rendering Support -- Review Criteria1181765 ! Node: Better Rendering Support -- Implementation1183851 ! Node: Better Rendering Support -- Current Status1194044 ! Node: Better Rendering Support -- Configuration with the Interim Patches1196055 ! Node: Better Rendering Support -- Modern Font Support1199684 ! Node: Modern Font Support -- Font Concepts1201826 ! Node: Modern Font Support -- fontconfig1206959 ! Node: Modern Font Support -- Xft1218877 ! Node: Future Work Discussion1219188 ! Node: Discussion -- Garbage Collection1219948 ! Node: Discussion -- Pure Space1220302 ! Node: Discussion -- Hashtable-Based Marking and Cleanup1223606 ! Node: Discussion -- The Anti-Cons1226244 ! Node: Discussion -- Glyphs1230186 ! Node: Discussion -- Dialog Boxes1239120 ! Node: Discussion -- Multilingual Issues1258985 ! Node: Discussion -- Instantiators and Generic Property Accessors1296942 ! Node: Discussion -- Switching to C++1319627 ! Node: Discussion -- Windows External Widget1334507 ! Node: Discussion -- Packages1341891 ! Node: Discussion -- Distribution Layout1343610 ! Node: Old Future Work1357305 ! Node: Old Future Work -- A Portable Unexec Replacement1358115 ! Node: Old Future Work -- Indirect Buffers1363890 ! Node: Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X1368879 ! Node: Old Future Work -- RTF Clipboard Support1370700 ! Node: Old Future Work -- xemacs.org Mailing Address Changes1372786 ! Node: Old Future Work -- Lisp callbacks from critical areas of the C code1377200 ! Node: Index1383081  End Tag Table diff -c 'xemacs-21.5.25/info/internals.info-1' 'xemacs-21.5.26/info/internals.info-1' Index: ./info/internals.info-1 *** ./info/internals.info-1 Sun Feb 26 22:31:24 2006 --- ./info/internals.info-1 Sat Apr 1 04:05:23 2006 *************** *** 226,231 **** --- 226,232 ---- * CCL:: * Microsoft Windows-Related Multilingual Issues:: * Modules for Internationalization:: + * The Great Mule Merge of March 2002:: Encodings *************** *** 272,277 **** --- 273,293 ---- * The format of the locale in setlocale():: * Random other Windows I18N docs:: + The Great Mule Merge of March 2002 + + * List of changed files in new Mule workspace:: + * Changes to the MULE subsystems:: + * Pervasive changes throughout XEmacs sources:: + * Changes to specific subsystems:: + * Mule changes by theme:: + * File-coding rewrite:: + * General User-Visible Changes:: + * General Lisp-Visible Changes:: + * User documentation:: + * General internal changes:: + * Ben's TODO list:: Probably obsolete. + * Ben's README:: Probably obsolete. + Consoles; Devices; Frames; Windows * Introduction to Consoles; Devices; Frames; Windows:: *************** *** 327,338 **** --- 343,359 ---- * Lstream Functions:: Functions for working with lstreams. * Lstream Methods:: Creating new lstream types. + Subprocesses + + * Ben's separate stderr notes:: Probably obsolete. + Interface to MS Windows * Different kinds of Windows environments:: * Windows Build Flags:: * Windows I18N Introduction:: * Modules for Interfacing with MS Windows:: + * CHANGES from 21.4-windows branch:: Probably obsolete. Interface to the X Window System diff -c 'xemacs-21.5.25/info/internals.info-2' 'xemacs-21.5.26/info/internals.info-2' Index: ./info/internals.info-2 *** ./info/internals.info-2 Sun Feb 26 22:31:24 2006 --- ./info/internals.info-2 Sat Apr 1 04:05:23 2006 *************** *** 2532,2537 **** --- 2532,2538 ---- * CCL:: * Microsoft Windows-Related Multilingual Issues:: * Modules for Internationalization:: + * The Great Mule Merge of March 2002::  File: internals.info, Node: Introduction to Multilingual Issues #1, Next: Introduction to Multilingual Issues #2, Prev: Multilingual Support, Up: Multilingual Support *************** *** 6094,6100 **** depending on XEUNICODE_P.  ! File: internals.info, Node: Modules for Internationalization, Prev: Microsoft Windows-Related Multilingual Issues, Up: Multilingual Support 25.13 Modules for Internationalization ====================================== --- 6095,6101 ---- depending on XEUNICODE_P.  ! File: internals.info, Node: Modules for Internationalization, Next: The Great Mule Merge of March 2002, Prev: Microsoft Windows-Related Multilingual Issues, Up: Multilingual Support 25.13 Modules for Internationalization ====================================== *************** *** 6166,6181 **** Asian-language support, and is not currently used.  ! File: internals.info, Node: Consoles; Devices; Frames; Windows, Next: The Redisplay Mechanism, Prev: Multilingual Support, Up: Top ! 26 Consoles; Devices; Frames; Windows ! ************************************* * Menu: ! * Introduction to Consoles; Devices; Frames; Windows:: ! * Point:: ! * Window Hierarchy:: ! * The Window Object:: ! * Modules for the Basic Displayable Lisp Objects:: --- 6167,6203 ---- Asian-language support, and is not currently used.  ! File: internals.info, Node: The Great Mule Merge of March 2002, Prev: Modules for Internationalization, Up: Multilingual Support ! 25.14 The Great Mule Merge of March 2002 ! ======================================== ! ! In March 2002, just after the release of XEmacs 21.5 beta 5, Ben Wing ! merged what was nominally a very large refactoring of the "Mule" ! multilingual support code into the mainline. This merge added robust ! support for Unicode on all platforms, and by providing support for Win32 ! Unicode APIs made the Mule support on the Windows platform a reality. ! This merge also included a large number of other changes and ! improvements, not necessarily related to internationalization. ! ! This node basically amounts to the ChangeLog for 2002-03-12. ! ! Some effort has been put into proper markup for code and file names, ! and some reorganization according to themes of revision. However, much ! remains to be done. * Menu: ! * List of changed files in new Mule workspace:: ! * Changes to the MULE subsystems:: ! * Pervasive changes throughout XEmacs sources:: ! * Changes to specific subsystems:: ! * Mule changes by theme:: ! * File-coding rewrite:: ! * General User-Visible Changes:: ! * General Lisp-Visible Changes:: ! * User documentation:: ! * General internal changes:: ! * Ben's TODO list:: Probably obsolete. ! * Ben's README:: Probably obsolete. diff -c 'xemacs-21.5.25/info/internals.info-3' 'xemacs-21.5.26/info/internals.info-3' Index: ./info/internals.info-3 *** ./info/internals.info-3 Sun Feb 26 22:31:24 2006 --- ./info/internals.info-3 Sat Apr 1 04:05:23 2006 *************** *** 46,6036 **** Foundation instead of in the original English.  ! File: internals.info, Node: Introduction to Consoles; Devices; Frames; Windows, Next: Point, Prev: Consoles; Devices; Frames; Windows, Up: Consoles; Devices; Frames; Windows ! 26.1 Introduction to Consoles; Devices; Frames; Windows ! ======================================================= ! A window-system window that you see on the screen is called a "frame" ! in Emacs terminology. Each frame is subdivided into one or more ! non-overlapping panes, called (confusingly) "windows". Each window ! displays the text of a buffer in it. (See above on Buffers.) Note that ! buffers and windows are independent entities: Two or more windows can ! be displaying the same buffer (potentially in different locations), and ! a buffer can be displayed in no windows. ! A single display screen that contains one or more frames is called a ! "display". Under most circumstances, there is only one display. ! However, more than one display can exist, for example if you have a ! "multi-headed" console, i.e. one with a single keyboard but multiple ! displays. (Typically in such a situation, the various displays act like ! one large display, in that the mouse is only in one of them at a time, ! and moving the mouse off of one moves it into another.) In some cases, ! the different displays will have different characteristics, e.g. one ! color and one mono. ! XEmacs can display frames on multiple displays. It can even deal ! simultaneously with frames on multiple keyboards (called "consoles" in ! XEmacs terminology). Here is one case where this might be useful: You ! are using XEmacs on your workstation at work, and leave it running. ! Then you go home and dial in on a TTY line, and you can use the ! already-running XEmacs process to display another frame on your local ! TTY. ! Thus, there is a hierarchy console -> display -> frame -> window. ! There is a separate Lisp object type for each of these four concepts. ! Furthermore, there is logically a "selected console", "selected ! display", "selected frame", and "selected window". Each of these ! objects is distinguished in various ways, such as being the default ! object for various functions that act on objects of that type. Note ! that every containing object remembers the "selected" object among the ! objects that it contains: e.g. not only is there a selected window, but ! every frame remembers the last window in it that was selected, and ! changing the selected frame causes the remembered window within it to ! become the selected window. Similar relationships apply for consoles ! to devices and devices to frames.  ! File: internals.info, Node: Point, Next: Window Hierarchy, Prev: Introduction to Consoles; Devices; Frames; Windows, Up: Consoles; Devices; Frames; Windows ! 26.2 Point ! ========== ! Recall that every buffer has a current insertion position, called ! "point". Now, two or more windows may be displaying the same buffer, ! and the text cursor in the two windows (i.e. `point') can be in two ! different places. You may ask, how can that be, since each buffer has ! only one value of `point'? The answer is that each window also has a ! value of `point' that is squirreled away in it. There is only one ! selected window, and the value of "point" in that buffer corresponds to ! that window. When the selected window is changed from one window to ! another displaying the same buffer, the old value of `point' is stored ! into the old window's "point" and the value of `point' from the new ! window is retrieved and made the value of `point' in the buffer. This ! means that `window-point' for the selected window is potentially ! inaccurate, and if you want to retrieve the correct value of `point' ! for a window, you must special-case on the selected window and retrieve ! the buffer's point instead. This is related to why ! `save-window-excursion' does not save the selected window's value of ! `point'. !  ! File: internals.info, Node: Window Hierarchy, Next: The Window Object, Prev: Point, Up: Consoles; Devices; Frames; Windows ! 26.3 Window Hierarchy ! ===================== ! If a frame contains multiple windows (panes), they are always created ! by splitting an existing window along the horizontal or vertical axis. ! Terminology is a bit confusing here: to "split a window horizontally" ! means to create two side-by-side windows, i.e. to make a _vertical_ cut ! in a window. Likewise, to "split a window vertically" means to create ! two windows, one above the other, by making a _horizontal_ cut. ! If you split a window and then split again along the same axis, you ! will end up with a number of panes all arranged along the same axis. ! The precise way in which the splits were made should not be important, ! and this is reflected internally. Internally, all windows are arranged ! in a tree, consisting of two types of windows, "combination" windows ! (which have children, and are covered completely by those children) and ! "leaf" windows, which have no children and are visible. Every ! combination window has two or more children, all arranged along the same ! axis. There are (logically) two subtypes of windows, depending on ! whether their children are horizontally or vertically arrayed. There is ! always one root window, which is either a leaf window (if the frame ! contains only one window) or a combination window (if the frame contains ! more than one window). In the latter case, the root window will have ! two or more children, either horizontally or vertically arrayed, and ! each of those children will be either a leaf window or another ! combination window. ! Here are some rules: ! 1. Horizontal combination windows can never have children that are ! horizontal combination windows; same for vertical. ! 2. Only leaf windows can be split (obviously) and this splitting does ! one of two things: (a) turns the leaf window into a combination ! window and creates two new leaf children, or (b) turns the leaf ! window into one of the two new leaves and creates the other leaf. ! Rule (1) dictates which of these two outcomes happens. ! 3. Every combination window must have at least two children. ! 4. Leaf windows can never become combination windows. They can be ! deleted, however. If this results in a violation of (3), the ! parent combination window also gets deleted. ! 5. All functions that accept windows must be prepared to accept ! combination windows, and do something sane (e.g. signal an error ! if so). Combination windows _do_ escape to the Lisp level. ! 6. All windows have three fields governing their contents: these are ! "hchild" (a list of horizontally-arrayed children), "vchild" (a ! list of vertically-arrayed children), and "buffer" (the buffer ! contained in a leaf window). Exactly one of these will be ! non-`nil'. Remember that "horizontally-arrayed" means ! "side-by-side" and "vertically-arrayed" means "one above the ! other". ! 7. Leaf windows also have markers in their `start' (the first buffer ! position displayed in the window) and `pointm' (the window's ! stashed value of `point'--see above) fields, while combination ! windows have `nil' in these fields. ! 8. The list of children for a window is threaded through the `next' ! and `prev' fields of each child window. ! 9. *Deleted windows can be undeleted*. This happens as a result of ! restoring a window configuration, and is unlike frames, displays, ! and consoles, which, once deleted, can never be restored. ! Deleting a window does nothing except set a special `dead' bit to ! 1 and clear out the `next', `prev', `hchild', and `vchild' fields, ! for GC purposes. ! 10. Most frames actually have two top-level windows--one for the ! minibuffer and one (the "root") for everything else. The modeline ! (if present) separates these two. The `next' field of the root ! points to the minibuffer, and the `prev' field of the minibuffer ! points to the root. The other `next' and `prev' fields are `nil', ! and the frame points to both of these windows. Minibuffer-less ! frames have no minibuffer window, and the `next' and `prev' of the ! root window are `nil'. Minibuffer-only frames have no root ! window, and the `next' of the minibuffer window is `nil' but the ! `prev' points to itself. (#### This is an artifact that should be ! fixed.) !  ! File: internals.info, Node: The Window Object, Next: Modules for the Basic Displayable Lisp Objects, Prev: Window Hierarchy, Up: Consoles; Devices; Frames; Windows ! 26.4 The Window Object ! ====================== ! Windows have the following accessible fields: ! `frame' ! The frame that this window is on. ! `mini_p' ! Non-`nil' if this window is a minibuffer window. ! `buffer' ! The buffer that the window is displaying. This may change often ! during the life of the window. ! `dedicated' ! Non-`nil' if this window is dedicated to its buffer. ! `pointm' ! This is the value of point in the current buffer when this window ! is selected; when it is not selected, it retains its previous ! value. ! `start' ! The position in the buffer that is the first character to be ! displayed in the window. ! `force_start' ! If this flag is non-`nil', it says that the window has been ! scrolled explicitly by the Lisp program. This affects what the ! next redisplay does if point is off the screen: instead of ! scrolling the window to show the text around point, it moves point ! to a location that is on the screen. ! `last_modified' ! The `modified' field of the window's buffer, as of the last time a ! redisplay completed in this window. ! `last_point' ! The buffer's value of point, as of the last time a redisplay ! completed in this window. ! `left' ! This is the left-hand edge of the window, measured in columns. ! (The leftmost column on the screen is column 0.) ! `top' ! This is the top edge of the window, measured in lines. (The top ! line on the screen is line 0.) ! `height' ! The height of the window, measured in lines. ! `width' ! The width of the window, measured in columns. ! `next' ! This is the window that is the next in the chain of siblings. It ! is `nil' in a window that is the rightmost or bottommost of a ! group of siblings. ! `prev' ! This is the window that is the previous in the chain of siblings. ! It is `nil' in a window that is the leftmost or topmost of a group ! of siblings. ! `parent' ! Internally, XEmacs arranges windows in a tree; each group of ! siblings has a parent window whose area includes all the siblings. ! This field points to a window's parent. ! Parent windows do not display buffers, and play little role in ! display except to shape their child windows. Emacs Lisp programs ! usually have no access to the parent windows; they operate on the ! windows at the leaves of the tree, which actually display buffers. ! `hscroll' ! This is the number of columns that the display in the window is ! scrolled horizontally to the left. Normally, this is 0. ! `use_time' ! This is the last time that the window was selected. The function ! `get-lru-window' uses this field. ! `display_table' ! The window's display table, or `nil' if none is specified for it. ! `update_mode_line' ! Non-`nil' means this window's mode line needs to be updated. ! `base_line_number' ! The line number of a certain position in the buffer, or `nil'. ! This is used for displaying the line number of point in the mode ! line. ! `base_line_pos' ! The position in the buffer for which the line number is known, or ! `nil' meaning none is known. ! `region_showing' ! If the region (or part of it) is highlighted in this window, this ! field holds the mark position that made one end of that region. ! Otherwise, this field is `nil'. !  ! File: internals.info, Node: Modules for the Basic Displayable Lisp Objects, Prev: The Window Object, Up: Consoles; Devices; Frames; Windows ! 26.5 Modules for the Basic Displayable Lisp Objects ! =================================================== ! `console-msw.c' ! `console-msw.h' ! `console-stream.c' ! `console-stream.h' ! `console-tty.c' ! `console-tty.h' ! `console-x.c' ! `console-x.h' ! `console.c' ! `console.h' ! These modules implement the "console" Lisp object type. A console ! contains multiple display devices, but only one keyboard and mouse. ! Most of the time, a console will contain exactly one device. ! *This model may no longer suffice.* The X Window System (at least) ! now supports a variety of input devices, including touchscreens and ! tablets, as well as the traditional keyboard and mouse, and may even be ! able to support multiple instances of a single type of input device ! (especially pointing devices) on a single console. ! Consoles are the top of a lisp object inclusion hierarchy. Consoles ! contain devices, which contain frames, which contain windows. ! `device-msw.c' ! `device-tty.c' ! `device-x.c' ! `device.c' ! `device.h' ! These modules implement the "device" Lisp object type. This ! abstracts a particular screen or connection on which frames are ! displayed. As with Lisp objects, event interfaces, and other ! subsystems, the device code is separated into a generic component that ! contains a standardized interface (in the form of a set of methods) onto ! particular device types. ! The device subsystem defines all the methods and provides method ! services for not only device operations but also for the frame, window, ! menubar, scrollbar, toolbar, and other displayable-object subsystems. ! The reason for this is that all of these subsystems have the same ! subtypes (X, TTY, NeXTstep, Microsoft Windows, etc.) as devices do. ! *This abstraction is probably broken* (as of late 2004), at least ! for X consoles, with the advent of the *Xft* library. Xft is a ! complete break from the traditional approach to text rendering in the ! X11 environment, since fonts are composed of glyphs rendered by ! _client-side_ code. These glyphs are then transmitted to the server as ! sets of trapezoids, and displayed by the *XRender* extension (where ! available; the X11 core protocol can also be used, but this is slow). ! The XRender extension is especially attractive because it allows modern ! image composition techniques to be used to render antialiased fonts. ! By contrast, the traditional approach renders fonts on the server ! side as a collection of bitmaps. It is also possible use a _font ! server_ that knows how to render antialiased fonts, but for some reason ! this approach has never caught on. ! The problem that this creates for XEmacs is that the traditional (and ! still popular) widget sets, the various Athena variants and the Motif ! widget set, are based on the server-side rendering model. Thus, even if ! XEmacs-specific widgets (such as the basic text window, the Lucid ! menubar, and the recently added tab control) can be adapted to render ! text via Xft, older widgets (such as buttons and labels) and "modern" ! widgets derived from traditional widgets (the progress gauge) still ! expect their font resources to be converted to server-side fonts. Then ! text is rendered by calls to the core protocol via Xlib, rather than by ! calls to the XRender protocol via Xft. ! It's even possible to imagine a situation where a widget is composed ! of components which draw their own text (_predefined widgets_) as well ! as new components which can draw using more modern methods. Handling ! this will either require reworking the Emacs face mechanism to provide a ! way to determine whether this widget can use that font, or ways to give ! each of several different widgets, even different components of a given ! widget, a different face property. This is already an issue, as widgets ! generally derive their font from the gui-element face, but this might ! not be appropriate for widgets embedded in a buffer. ! There seem to be two overall ways to go. ! 1. Add face information to the Lucid widget library, and extend the ! coverage of that library to device types that aren't supported by ! it yet (MS Windows, and maybe TTY). ! 2. Create a lighter-weight interface, perhaps an extension of the ! device interface, that allows widgets to access face information ! from the device it is implemented on. ! `frame-msw.c' ! `frame-tty.c' ! `frame-x.c' ! `frame.c' ! `frame.h' ! Each device contains one or more frames in which objects (e.g. text) ! are displayed. A frame corresponds to a window in the window system; ! usually this is a top-level window but it could potentially be one of a ! number of overlapping child windows within a top-level window, using the ! MDI (Multiple Document Interface) protocol in Microsoft Windows or a ! similar scheme. ! The `frame-*' files implement the "frame" Lisp object type and ! provide the generic and device-type-specific operations on frames (e.g. ! raising, lowering, resizing, moving, etc.). ! `window.c' ! `window.h' ! Each frame consists of one or more non-overlapping "windows" (better ! known as "panes" in standard window-system terminology) in which a ! buffer's text can be displayed. Windows can also have scrollbars ! displayed around their edges. ! `window.c' and `window.h' implement the "window" Lisp object type ! and provide code to manage windows. Since windows have no associated ! resources in the window system (the window system knows only about the ! frame; no child windows or anything are used for XEmacs windows), there ! is no device-type-specific code here; all of that code is part of the ! redisplay mechanism or the code for particular object types such as ! scrollbars. !  ! File: internals.info, Node: The Redisplay Mechanism, Next: Extents, Prev: Consoles; Devices; Frames; Windows, Up: Top ! 27 The Redisplay Mechanism ! ************************** ! The redisplay mechanism is one of the most complicated sections of ! XEmacs, especially from a conceptual standpoint. This is doubly so ! because, unlike for the basic aspects of the Lisp interpreter, the ! computer science theories of how to efficiently handle redisplay are not ! well-developed. ! When working with the redisplay mechanism, remember the Golden Rules ! of Redisplay: ! 1. It Is Better To Be Correct Than Fast. ! 2. Thou Shalt Not Run Elisp From Within Redisplay. ! 3. It Is Better To Be Fast Than Not To Be. ! * Menu: ! * Critical Redisplay Sections:: ! * Line Start Cache:: ! * Redisplay Piece by Piece:: ! * Modules for the Redisplay Mechanism:: ! * Modules for other Display-Related Lisp Objects:: !  ! File: internals.info, Node: Critical Redisplay Sections, Next: Line Start Cache, Prev: The Redisplay Mechanism, Up: The Redisplay Mechanism - 27.1 Critical Redisplay Sections - ================================ ! *The following paragraphs are way out-of-date and inaccurate.* ! Within this section, we are defenseless and assume that the ! following cannot happen: ! 1. garbage collection ! 2. Lisp code evaluation ! 3. frame size changes ! We ensure (3) by calling `hold_frame_size_changes()', which will ! cause any pending frame size changes to get put on hold till after the ! end of the critical section. (1) follows automatically if (2) is met. ! #### Unfortunately, there are some places where Lisp code can be called ! within this section. We need to remove them. ! If `Fsignal()' is called during this critical section, we will ! `abort()'. ! If garbage collection is called during this critical section, we ! simply return. #### We should abort instead. ! #### If a frame-size change does occur we should probably actually ! be preempting redisplay. ! *Begin up-to-date stuff* ! 27.1.1 Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT ! ------------------------------------------------------------------------- ! These are now fixed as of November 10, 2004. ! Crash - reentrant `regenerate_window()' ! --------------------------------------- ! Here is a crash I (ben) just got - November 9, 2004: It can sort of be ! reproduced by creating a bunch of frames, opening a bunch of large ! files (which may be fontlocking for awhile). and immediately start ! Alt-TAB-ing back and forth quickly and constantly scrolling up and down ! using the scrolling dial on your mouse. ! Fatal error: assertion failed, file c:\xemacs\build\src\redisplay.c, line 5532, ! !dy->locked ! C backtrace: ! assert_failed(const char * 0x012a4ff0 `string', int 5532, const char * 0x0127bea4 `string') line 3839 ! Dynarr_verify_mod_1(void * 0x023ad2b0, const char * 0x012a4ff0 `string', int 5532) line 1306 + 36 bytes ! regenerate_window(window * 0x02f2ca88, long 40372, long 40372, int 2) line 5532 + 25 bytes ! update_line_start_cache(window * 0x02f2ca88, long 40372, long 40401, long 40372, int 0) line 8543 + 19 bytes ! point_in_line_start_cache(window * 0x02f2ca88, long 40372, int 0) line 7850 + 23 bytes ! start_end_of_last_line(window * 0x02f2ca88, long 40372, int 1, int 1) line 8121 + 15 bytes ! end_of_last_line_may_error(window * 0x02f2ca88, long 40372) line 8203 + 17 bytes ! pixel_to_glyph_translation(frame * 0x02f2c900, int 291, int 317, int * 0x0082bb04, int * 0x0082bb00, int * 0x0082bafc, int * 0x0082baf8, window * * 0x0082bae8, long * 0x0082baf4, long * 0x0082baf0, long * 0x0082baec, long * 0x0082bb10, long * 0x0082bb0c) line 9336 + 32 bytes ! mswindows_handle_mousewheel_event(long 49465600, int 0, int -240, tagPOINTS {...}) line 360 + 82 bytes ! mswindows_wnd_proc(HWND__ * 0x00260a42, unsigned int 522, unsigned int 4279238656, long 29885130) line 3561 + 36 bytes ! intercepted_wnd_proc(HWND__ * 0x00260a42, unsigned int 522, unsigned int 4279238656, long 29885130) line 2376 ! USER32! 77e11ef0() ! USER32! 77e1204c() ! USER32! 77e121af() ! mswindows_drain_windows_queue(int 0) line 1330 + 9 bytes ! emacs_mswindows_drain_queue() line 1339 + 7 bytes ! event_stream_drain_queue() line 1785 ! event_stream_quit_p() line 1893 ! check_quit() line 938 ! check_what_happened() line 459 ! internal_equal(long 22180468, long 22180468, int 0) line 2823 + 14 bytes ! update_image_instance(long 83498640, long 22180468) line 2121 + 18 bytes ! image_instantiate(long 21418616, long 20663624, long 54932896, long 22180468, long 3) line 3403 + 13 bytes ! va_call_trapping_problems_1(void * 0x0082cf94) line 5220 + 221 bytes ! call_trapping_problems_2(long 83160440) line 4867 + 13 bytes ! call_with_condition_handler(long (long, long, long)* 0x010cc4c0 flagged_a_squirmer(long, long, long), long 83160440, long (long)* 0x010cc440 call_trapping_problems_2(long), long 83160440) line 2129 + 7 bytes ! call_trapping_problems_1(long 83160440) line 4874 + 23 bytes ! internal_catch(long 21399864, long (long)* 0x010cc490 call_trapping_problems_1(long), long 83160440, int * volatile 0x0082ce4c, long * volatile 0x0082ce54) line 1527 + 7 bytes ! call_trapping_problems(long 20908160, const char * 0x00000000, int 98315, call_trapping_problems_result * 0x00000000, long (void *)* 0x010cca30 va_call_trapping_problems_1(void *), void * 0x0082cf94) line 5147 + 32 bytes ! call_with_suspended_errors(long (void)* 0x011448c0 image_instantiate(long, long, long, long, long), long 20663624, long 20908160, _error_behavior_struct_ {...}, int 5) line 5314 + 26 bytes ! specifier_instance_from_inst_list(long 21418616, long 20663624, long 54932896, long 21673760, _error_behavior_struct_ {...}, int 1, long 3) line 2501 + 54 bytes ! specifier_instance(long 21418616, long 20663624, long 54932896, _error_behavior_struct_ {...}, int 1, int 0, long 3) line 2614 + 64 bytes ! glyph_image_instance(long 22692176, long 54932896, _error_behavior_struct_ {...}, int 1) line 3955 + 31 bytes ! add_glyph_rune(position_redisplay_data_type * 0x0082d52c, glyph_block * 0x0082d454, int 0, int 0, glyph_cachel * 0x04f4e518) line 1972 + 26 bytes ! create_text_block(window * 0x034635a0, display_line * 0x033bfb28, long 29860, prop_block_dynarr * * 0x0082d7b8, int 2) line 2827 + 30 bytes ! generate_display_line(window * 0x034635a0, display_line * 0x033bfb28, int 1, long 29860, prop_block_dynarr * * 0x0082d7b8, int 2) line 979 + 38 bytes ! regenerate_window(window * 0x034635a0, long 29860, long 25012, int 2) line 5607 + 30 bytes ! update_line_start_cache(window * 0x034635a0, long 25012, long 28767, long 25012, int 0) line 8614 + 19 bytes ! point_in_line_start_cache(window * 0x034635a0, long 25012, int 0) line 7850 + 23 bytes ! start_end_of_last_line(window * 0x034635a0, long 25012, int 1, int 0) line 8121 + 15 bytes ! end_of_last_line(window * 0x034635a0, long 25012) line 8197 + 17 bytes ! Fwindow_end(long 54932896, long 20926544) line 1848 + 13 bytes ! Ffuncall(int 3, long * 0x0082dbb8) line 3841 + 93 bytes ! execute_optimized_program(const unsigned char * 0x032ceee8, int 7, long * 0x03289f40) line 823 + 16 bytes ! funcall_compiled_function(long 52991916, int 1, long * 0x0082dfb0) line 3454 + 85 bytes ! Ffuncall(int 2, long * 0x0082dfac) line 3880 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02f667d8, int 6, long * 0x01558748) line 823 + 16 bytes ! funcall_compiled_function(long 22579576, int 3, long * 0x0082e3ac) line 3454 + 85 bytes ! Ffuncall(int 4, long * 0x0082e3a8) line 3880 + 17 bytes ! execute_optimized_program(const unsigned char * 0x03209c98, int 5, long * 0x03288c68) line 823 + 16 bytes ! funcall_compiled_function(long 51656320, int 1, long * 0x0082e7a4) line 3454 + 85 bytes ! Ffuncall(int 2, long * 0x0082e7a0) line 3880 + 17 bytes ! execute_optimized_program(const unsigned char * 0x0082e9ec, int 4, long * 0x03224990) line 823 + 16 bytes ! Fbyte_code(long 37927380, long 52578688, long 9) line 2564 + 70 bytes ! Feval(long 51505420) line 3601 + 187 bytes ! internal_catch(long 51959412, long (long)* 0x010c6f40 Feval(long), long 51505420, int * volatile 0x00000000, long * volatile 0x00000000) line 1527 + 7 bytes ! execute_rare_opcode(long * 0x0082eee8, const unsigned char * 0x03248365, Opcode Bcatch) line 1380 + 24 bytes ! execute_optimized_program(const unsigned char * 0x03248340, int 2, long * 0x02f3c0a0) line 715 + 17 bytes ! funcall_compiled_function(long 51656276, int 0, long * 0x0082f444) line 3454 + 85 bytes ! Ffuncall(int 1, long * 0x0082f440) line 3880 + 17 bytes ! run_hook_with_args_in_buffer(buffer * 0x04ee9060, int 1, long * 0x0082f440, run_hooks_condition RUN_HOOKS_TO_COMPLETION) line 4361 + 13 bytes ! run_hook_with_args(int 1, long * 0x0082f440, run_hooks_condition RUN_HOOKS_TO_COMPLETION) line 4374 + 23 bytes ! run_hook(long 51959028) line 4443 + 13 bytes ! safe_run_hook_trapping_problems_1(void * 0x013c73c0) line 5517 + 9 bytes ! call_trapping_problems_2(long 83157920) line 4867 + 13 bytes ! call_with_condition_handler(long (long, long, long)* 0x010cc4c0 flagged_a_squirmer(long, long, long), long 83157920, long (long)* 0x010cc440 call_trapping_problems_2(long), long 83157920) line 2129 + 7 bytes ! call_trapping_problems_1(long 83157920) line 4874 + 23 bytes ! internal_catch(long 21399864, long (long)* 0x010cc490 call_trapping_problems_1(long), long 83157920, int * volatile 0x0082f700, long * volatile 0x0082f708) line 1527 + 7 bytes ! call_trapping_problems(long 20925944, const char * 0x00000000, int 131235, call_trapping_problems_result * 0x0082f830, long (void *)* 0x010cd990 safe_run_hook_trapping_problems_1(void *), void * 0x013c73c0) line 5147 + 32 bytes ! safe_run_hook_trapping_problems(long 20741312, long 20739008, int 160) line 5543 + 36 bytes ! run_pre_idle_hook() line 2084 + 24 bytes ! redisplay() line 7224 ! Fnext_event(long 37363732, long 20928056) line 2263 ! Fcommand_loop_1() line 600 + 15 bytes ! command_loop_1(long 20928056) line 512 ! condition_case_1(long 20925944, long (long)* 0x01096a80 command_loop_1(long), long 20928056, long (long, long)* 0x01096630 cmd_error(long, long), long 20928056) line 1918 + 7 bytes ! command_loop_3() line 262 + 35 bytes ! command_loop_2(long 20928056) line 277 ! internal_catch(long 20683712, long (long)* 0x010967a0 command_loop_2(long), long 20928056, int * volatile 0x00000000, long * volatile 0x00000000) line 1527 + 7 bytes ! initial_command_loop(long 20928056) line 313 + 28 bytes ! xemacs_21_5_b18_i586_pc_win32(int 1, unsigned short * * 0x0082fed0, unsigned short * * 0x00000000, int 0) line 2551 ! main(int 1, char * * 0x00e52610, char * * 0x00e52bb0) line 2992 ! mainCRTStartup() line 338 + 17 bytes ! KERNEL32! 7c59893d() ! Lisp backtrace: ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! window-end(#" 0x5e4a> t) ! # (unwind-protect ...) ! # bind (buffer we-are-screwed check-text-props window) ! lazy-lock-fontify-window(#" 0x5e4a>) ! # bind (walk-windows-current walk-windows-start arg which-devices which-frames ! minibuf function) ! walk-windows(lazy-lock-fontify-window no-minibuf #) ! # (unwind-protect ...) ! # bind (ssf65112 tick frame) ! lazy-lock-maybe-fontify-frame(#) ! # bind (frame starting-frame) ! byte-code("..." [starting-frame frame selected-frame frame-visible-p frame-min ! ibuffer-only-p next-frame visible-nomini throw lazy-lock-frame-loop-done t lazy- ! lock-maybe-fontify-frame] 4) ! # (catch lazy-lock-frame-loop-done ...) ! lazy-lock-pre-idle-fontify-windows() ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! (next-event "[internal]") ! # (condition-case ... . error) ! # (catch top-level ...) ! Another Lisp trace of a similar situation (C stack trace not available): ! ........................................................................ ! Fatal error: assertion failed, file c:\xemacs\build\src\redisplay.c, line 5532, ! !dy->locked ! ! Lisp backtrace follows: ! ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! scrollbar-page-down((#)) ! (dispatch-event "[internal]") ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! window-end(# t) ! # (unwind-protect ...) ! # bind (buffer we-are-screwed check-text-props window) ! lazy-lock-fontify-window(#) ! # bind (walk-windows-current walk-windows-start arg which-devices which-frames ! minibuf function) ! walk-windows(lazy-lock-fontify-window no-minibuf #) ! # (unwind-protect ...) ! # bind (ssf65112 tick frame) ! lazy-lock-maybe-fontify-frame(#) ! # bind (frame starting-frame) ! byte-code("..." [starting-frame frame selected-frame frame-visible-p frame-min ! ibuffer-only-p next-frame visible-nomini throw lazy-lock-frame-loop-done t lazy- ! lock-maybe-fontify-frame] 4) ! # (catch lazy-lock-frame-loop-done ...) ! lazy-lock-pre-idle-fontify-windows() ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! (next-event "[internal]") ! # (condition-case ... . error) ! # (catch top-level ...) ! Crash - reentrant `generate_displayable_area()' ! ----------------------------------------------- ! Original code said [Tricky tricky tricky. ! `generate_displayable_area()' can (could) be called reentrantly, and ! redisplay is not prepared to handle this:]. ! assert_failed(const char * 0x0129c8c8 `string', int 5328, const char ! * 0x01274068 `string') line 3620 Dynarr_verify_mod_1(void * 0x0250f228, ! const char * 0x0129c8c8 `string', int 5328) line 1256 + 36 bytes ! generate_displayable_area(window * 0x02480028, long 38776292, int 0, ! int 0, int 265, int 169, display_line_dynarr * 0x0250f228, long 0, int ! 2) line 5328 + 25 bytes output_gutter(frame * 0x0228ad90, gutter_pos ! TOP_GUTTER, int 1) line 409 + 69 bytes redraw_exposed_gutter(frame * ! 0x0228ad90, gutter_pos TOP_GUTTER, int 8, int 23, int 249, int 127) ! line 687 + 15 bytes redraw_exposed_gutters(frame * 0x0228ad90, int 8, ! int 23, int 249, int 127) line 703 + 29 bytes ! mswindows_redraw_exposed_area(frame * 0x0228ad90, int 8, int 23, int ! 249, int 127) line 862 + 25 bytes mswindows_handle_paint(frame * ! 0x0228ad90) line 2176 + 25 bytes mswindows_wnd_proc(HWND__ * ! 0x001003e2, unsigned int 15, unsigned int 0, long 0) line 3233 + 45 ! bytes intercepted_wnd_proc(HWND__ * 0x001003e2, unsigned int 15, ! unsigned int 0, long 0) line 2488 USER32! 77e3a244() USER32! 77e14730() ! USER32! 77e1558a() NTDLL! KiUserCallbackDispatcher@12 + 19 bytes ! USER32! 77e14680() USER32! 77e1a792() qxeIsDialogMessage(HWND__ * ! 0x001003e2, tagMSG * 0x0082a93c {msg=0x0000000f wp=0x00000000 ! lp=0x00000000}) line 2298 + 14 bytes mswindows_is_dialog_msg(tagMSG * ! 0x0082a93c {msg=0x0000000f wp=0x00000000 lp=0x00000000}) line 165 + 13 ! bytes mswindows_drain_windows_queue(int 0) line 1282 + 9 bytes ! emacs_mswindows_drain_queue() line 1326 + 7 bytes ! event_stream_drain_queue() line 1887 event_stream_quit_p() line 1992 ! check_quit() line 993 unbind_to_hairy(int 35) line 5963 unbind_to_1(int ! 35, long 20888208) line 5945 + 200 bytes ! specifier_instance_from_inst_list(long 21379344, long 38135616, long ! 36220304, long 20888208, _error_behavior_struct_ {...}, int 1, long 3) ! line 2522 + 16 bytes specifier_instance(long 21379344, long 38135616, ! long 36220304, _error_behavior_struct_ {...}, int 1, int 0, long 3) ! line 2625 + 65 bytes specifier_instance_no_quit(long 21379344, long ! 38135616, long 36220304, _error_behavior_struct_ {...}, int 0, long 1) ! line 2658 + 31 bytes face_property_matching_instance(long 22612340, ! long 20860632, long 22530956, long 36220304, _error_behavior_struct_ ! {...}, int 0, long 1) line 565 + 48 bytes ! ensure_face_cachel_contains_charset(face_cachel * 0x0082b014, long ! 36220304, long 22530956) line 1104 + 35 bytes ! update_face_cachel_data(face_cachel * 0x0082b014, long 36220304, long ! 22612340) line 1304 + 19 bytes query_string_geometry(long 21110576, ! long 22612340, int * 0x00000000, int * 0x0082b5b4, int * 0x00000000, ! long 38852960) line 2370 + 23 bytes ! mswindows_widget_query_string_geometry(long 21110576, long 22612340, ! int * 0x0082b5b8, int * 0x0082b5b4, long 38852960) line 2914 + 25 bytes ! widget_query_string_geometry(long 21110576, long 22612340, int * ! 0x0082b5b8, int * 0x0082b5b4, long 38852960) line 514 + 32 bytes ! edit_field_query_geometry(long 38857648, int * 0x0082b7b4, int * ! 0x0082b7b8, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long ! 38852960) line 920 + 390 bytes widget_query_geometry(long 38857648, int ! * 0x0082b7b4, int * 0x0082b7b8, image_instance_geometry ! IMAGE_DESIRED_GEOMETRY, long 38852960) line 567 + 26 bytes ! image_instance_query_geometry(long 38857648, int * 0x0082b7b4, int * ! 0x0082b7b8, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long ! 38852960) line 2015 + 26 bytes glyph_query_geometry(long 38853384, int ! * 0x0082b7b4, int * 0x0082b7b8, image_instance_geometry ! IMAGE_DESIRED_GEOMETRY, long 38852960) line 4197 + 25 bytes ! layout_query_geometry(long 38852960, int * 0x0082b9cc, int * ! 0x0082b9d0, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long ! 38404624) line 1351 + 25 bytes widget_query_geometry(long 38852960, int ! * 0x0082b9cc, int * 0x0082b9d0, image_instance_geometry ! IMAGE_DESIRED_GEOMETRY, long 38404624) line 567 + 26 bytes ! image_instance_query_geometry(long 38852960, int * 0x0082b9cc, int * ! 0x0082b9d0, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long ! 38404624) line 2015 + 26 bytes glyph_query_geometry(long 38537976, int ! * 0x0082b9cc, int * 0x0082b9d0, image_instance_geometry ! IMAGE_DESIRED_GEOMETRY, long 38404624) line 4197 + 25 bytes ! layout_layout(long 38404624, int 265, int 156, int -2, int -2, long ! 38273064) line 1468 + 23 bytes widget_layout(long 38404624, int 265, ! int 156, int -2, int -2, long 38273064) line 626 + 30 bytes ! image_instance_layout(long 38404624, int 265, int 156, int -2, int -2, ! long 38273064) line 2102 + 51 bytes glyph_ascent(long 38404624, long ! 38273064) line 4009 + 21 bytes update_glyph_cachel_data(window * ! 0x02480028, long 36201168, glyph_cachel * 0x0248c3d8) line 4272 + 13 ! bytes get_glyph_cachel_index(window * 0x02480028, long 36201168) line ! 4306 + 17 bytes add_glyph_rune(position_redisplay_data_type * ! 0x0082bf2c, glyph_block * 0x024bd028, int 0, int 0, glyph_cachel * ! 0x00000000) line 1800 + 15 bytes ! add_glyph_runes(position_redisplay_data_type * 0x0082bf2c, int 0) line ! 2085 + 31 bytes create_string_text_block(window * 0x02480028, long ! 38776292, display_line * 0x02514500, long 0, prop_block_dynarr * * ! 0x0082c13c, int 2) line 4907 + 14 bytes ! generate_string_display_line(window * 0x02480028, long 38776292, ! display_line * 0x02514500, long 0, prop_block_dynarr * * 0x0082c13c, ! int 2) line 5293 + 29 bytes generate_displayable_area(window * ! 0x02480028, long 38776292, int 0, int 0, int 265, int 169, ! display_line_dynarr * 0x0250f228, long 0, int 2) line 5372 + 29 bytes ! output_gutter(frame * 0x0228ad90, gutter_pos TOP_GUTTER, int 0) line ! 409 + 69 bytes update_frame_gutters(frame * 0x0228ad90) line 639 + 15 ! bytes redisplay_frame(frame * 0x0228ad90, int 1) line 6792 + 9 bytes ! redisplay_device(device * 0x0171df00, int 1) line 6911 + 11 bytes ! redisplay_without_hooks() line 6957 + 11 bytes ! redisplay_no_pre_idle_hook() line 7029 redisplay() line 7011 ! mswindows_wnd_proc(HWND__ * 0x001003e2, unsigned int 5, unsigned int 0, ! long 10223881) line 3424 intercepted_wnd_proc(HWND__ * 0x001003e2, ! unsigned int 5, unsigned int 0, long 10223881) line 2488 USER32! ! 77e3a244() USER32! 77e16362() USER32! 77e14c1a() USER32! 77e1dd30() ! mswindows_wnd_proc(HWND__ * 0x001003e2, unsigned int 71, unsigned int ! 0, long 8578308) line 3926 + 21 bytes intercepted_wnd_proc(HWND__ * ! 0x001003e2, unsigned int 71, unsigned int 0, long 8578308) line 2488 ! USER32! 77e3a244() USER32! 77e14730() USER32! 77e174b4() NTDLL! ! KiUserCallbackDispatcher@12 + 19 bytes mswindows_set_frame_size(frame * ! 0x0228ad90, int 265, int 156) line 355 internal_set_frame_size(frame * ! 0x0228ad90, int 265, int 156, int 0) line 2754 + 24 bytes ! Fset_frame_displayable_pixel_size(long 36220304, long 531, long 313, ! long 20888208) line 3004 + 32 bytes Ffuncall(int 4, long * 0x0082e778) ! line 3844 + 168 bytes execute_optimized_program(const unsigned char * ! 0x02286e48, int 40, long * 0x01529b80) line 609 + 16 bytes ! funcall_compiled_function(long 22433308, int 0, long * 0x0082ec08) line ! 3452 + 85 bytes Ffuncall(int 1, long * 0x0082ec04) line 3883 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02286d40, int 6, long ! * 0x01548ddc) line 609 + 16 bytes funcall_compiled_function(long ! 22505864, int 11, long * 0x0082f00c) line 3452 + 85 bytes Ffuncall(int ! 12, long * 0x0082f008) line 3883 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02503e38, int 47, ! long * 0x0152dc48) line 609 + 16 bytes funcall_compiled_function(long ! 22436784, int 0, long * 0x0082f534) line 3452 + 85 bytes Ffuncall(int ! 1, long * 0x0082f530) line 3883 + 17 bytes apply1(long 22436784, long ! 20888208) line 4458 + 11 bytes Fcall_interactively(long 20742816, long ! 20888208, long 20888208) line 460 + 13 bytes Ffuncall(int 2, long * ! 0x0082f8ec) line 3844 + 127 bytes call1(long 20854392, long 20742816) ! line 4489 + 11 bytes execute_command_event(command_builder * ! 0x01798f98, long 24439276) line 4198 + 69 bytes Fdispatch_event(long ! 24439276) line 4569 + 13 bytes Fcommand_loop_1() line 569 + 9 bytes ! command_loop_1(long 20888208) line 489 condition_case_1(long 20886024, ! long (long)* 0x010955a0 command_loop_1(long), long 20888208, long ! (long, long)* 0x01095150 cmd_error(long, long), long 20888208) line ! 1917 + 7 bytes command_loop_3() line 251 + 35 bytes command_loop_2(long ! 20888208) line 264 internal_catch(long 20650992, long (long)* ! 0x010952c0 command_loop_2(long), long 20888208, int * volatile ! 0x00000000, long * volatile 0x00000000) line 1527 + 7 bytes ! initial_command_loop(long 20888208) line 300 + 28 bytes ! xemacs_21_5_b10_i586_pc_win32(int 1, char * * 0x00e52620, char * * ! 0x00e52bb0, int 0) line 2356 main(int 1, char * * 0x00e52620, char * * ! 0x00e52bb0) line 2733 mainCRTStartup() line 338 + 17 bytes KERNEL32! ! 77ea847c() !  ! File: internals.info, Node: Line Start Cache, Next: Redisplay Piece by Piece, Prev: Critical Redisplay Sections, Up: The Redisplay Mechanism ! 27.2 Line Start Cache ! ===================== ! The traditional scrolling code in Emacs breaks in a variable height ! world. It depends on the key assumption that the number of lines that ! can be displayed at any given time is fixed. This led to a complete ! separation of the scrolling code from the redisplay code. In order to ! fully support variable height lines, the scrolling code must actually be ! tightly integrated with redisplay. Only redisplay can determine how ! many lines will be displayed on a screen for any given starting point. ! What is ideally wanted is a complete list of the starting buffer ! position for every possible display line of a buffer along with the ! height of that display line. Maintaining such a full list would be very ! expensive. We settle for having it include information for all areas ! which we happen to generate anyhow (i.e. the region currently being ! displayed) and for those areas we need to work with. ! In order to ensure that the cache accurately represents what ! redisplay would actually show, it is necessary to invalidate it in many ! situations. If the buffer changes, the starting positions may no longer ! be correct. If a face or an extent has changed then the line heights ! may have altered. These events happen frequently enough that the cache ! can end up being constantly disabled. With this potentially constant ! invalidation when is the cache ever useful? ! Even if the cache is invalidated before every single usage, it is ! necessary. Scrolling often requires knowledge about display lines which ! are actually above or below the visible region. The cache provides a ! convenient light-weight method of storing this information for multiple ! display regions. This knowledge is necessary for the scrolling code to ! always obey the First Golden Rule of Redisplay. ! If the cache already contains all of the information that the ! scrolling routines happen to need so that it doesn't have to go ! generate it, then we are able to obey the Third Golden Rule of ! Redisplay. The first thing we do to help out the cache is to always ! add the displayed region. This region had to be generated anyway, so ! the cache ends up getting the information basically for free. In those ! cases where a user is simply scrolling around viewing a buffer there is ! a high probability that this is sufficient to always provide the needed ! information. The second thing we can do is be smart about invalidating ! the cache. ! TODO--Be smart about invalidating the cache. Potential places: ! * Insertions at end-of-line which don't cause line-wraps do not ! alter the starting positions of any display lines. These types of ! buffer modifications should not invalidate the cache. This is ! actually a large optimization for redisplay speed as well. ! * Buffer modifications frequently only affect the display of lines ! at and below where they occur. In these situations we should only ! invalidate the part of the cache starting at where the ! modification occurs. ! In case you're wondering, the Second Golden Rule of Redisplay is not ! applicable.  ! File: internals.info, Node: Redisplay Piece by Piece, Next: Modules for the Redisplay Mechanism, Prev: Line Start Cache, Up: The Redisplay Mechanism ! 27.3 Redisplay Piece by Piece ! ============================= ! As you can begin to see redisplay is complex and also not well ! documented. Chuck no longer works on XEmacs so this section is my take ! on the workings of redisplay. ! Redisplay happens in three phases: ! 1. Determine desired display in area that needs redisplay. ! Implemented by `redisplay.c' ! 2. Compare desired display with current display Implemented by ! `redisplay-output.c' ! 3. Output changes Implemented by `redisplay-output.c', ! `redisplay-x.c', `redisplay-msw.c' and `redisplay-tty.c' ! Steps 1 and 2 are device-independent and relatively complex. Step 3 ! is mostly device-dependent. ! Determining the desired display ! Display attributes are stored in `display_line' structures. Each ! `display_line' consists of a set of `display_block''s and each ! `display_block' contains a number of `rune''s. Generally dynarr's of ! `display_line''s are held by each window representing the current ! display and the desired display. ! The `display_line' structures are tightly tied to buffers which ! presents a problem for redisplay as this connection is bogus for the ! modeline. Hence the `display_line' generation routines are duplicated ! for generating the modeline. This means that the modeline display code ! has many bugs that the standard redisplay code does not. ! The guts of `display_line' generation are in `create_text_block', ! which creates a single display line for the desired locale. This ! incrementally parses the characters on the current line and generates ! redisplay structures for each. ! Gutter redisplay is different. Because the data to display is stored ! in a string we cannot use `create_text_block'. Instead we use ! `create_text_string_block' which performs the same function as ! `create_text_block' but for strings. Many of the complexities of ! `create_text_block' to do with cursor handling and selective display ! have been removed. !  ! File: internals.info, Node: Modules for the Redisplay Mechanism, Next: Modules for other Display-Related Lisp Objects, Prev: Redisplay Piece by Piece, Up: The Redisplay Mechanism ! 27.4 Modules for the Redisplay Mechanism ! ======================================== ! `redisplay-output.c' ! `redisplay-msw.c' ! `redisplay-tty.c' ! `redisplay-x.c' ! `redisplay.c' ! `redisplay.h' ! These files provide the redisplay mechanism. As with many other ! subsystems in XEmacs, there is a clean separation between the general ! and device-specific support. ! `redisplay.c' contains the bulk of the redisplay engine. These ! functions update the redisplay structures (which describe how the screen ! is to appear) to reflect any changes made to the state of any ! displayable objects (buffer, frame, window, etc.) since the last time ! that redisplay was called. These functions are highly optimized to ! avoid doing more work than necessary (since redisplay is called ! extremely often and is potentially a huge time sink), and depend heavily ! on notifications from the objects themselves that changes have occurred, ! so that redisplay doesn't explicitly have to check each possible object. ! The redisplay mechanism also contains a great deal of caching to further ! speed things up; some of this caching is contained within the various ! displayable objects. ! `redisplay-output.c' goes through the redisplay structures and ! converts them into calls to device-specific methods to actually output ! the screen changes. ! `redisplay-x.c' and `redisplay-tty.c' are two implementations of ! these redisplay output methods, for X frames and TTY frames, ! respectively. ! `indent.c' ! This module contains various functions and Lisp primitives for ! converting between buffer positions and screen positions. These ! functions call the redisplay mechanism to do most of the work, and then ! examine the redisplay structures to get the necessary information. This ! module needs work. ! `termcap.c' ! `terminfo.c' ! `tparam.c' ! These files contain functions for working with the termcap ! (BSD-style) and terminfo (System V style) databases of terminal ! capabilities and escape sequences, used when XEmacs is displaying in a ! TTY. ! `cm.c' ! `cm.h' ! These files provide some miscellaneous TTY-output functions and ! should probably be merged into `redisplay-tty.c'. !  ! File: internals.info, Node: Modules for other Display-Related Lisp Objects, Prev: Modules for the Redisplay Mechanism, Up: The Redisplay Mechanism ! 27.5 Modules for other Display-Related Lisp Objects ! =================================================== ! `faces.c' ! `faces.h' ! `bitmaps.h' ! `glyphs-eimage.c' ! `glyphs-msw.c' ! `glyphs-msw.h' ! `glyphs-widget.c' ! `glyphs-x.c' ! `glyphs-x.h' ! `glyphs.c' ! `glyphs.h' ! `objects-msw.c' ! `objects-msw.h' ! `objects-tty.c' ! `objects-tty.h' ! `objects-x.c' ! `objects-x.h' ! `objects.c' ! `objects.h' ! `menubar-msw.c' ! `menubar-msw.h' ! `menubar-x.c' ! `menubar.c' ! `menubar.h' ! `scrollbar-msw.c' ! `scrollbar-msw.h' ! `scrollbar-x.c' ! `scrollbar-x.h' ! `scrollbar.c' ! `scrollbar.h' ! `toolbar-msw.c' ! `toolbar-x.c' ! `toolbar.c' ! `toolbar.h' ! `font-lock.c' ! This file provides C support for syntax highlighting--i.e. ! highlighting different syntactic constructs of a source file in ! different colors, for easy reading. The C support is provided so that ! this is fast. ! `dgif_lib.c' ! `gif_err.c' ! `gif_lib.h' ! `gifalloc.c' ! These modules decode GIF-format image files, for use with glyphs. ! These files were removed due to Unisys patent infringement concerns. !  ! File: internals.info, Node: Extents, Next: Faces, Prev: The Redisplay Mechanism, Up: Top ! 28 Extents ! ********** ! * Menu: ! * Introduction to Extents:: Extents are ranges over text, with properties. ! * Extent Ordering:: How extents are ordered internally. ! * Format of the Extent Info:: The extent information in a buffer or string. ! * Zero-Length Extents:: A weird special case. ! * Mathematics of Extent Ordering:: A rigorous foundation. ! * Extent Fragments:: Cached information useful for redisplay. !  ! File: internals.info, Node: Introduction to Extents, Next: Extent Ordering, Prev: Extents, Up: Extents ! 28.1 Introduction to Extents ! ============================ ! Extents are regions over a buffer, with a start and an end position ! denoting the region of the buffer included in the extent. In addition, ! either end can be closed or open, meaning that the endpoint is or is ! not logically included in the extent. Insertion of a character at a ! closed endpoint causes the character to go inside the extent; insertion ! at an open endpoint causes the character to go outside. ! Extent endpoints are stored using memory indices (see `insdel.c'), ! to minimize the amount of adjusting that needs to be done when ! characters are inserted or deleted. ! (Formerly, extent endpoints at the gap could be either before or ! after the gap, depending on the open/closedness of the endpoint. The ! intent of this was to make it so that insertions would automatically go ! inside or out of extents as necessary with no further work needing to ! be done. It didn't work out that way, however, and just ended up ! complexifying and buggifying all the rest of the code.)  ! File: internals.info, Node: Extent Ordering, Next: Format of the Extent Info, Prev: Introduction to Extents, Up: Extents ! 28.2 Extent Ordering ! ==================== ! Extents are compared using memory indices. There are two orderings for ! extents and both orders are kept current at all times. The normal or ! "display" order is as follows: ! Extent A is ``less than'' extent B, ! that is, earlier in the display order, ! if: A-start < B-start, ! or if: A-start = B-start, and A-end > B-end ! So if two extents begin at the same position, the larger of them is ! the earlier one in the display order (`EXTENT_LESS' is true). ! For the e-order, the same thing holds: ! Extent A is ``less than'' extent B in e-order, ! that is, later in the buffer, ! if: A-end < B-end, ! or if: A-end = B-end, and A-start > B-start ! So if two extents end at the same position, the smaller of them is ! the earlier one in the e-order (`EXTENT_E_LESS' is true). ! The display order and the e-order are complementary orders: any ! theorem about the display order also applies to the e-order if you swap ! all occurrences of "display order" and "e-order", "less than" and ! "greater than", and "extent start" and "extent end". !  ! File: internals.info, Node: Format of the Extent Info, Next: Zero-Length Extents, Prev: Extent Ordering, Up: Extents ! 28.3 Format of the Extent Info ! ============================== ! An extent-info structure consists of a list of the buffer or string's ! extents and a "stack of extents" that lists all of the extents over a ! particular position. The stack-of-extents info is used for ! optimization purposes--it basically caches some info that might be ! expensive to compute. Certain otherwise hard computations are easy ! given the stack of extents over a particular position, and if the stack ! of extents over a nearby position is known (because it was calculated ! at some prior point in time), it's easy to move the stack of extents to ! the proper position. ! Given that the stack of extents is an optimization, and given that ! it requires memory, a string's stack of extents is wiped out each time ! a garbage collection occurs. Therefore, any time you retrieve the ! stack of extents, it might not be there. If you need it to be there, ! use the `_force' version. ! Similarly, a string may or may not have an extent_info structure. ! (Generally it won't if there haven't been any extents added to the ! string.) So use the `_force' version if you need the extent_info ! structure to be there. ! A list of extents is maintained as a double gap array. One gap array ! is ordered by start index (the "display order") and the other is ! ordered by end index (the "e-order"). Note that positions in an extent ! list should logically be conceived of as referring _to_ a particular ! extent (as is the norm in programs) rather than sitting between two ! extents. Note also that callers of these functions should not be aware ! of the fact that the extent list is implemented as an array, except for ! the fact that positions are integers (this should be generalized to ! handle integers and linked list equally well). ! A gap array is the same structure used by buffer text: an array of ! elements with a "gap" somewhere in the middle. Insertion and deletion ! happens by moving the gap to the insertion/deletion point, and then ! expanding/contracting as necessary. Gap arrays have a number of useful ! properties: ! 1. They are space efficient, as there is no need for next/previous ! pointers. ! 2. If the items in them are sorted, locating an item is fast - O(log ! N). ! 3. Insertion and deletion is very fast (constant time, essentially) ! if the gap is near (which favors localized operations, as will ! usually be the case). Even if not, it requires only a block move ! of memory, which is generally a highly optimized operation on ! modern processors. ! 4. Code to manipulate them is relatively simple to write. ! An alternative would be balanced binary trees, which have guaranteed ! O(log N) time for all operations (although the constant factors are not ! as good, and repeated localized operations will be slower than for a ! gap array). Such code is quite tricky to write, however. !  ! File: internals.info, Node: Zero-Length Extents, Next: Mathematics of Extent Ordering, Prev: Format of the Extent Info, Up: Extents ! 28.4 Zero-Length Extents ! ======================== ! Extents can be zero-length, and will end up that way if their endpoints ! are explicitly set that way or if their detachable property is `nil' ! and all the text in the extent is deleted. (The exception is open-open ! zero-length extents, which are barred from existing because there is no ! sensible way to define their properties. Deletion of the text in an ! open-open extent causes it to be converted into a closed-open extent.) ! Zero-length extents are primarily used to represent annotations, and ! behave as follows: ! 1. Insertion at the position of a zero-length extent expands the ! extent if both endpoints are closed; goes after the extent if it ! is closed-open; and goes before the extent if it is open-closed. ! 2. Deletion of a character on a side of a zero-length extent whose ! corresponding endpoint is closed causes the extent to be detached ! if it is detachable; if the extent is not detachable or the ! corresponding endpoint is open, the extent remains in the buffer, ! moving as necessary. ! Note that closed-open, non-detachable zero-length extents behave ! exactly like markers and that open-closed, non-detachable zero-length ! extents behave like the "point-type" marker in Mule. !  ! File: internals.info, Node: Mathematics of Extent Ordering, Next: Extent Fragments, Prev: Zero-Length Extents, Up: Extents ! 28.5 Mathematics of Extent Ordering ! =================================== ! The extents in a buffer are ordered by "display order" because that is ! that order that the redisplay mechanism needs to process them in. The ! e-order is an auxiliary ordering used to facilitate operations over ! extents. The operations that can be performed on the ordered list of ! extents in a buffer are ! 1. Locate where an extent would go if inserted into the list. ! 2. Insert an extent into the list. ! 3. Remove an extent from the list. ! 4. Map over all the extents that overlap a range. ! (4) requires being able to determine the first and last extents that ! overlap a range. ! NOTE: "overlap" is used as follows: ! * two ranges overlap if they have at least one point in common. ! Whether the endpoints are open or closed makes a difference here. ! * a point overlaps a range if the point is contained within the ! range; this is equivalent to treating a point P as the range [P, ! P]. ! * In the case of an _extent_ overlapping a point or range, the extent ! is normally treated as having closed endpoints. This applies ! consistently in the discussion of stacks of extents and such below. ! Note that this definition of overlap is not necessarily consistent ! with the extents that `map-extents' maps over, since `map-extents' ! sometimes pays attention to whether the endpoints of an extents ! are open or closed. But for our purposes, it greatly simplifies ! things to treat all extents as having closed endpoints. ! First, define >, <, <=, etc. as applied to extents to mean ! comparison according to the display order. Comparison between an ! extent E and an index I means comparison between E and the range [I, I]. ! Also define e>, e<, e<=, etc. to mean comparison according to the ! e-order. ! For any range R, define R(0) to be the starting index of the range ! and R(1) to be the ending index of the range. ! For any extent E, define E(next) to be the extent directly following ! E, and E(prev) to be the extent directly preceding E. Assume E(next) ! and E(prev) can be determined from E in constant time. (This is ! because we store the extent list as a doubly linked list.) ! Similarly, define E(e-next) and E(e-prev) to be the extents directly ! following and preceding E in the e-order. ! Now: ! Let R be a range. Let F be the first extent overlapping R. Let L ! be the last extent overlapping R. ! Theorem 1: R(1) lies between L and L(next), i.e. L <= R(1) < L(next). ! This follows easily from the definition of display order. The basic ! reason that this theorem applies is that the display order sorts by ! increasing starting index. ! Therefore, we can determine L just by looking at where we would ! insert R(1) into the list, and if we know F and are moving forward over ! extents, we can easily determine when we've hit L by comparing the ! extent we're at to R(1). ! Theorem 2: F(e-prev) e< [1, R(0)] e<= F. ! This is the analog of Theorem 1, and applies because the e-order ! sorts by increasing ending index. ! Therefore, F can be found in the same amount of time as operation ! (1), i.e. the time that it takes to locate where an extent would go if ! inserted into the e-order list. This is O(log N), since we are using ! gap arrays to manage extents. ! Define a "stack of extents" (or "SOE") as the set of extents ! (ordered in display order and e-order, just like for normal extent ! lists) that overlap an index I. ! Now: ! Let I be an index, let S be the stack of extents on I and let F be ! the first extent in S. ! Theorem 3: The first extent in S is the first extent that overlaps ! any range [I, J]. ! Proof: Any extent that overlaps [I, J] but does not include I must ! have a start index > I, and thus be greater than any extent in S. ! Therefore, finding the first extent that overlaps a range R is the ! same as finding the first extent that overlaps R(0). ! Theorem 4: Let I2 be an index such that I2 > I, and let F2 be the ! first extent that overlaps I2. Then, either F2 is in S or F2 is ! greater than any extent in S. ! Proof: If F2 does not include I then its start index is greater than ! I and thus it is greater than any extent in S, including F. Otherwise, ! F2 includes I and thus is in S, and thus F2 >= F. !  ! File: internals.info, Node: Extent Fragments, Prev: Mathematics of Extent Ordering, Up: Extents ! 28.6 Extent Fragments ! ===================== ! Imagine that the buffer is divided up into contiguous, non-overlapping ! "runs" of text such that no extent starts or ends within a run (extents ! that abut the run don't count). ! An extent fragment is a structure that holds data about the run that ! contains a particular buffer position (if the buffer position is at the ! junction of two runs, the run after the position is used)--the ! beginning and end of the run, a list of all of the extents in that run, ! the "merged face" that results from merging all of the faces ! corresponding to those extents, the begin and end glyphs at the ! beginning of the run, etc. This is the information that redisplay needs ! in order to display this run. ! Extent fragments have to be very quick to update to a new buffer ! position when moving linearly through the buffer. They rely on the ! stack-of-extents code, which does the heavy-duty algorithmic work of ! determining which extents overly a particular position. !  ! File: internals.info, Node: Faces, Next: Glyphs, Prev: Extents, Up: Top ! 29 Faces ! ******** ! Not yet documented. !  ! File: internals.info, Node: Glyphs, Next: Specifiers, Prev: Faces, Up: Top ! 30 Glyphs ! ********* ! Glyphs are graphical elements that can be displayed in XEmacs buffers or ! gutters. We use the term graphical element here in the broadest possible ! sense since glyphs can be as mundane as text or as arcane as a native ! tab widget. ! In XEmacs, glyphs represent the uninstantiated state of graphical ! elements, i.e. they hold all the information necessary to produce an ! image on-screen but the image need not exist at this stage, and multiple ! screen images can be instantiated from a single glyph. ! Glyphs are lazily instantiated by calling one of the glyph ! functions. This usually occurs within redisplay when `Fglyph_height' is ! called. Instantiation causes an image-instance to be created and ! cached. This cache is on a per-device basis for all glyphs except ! widget-glyphs, and on a per-window basis for widgets-glyphs. The ! caching is done by `image_instantiate' and is necessary because it is ! generally possible to display an image-instance in multiple domains. ! For instance if we create a Pixmap, we can actually display this on ! multiple windows - even though we only need a single Pixmap instance to ! do this. If caching wasn't done then it would be necessary to create ! image-instances for every displayable occurrence of a glyph - and every ! usage - and this would be extremely memory and cpu intensive. ! Widget-glyphs (a.k.a native widgets) are not cached in this way. ! This is because widget-glyph image-instances on screen are toolkit ! windows, and thus cannot be reused in multiple XEmacs domains. Thus ! widget-glyphs are cached on an XEmacs window basis. ! Any action on a glyph first consults the cache before actually ! instantiating a widget. ! 30.1 Glyph Instantiation ! ======================== ! Glyph instantiation is a hairy topic and requires some explanation. The ! guts of glyph instantiation is contained within `image_instantiate'. A ! glyph contains an image which is a specifier. When a glyph function - ! for instance `Fglyph_height' - asks for a property of the glyph that ! can only be determined from its instantiated state, then the glyph ! image is instantiated and an image instance created. The instantiation ! process is governed by the specifier code and goes through a series of ! steps: ! * Validation. Instantiation of image instances happens dynamically - ! often within the guts of redisplay. Thus it is often not feasible ! to catch instantiator errors at instantiation time. Instead the ! instantiator is validated at the time it is added to the image ! specifier. This function is defined by `image_validate' and at a ! simple level validates keyword value pairs. ! * Duplication. The specifier code by default takes a copy of the ! instantiator. This is reasonable for most specifiers but in the ! case of widget-glyphs can be problematic, since some of the ! properties in the instantiator - for instance callbacks - could ! cause infinite recursion in the copying process. Thus the image ! code defines a function - `image_copy_instantiator' - which will ! selectively copy values. This is controlled by the way that a ! keyword is defined either using `IIFORMAT_VALID_KEYWORD' or ! `IIFORMAT_VALID_NONCOPY_KEYWORD'. Note that the image caching and ! redisplay code relies on instantiator copying to ensure that ! current and new instantiators are actually different rather than ! referring to the same thing. ! * Normalization. Once the instantiator has been copied it must be ! converted into a form that is viable at instantiation time. This ! can involve no changes at all, but typically involves things like ! converting file names to the actual data. This function is defined ! by `image_going_to_add' and `normalize_image_instantiator'. ! * Instantiation. When an image instance is actually required for ! display it is instantiated using `image_instantiate'. This ! involves calling instantiate methods that are specific to the type ! of image being instantiated. ! The final instantiation phase also involves a number of steps. In ! order to understand these we need to describe a number of concepts. ! An image is instantiated in a "domain", where a domain can be any ! one of a device, frame, window or image-instance. The domain gives the ! image-instance context and identity and properties that affect the ! appearance of the image-instance may be different for the same glyph ! instantiated in different domains. An example is the face used to ! display the image-instance. ! Although an image is instantiated in a particular domain the ! instantiation domain is not necessarily the domain in which the ! image-instance is cached. For example a pixmap can be instantiated in a ! window be actually be cached on a per-device basis. The domain in which ! the image-instance is actually cached is called the "governing-domain". ! A governing-domain is currently either a device or a window. ! Widget-glyphs and text-glyphs have a window as a governing-domain, all ! other image-instances have a device as the governing-domain. The ! governing domain for an image-instance is determined using the ! governing_domain image-instance method. ! 30.2 Widget-Glyphs ! ================== ! 30.3 Widget-Glyphs in the MS-Windows Environment ! ================================================ ! To Do ! 30.4 Widget-Glyphs in the X Environment ! ======================================= ! Widget-glyphs under X make heavy use of lwlib (*note Lucid Widget ! Library::) for manipulating the native toolkit objects. This is ! primarily so that different toolkits can be supported for ! widget-glyphs, just as they are supported for features such as menubars ! etc. ! Lwlib is extremely poorly documented and quite hairy so here is my ! understanding of what goes on. ! Lwlib maintains a set of widget_instances which mirror the ! hierarchical state of Xt widgets. I think this is so that widgets can ! be updated and manipulated generically by the lwlib library. For ! instance update_one_widget_instance can cope with multiple types of ! widget and multiple types of toolkit. Each element in the widget ! hierarchy is updated from its corresponding widget_instance by walking ! the widget_instance tree recursively. ! This has desirable properties such as lw_modify_all_widgets which is ! called from `glyphs-x.c' and updates all the properties of a widget ! without having to know what the widget is or what toolkit it is from. ! Unfortunately this also has hairy properties such as making the lwlib ! code quite complex. And of course lwlib has to know at some level what ! the widget is and how to set its properties. !  ! File: internals.info, Node: Specifiers, Next: Menus, Prev: Glyphs, Up: Top ! 31 Specifiers ! ************* ! Not yet documented. ! Specifiers are documented in depth in the Lisp Reference manual. ! *Note Specifiers: (lispref)Specifiers. The code in `specifier.c' is ! pretty straightforward. !  ! File: internals.info, Node: Menus, Next: Events and the Event Loop, Prev: Specifiers, Up: Top ! 32 Menus ! ******** ! A menu is set by setting the value of the variable `current-menubar' ! (which may be buffer-local) and then calling `set-menubar-dirty-flag' ! to signal a change. This will cause the menu to be redrawn at the next ! redisplay. The format of the data in `current-menubar' is described in ! `menubar.c'. ! Internally the data in current-menubar is parsed into a tree of ! `widget_value's' (defined in `lwlib.h'); this is accomplished by the ! recursive function `menu_item_descriptor_to_widget_value()', called by ! `compute_menubar_data()'. Such a tree is deallocated using ! `free_widget_value()'. ! `update_screen_menubars()' is one of the external entry points. ! This checks to see, for each screen, if that screen's menubar needs to ! be updated. This is the case if ! 1. `set-menubar-dirty-flag' was called since the last redisplay. ! (This function sets the C variable menubar_has_changed.) ! 2. The buffer displayed in the screen has changed. ! 3. The screen has no menubar currently displayed. ! `set_screen_menubar()' is called for each such screen. This ! function calls `compute_menubar_data()' to create the tree of ! widget_value's, then calls `lw_create_widget()', ! `lw_modify_all_widgets()', and/or `lw_destroy_all_widgets()' to create ! the X-Toolkit widget associated with the menu. ! `update_psheets()', the other external entry point, actually changes ! the menus being displayed. It uses the widgets fixed by ! `update_screen_menubars()' and calls various X functions to ensure that ! the menus are displayed properly. ! The menubar widget is set up so that `pre_activate_callback()' is ! called when the menu is first selected (i.e. mouse button goes down), ! and `menubar_selection_callback()' is called when an item is selected. ! `pre_activate_callback()' calls the function in activate-menubar-hook, ! which can change the menubar (this is described in `menubar.c'). If ! the menubar is changed, `set_screen_menubars()' is called. ! `menubar_selection_callback()' enqueues a menu event, putting in it a ! function to call (either `eval' or `call-interactively') and its ! argument, which is the callback function or form given in the menu's ! description. !  ! File: internals.info, Node: Events and the Event Loop, Next: Asynchronous Events; Quit Checking, Prev: Menus, Up: Top ! 33 Events and the Event Loop ! **************************** ! * Menu: ! * Introduction to Events:: ! * Main Loop:: ! * Specifics of the Event Gathering Mechanism:: ! * Specifics About the Emacs Event:: ! * Event Queues:: ! * Event Stream Callback Routines:: ! * Other Event Loop Functions:: ! * Stream Pairs:: ! * Converting Events:: ! * Dispatching Events; The Command Builder:: ! * Focus Handling:: ! * Editor-Level Control Flow Modules:: !  ! File: internals.info, Node: Introduction to Events, Next: Main Loop, Prev: Events and the Event Loop, Up: Events and the Event Loop ! 33.1 Introduction to Events ! =========================== ! An event is an object that encapsulates information about an ! interesting occurrence in the operating system. Events are generated ! either by user action, direct (e.g. typing on the keyboard or moving ! the mouse) or indirect (moving another window, thereby generating an ! expose event on an Emacs frame), or as a result of some other typically ! asynchronous action happening, such as output from a subprocess being ! ready or a timer expiring. Events come into the system in an ! asynchronous fashion (typically through a callback being called) and ! are converted into a synchronous event queue (first-in, first-out) in a ! process that we will call "collection". ! Note that each application has its own event queue. (It is ! immaterial whether the collection process directly puts the events in ! the proper application's queue, or puts them into a single system ! queue, which is later split up.) ! The most basic level of event collection is done by the operating ! system or window system. Typically, XEmacs does its own event ! collection as well. Often there are multiple layers of collection in ! XEmacs, with events from various sources being collected into a queue, ! which is then combined with other sources to go into another queue ! (i.e. a second level of collection), with perhaps another level on top ! of this, etc. ! XEmacs has its own types of events (called "Emacs events"), which ! provides an abstract layer on top of the system-dependent nature of the ! most basic events that are received. Part of the complex nature of the ! XEmacs event collection process involves converting from the ! operating-system events into the proper Emacs events--there may not be ! a one-to-one correspondence. ! Emacs events are documented in `events.h'; I'll discuss them later. !  ! File: internals.info, Node: Main Loop, Next: Specifics of the Event Gathering Mechanism, Prev: Introduction to Events, Up: Events and the Event Loop ! 33.2 Main Loop ! ============== ! The "command loop" is the top-level loop that the editor is always ! running. It loops endlessly, calling `next-event' to retrieve an event ! and `dispatch-event' to execute it. `dispatch-event' does the ! appropriate thing with non-user events (process, timeout, magic, eval, ! mouse motion); this involves calling a Lisp handler function, redrawing ! a newly-exposed part of a frame, reading subprocess output, etc. For ! user events, `dispatch-event' looks up the event in relevant keymaps or ! menubars; when a full key sequence or menubar selection is reached, the ! appropriate function is executed. `dispatch-event' may have to keep ! state across calls; this is done in the "command-builder" structure ! associated with each console (remember, there's usually only one ! console), and the engine that looks up keystrokes and constructs full ! key sequences is called the "command builder". This is documented ! elsewhere. ! The guts of the command loop are in `command_loop_1()'. This ! function doesn't catch errors, though--that's the job of ! `command_loop_2()', which is a condition-case (i.e. error-trapping) ! wrapper around `command_loop_1()'. `command_loop_1()' never returns, ! but may get thrown out of. ! When an error occurs, `cmd_error()' is called, which usually invokes ! the Lisp error handler in `command-error'; however, a default error ! handler is provided if `command-error' is `nil' (e.g. during startup). ! The purpose of the error handler is simply to display the error message ! and do associated cleanup; it does not need to throw anywhere. When ! the error handler finishes, the condition-case in `command_loop_2()' ! will finish and `command_loop_2()' will reinvoke `command_loop_1()'. ! `command_loop_2()' is invoked from three places: from ! `initial_command_loop()' (called from `main()' at the end of internal ! initialization), from the Lisp function `recursive-edit', and from ! `call_command_loop()'. ! `call_command_loop()' is called when a macro is started and when the ! minibuffer is entered; normal termination of the macro or minibuffer ! causes a throw out of the recursive command loop. (To ! `execute-kbd-macro' for macros and `exit' for minibuffers. Note also ! that the low-level minibuffer-entering function, ! `read-minibuffer-internal', provides its own error handling and does ! not need `command_loop_2()''s error encapsulation; so it tells ! `call_command_loop()' to invoke `command_loop_1()' directly.) ! Note that both read-minibuffer-internal and recursive-edit set up a ! catch for `exit'; this is why `abort-recursive-edit', which throws to ! this catch, exits out of either one. ! `initial_command_loop()', called from `main()', sets up a catch for ! `top-level' when invoking `command_loop_2()', allowing functions to ! throw all the way to the top level if they really need to. Before ! invoking `command_loop_2()', `initial_command_loop()' calls ! `top_level_1()', which handles all of the startup stuff (creating the ! initial frame, handling the command-line options, loading the user's ! `.emacs' file, etc.). The function that actually does this is in Lisp ! and is pointed to by the variable `top-level'; normally this function is ! `normal-top-level'. `top_level_1()' is just an error-handling wrapper ! similar to `command_loop_2()'. Note also that `initial_command_loop()' ! sets up a catch for `top-level' when invoking `top_level_1()', just ! like when it invokes `command_loop_2()'. !  ! File: internals.info, Node: Specifics of the Event Gathering Mechanism, Next: Specifics About the Emacs Event, Prev: Main Loop, Up: Events and the Event Loop ! 33.3 Specifics of the Event Gathering Mechanism ! =============================================== ! Here is an approximate diagram of the collection processes at work in ! XEmacs, under TTY's (TTY's are simpler than X so we'll look at this ! first): ! asynch. asynch. asynch. asynch. [Collectors in ! kbd events kbd events process process the OS] ! | | output output ! | | | | ! | | | | SIGINT, [signal handlers ! | | | | SIGQUIT, in XEmacs] ! V V V V SIGWINCH, ! file file file file SIGALRM ! desc. desc. desc. desc. | ! (TTY) (TTY) (pipe) (pipe) | ! | | | | fake timeouts ! | | | | file | ! | | | | desc. | ! | | | | (pipe) | ! | | | | | | ! | | | | | | ! | | | | | | ! V V V V V V ! ------>-----------<----------------<---------------- ! | ! | ! | [collected using `select()' in `emacs_tty_next_event()' ! | and converted to the appropriate Emacs event] ! | ! | ! V (above this line is TTY-specific) ! Emacs ----------------------------------------------- ! event (below this line is the generic event mechanism) ! | ! | ! was there if not, call ! a SIGINT? `emacs_tty_next_event()' ! | | ! | | ! | | ! V V ! --->------<---- ! | ! | [collected in `event_stream_next_event()'; ! | SIGINT is converted using `maybe_read_quit_event()'] ! V ! Emacs ! event ! | ! \---->------>----- maybe_kbd_translate() ---->---\ ! | ! | ! | ! command event queue | ! if not from command ! (contains events that were event queue, call ! read earlier but not processed, `event_stream_next_event()' ! typically when waiting in a | ! sit-for, sleep-for, etc. for | ! a particular event to be received) | ! | | ! | | ! V V ! ---->------------------------------------<---- ! | ! | [collected in ! | `next_event_internal()'] ! | ! unread- unread- event from | ! command- command- keyboard else, call ! events event macro `next_event_internal()' ! | | | | ! | | | | ! | | | | ! V V V V ! --------->----------------------<------------ ! | ! | [collected in `next-event', which may loop ! | more than once if the event it gets is on ! | a dead frame, device, etc.] ! | ! | ! V ! feed into top-level event loop, ! which repeatedly calls `next-event' ! and then dispatches the event ! using `dispatch-event' ! Notice the separation between TTY-specific and generic event ! mechanism. When using the Xt-based event loop, the TTY-specific stuff ! is replaced but the rest stays the same. ! It's also important to realize that only one different kind of ! system-specific event loop can be operating at a time, and must be able ! to receive all kinds of events simultaneously. For the two existing ! event loops (implemented in `event-tty.c' and `event-Xt.c', ! respectively), the TTY event loop _only_ handles TTY consoles, while ! the Xt event loop handles _both_ TTY and X consoles. This situation is ! different from all of the output handlers, where you simply have one ! per console type. ! Here's the Xt Event Loop Diagram (notice that below a certain point, ! it's the same as the above diagram): ! asynch. asynch. asynch. asynch. [Collectors in ! kbd kbd process process the OS] ! events events output output ! | | | | ! | | | | asynch. asynch. [Collectors in the ! | | | | X X OS and X Window System] ! | | | | events events ! | | | | | | ! | | | | | | ! | | | | | | SIGINT, [signal handlers ! | | | | | | SIGQUIT, in XEmacs] ! | | | | | | SIGWINCH, ! | | | | | | SIGALRM ! | | | | | | | ! | | | | | | | ! | | | | | | | timeouts ! | | | | | | | | ! | | | | | | | | ! | | | | | | V | ! V V V V V V fake | ! file file file file file file file | ! desc. desc. desc. desc. desc. desc. desc. | ! (TTY) (TTY) (pipe) (pipe) (socket) (socket) (pipe) | ! | | | | | | | | ! | | | | | | | | ! | | | | | | | | ! V V V V V V V V ! --->----------------------------------------<---------<------ ! | | | ! | | |[collected using `select()' in ! | | | `_XtWaitForSomething()', called ! | | | from `XtAppProcessEvent()', called ! | | | in `emacs_Xt_next_event()'; ! | | | dispatched to various callbacks] ! | | | ! | | | ! emacs_Xt_ p_s_callback(), | [popup_selection_callback] ! event_handler() x_u_v_s_callback(),| [x_update_vertical_scrollbar_ ! | x_u_h_s_callback(),| callback] ! | search_callback() | [x_update_horizontal_scrollbar_ ! | | | callback] ! | | | ! | | | ! enqueue_Xt_ signal_special_ | ! dispatch_event() Xt_user_event() | ! [maybe multiple | | ! times, maybe 0 | | ! times] | | ! | enqueue_Xt_ | ! | dispatch_event() | ! | | | ! | | | ! V V | ! -->----------<-- | ! | | ! | | ! dispatch `Xt_what_callback()' ! event sets flags ! queue | ! | | ! | | ! | | ! | | ! ---->-----------<-------- ! | ! | ! | [collected and converted as appropriate in ! | `emacs_Xt_next_event()'] ! | ! | ! V (above this line is Xt-specific) ! Emacs ------------------------------------------------ ! event (below this line is the generic event mechanism) ! | ! | ! was there if not, call ! a SIGINT? `emacs_Xt_next_event()' ! | | ! | | ! | | ! V V ! --->-------<---- ! | ! | [collected in `event_stream_next_event()'; ! | SIGINT is converted using `maybe_read_quit_event()'] ! V ! Emacs ! event ! | ! \---->------>----- maybe_kbd_translate() -->-----\ ! | ! | ! | ! command event queue | ! if not from command ! (contains events that were event queue, call ! read earlier but not processed, `event_stream_next_event()' ! typically when waiting in a | ! sit-for, sleep-for, etc. for | ! a particular event to be received) | ! | | ! | | ! V V ! ---->----------------------------------<------ ! | ! | [collected in ! | `next_event_internal()'] ! | ! unread- unread- event from | ! command- command- keyboard else, call ! events event macro `next_event_internal()' ! | | | | ! | | | | ! | | | | ! V V V V ! --------->----------------------<------------ ! | ! | [collected in `next-event', which may loop ! | more than once if the event it gets is on ! | a dead frame, device, etc.] ! | ! | ! V ! feed into top-level event loop, ! which repeatedly calls `next-event' ! and then dispatches the event ! using `dispatch-event' !  ! File: internals.info, Node: Specifics About the Emacs Event, Next: Event Queues, Prev: Specifics of the Event Gathering Mechanism, Up: Events and the Event Loop ! 33.4 Specifics About the Emacs Event ! ==================================== !  ! File: internals.info, Node: Event Queues, Next: Event Stream Callback Routines, Prev: Specifics About the Emacs Event, Up: Events and the Event Loop ! 33.5 Event Queues ! ================= ! There are two event queues here - the command event queue (#### which ! should be called "deferred event queue" and is in my glyph ws) and the ! dispatch event queue. (MS Windows actually has an extra dispatch queue ! for non-user events and uses the generic one only for user events. This ! is because user and non-user events in Windows come through the same ! place - the window procedure - but under X, it's possible to ! selectively process events such that we take all the user events before ! the non-user ones. #### In fact, given the way we now drain the queue, ! we might need two separate queues, like under Windows. Need to think ! carefully exactly how this works, and should certainly generalize the ! two different queues. ! The dispatch queue (which used to occur duplicated inside of each ! event implementation) is used for events that have been read from the ! window-system event queue(s) and not yet process by ! `next_event_internal()'. It exists for two reasons: (1) because in many ! implementations, events often come from the window system by way of ! callbacks, and need to push the event to be returned onto a queue; (2) ! in order to handle QUIT in a guaranteed correct fashion without ! resorting to weird implementation-specific hacks that may or may not ! work well, we need to drain the window-system event queues and then look ! through to see if there's an event matching quit-char (usually ^G). the ! drained events need to go onto a queue. (There are other, similar cases ! where we need to drain the pending events so we can look ahead - for ! example, checking for pending expose events under X to avoid excessive ! server activity.) ! The command event queue is used *AFTER* an event has been read from ! `next_event_internal()', when it needs to be pushed back. This ! includes, for example, `accept-process-output', `sleep-for' and ! `wait_delaying_user_input()'. Eval events and the like, generated by ! `enqueue-eval-event', `enqueue_magic_eval_event()', etc. are also ! pushed onto this queue. Some events generated by callbacks are also ! pushed onto this queue, #### although maybe shouldn't be. ! The command queue takes precedence over the dispatch queue. ! #### It is worth investigating to see whether both queues are really ! needed, and how exactly they should be used. `enqueue-eval-event', for ! example, could certainly push onto the dispatch queue, and all ! callbacks maybe should. `wait_delaying_user_input()' seems to need ! both queues, since it can take events from the dispatch queue and push ! them onto the command queue; but it perhaps could be rewritten to avoid ! this. #### In general we need to review the handling of these two ! queues, figure out exactly what ought to be happening, and document it. !  ! File: internals.info, Node: Event Stream Callback Routines, Next: Other Event Loop Functions, Prev: Event Queues, Up: Events and the Event Loop ! 33.6 Event Stream Callback Routines ! =================================== ! There is one object called an event_stream. This object contains ! callback functions for doing the window-system-dependent operations ! that XEmacs requires. ! If XEmacs is compiled with support for X11 and the X Toolkit, then ! this event_stream structure will contain functions that can cope with ! input on XEmacs windows on multiple displays, as well as input from ! dumb tty frames. ! If it is desired to have XEmacs able to open frames on the displays ! of multiple heterogeneous machines, X11 and SunView, or X11 and NeXT, ! for example, then it will be necessary to construct an event_stream ! structure that can cope with the given types. Currently, the only ! implemented event_streams are for dumb-ttys, and for X11 plus dumb-ttys, ! and for mswindows. ! To implement this for one window system is relatively simple. To ! implement this for multiple window systems is trickier and may not be ! possible in all situations, but it's been done for X and TTY. ! Note that these callbacks are *NOT* console methods; that's because ! the routines are not specific to a particular console type but must be ! able to simultaneously cope with all allowable console types. ! The slots of the event_stream structure: ! `next_event_cb' ! A function which fills in an XEmacs_event structure with the next ! event available. If there is no event available, then this should ! block. ! IMPORTANT: timer events and especially process events *must not* be ! returned if there are events of other types available; otherwise ! you can end up with an infinite loop in `Fdiscard_input()'. ! `event_pending_cb' ! A function which says whether there are events to be read. If ! called with an argument of 0, then this should say whether calling ! the `next_event_cb' will block. If called with a non-zero ! argument, then this should say whether there are that many ! user-generated events pending (that is, keypresses, mouse-clicks, ! dialog-box selection events, etc.). (This is used for redisplay ! optimization, among other things.) The difference is that the ! former includes process events and timer events, but the latter ! doesn't. ! If this function is not sure whether there are events to be read, ! it *must* return 0. Otherwise various undesirable effects will ! occur, such as redisplay not occurring until the next event occurs. ! `handle_magic_event_cb' ! XEmacs calls this with an event structure which contains ! window-system dependent information that XEmacs doesn't need to ! know about, but which must happen in order. If the ! `next_event_cb' never returns an event of type "magic", this will ! never be used. ! `format_magic_event_cb' ! Called with a magic event; print a representation of the innards ! of the event to PSTREAM. ! `compare_magic_event_cb' ! Called with two magic events; return non-zero if the innards of ! the two are equal, zero otherwise. ! `hash_magic_event_cb' ! Called with a magic event; return a hash of the innards of the ! event. ! `add_timeout_cb' ! Called with an EMACS_TIME, the absolute time at which a wakeup ! event should be generated; and a void *, which is an arbitrary ! value that will be returned in the timeout event. The timeouts ! generated by this function should be one-shots: they fire once and ! then disappear. This callback should return an int id-number ! which uniquely identifies this wakeup. If an implementation ! doesn't have microseconds or millisecond granularity, it should ! round up to the closest value it can deal with. ! `remove_timeout_cb' ! Called with an int, the id number of a wakeup to discard. This id ! number must have been returned by the `add_timeout_cb'. If the ! given wakeup has already expired, this should do nothing. ! `select_process_cb' ! `unselect_process_cb' ! These callbacks tell the underlying implementation to add or ! remove a file descriptor from the list of fds which are polled for ! inferior-process input. When input becomes available on the given ! process connection, an event of type "process" should be generated. ! `select_console_cb' ! `unselect_console_cb' ! These callbacks tell the underlying implementation to add or ! remove a console from the list of consoles which are polled for ! user-input. ! `select_device_cb' ! `unselect_device_cb' ! These callbacks are used by Unixoid event loops (those that use ! `select()' and file descriptors and have a separate input fd per ! device). ! `create_io_streams_cb' ! `delete_io_streams_cb' ! These callbacks are called by process code to create the input and ! output lstreams which are used for subprocess I/O. ! `quitp_cb' ! A handler function called from the `QUIT' macro which should check ! whether the quit character has been typed. On systems with SIGIO, ! this will not be called unless the `sigio_happened' flag is true ! (it is set from the SIGIO handler). ! XEmacs has its own event structures, which are distinct from the ! event structures used by X or any other window system. It is the job ! of the event_stream layer to translate to this format. !  ! File: internals.info, Node: Other Event Loop Functions, Next: Stream Pairs, Prev: Event Stream Callback Routines, Up: Events and the Event Loop ! 33.7 Other Event Loop Functions ! =============================== - `detect_input_pending()' and `input-pending-p' look for input by - calling `event_stream->event_pending_p' and looking in - `[V]unread-command-event' and the `command_event_queue' (they do not - check for an executing keyboard macro, though). ! `discard-input' cancels any command events pending (and any keyboard ! macros currently executing), and puts the others onto the ! `command_event_queue'. There is a comment about a "race condition", ! which is not a good sign. ! `next-command-event' and `read-char' are higher-level interfaces to ! `next-event'. `next-command-event' gets the next "command" event (i.e. ! keypress, mouse event, menu selection, or scrollbar action), calling ! `dispatch-event' on any others. `read-char' calls `next-command-event' ! and uses `event_to_character()' to return the character equivalent. ! With the right kind of input method support, it is possible for ! (read-char) to return a Kanji character. !  ! File: internals.info, Node: Stream Pairs, Next: Converting Events, Prev: Other Event Loop Functions, Up: Events and the Event Loop ! 33.8 Stream Pairs ! ================= ! Since there are many possible processes/event loop combinations, the ! event code is responsible for creating an appropriate lstream type. The ! process implementation does not care about that implementation. ! The Create stream pair function is passed two void* values, which ! identify process-dependent 'handles'. The process implementation uses ! these handles to communicate with child processes. The function must be ! prepared to receive handle types of any process implementation. Since ! only one process implementation exists in a particular XEmacs ! configuration, preprocessing is a means of compiling in the support for ! the code which deals with particular handle types. ! For example, a unixoid type loop, which relies on file descriptors, ! may be asked to create a pair of streams by a unix-style process ! implementation. In this case, the handles passed are unix file ! descriptors, and the code may deal with these directly. Although, the ! same code may be used on Win32 system with X-Windows. In this case, ! Win32 process implementation passes handles of type HANDLE, and the ! `create_io_streams' function must call appropriate function to get file ! descriptors given HANDLEs, so that these descriptors may be passed to ! `XtAddInput'. ! The handle given may have special denying value, in which case the ! corresponding lstream should not be created. ! The return value of the function is a unique stream identifier. It ! is used by processes implementation, in its platform-independent part. ! There is the get_process_from_usid function, which returns process ! object given its USID. The event stream is responsible for converting ! its internal handle type into USID. ! Example is the TTY event stream. When a file descriptor signals ! input, the event loop must determine process to which the input is ! destined. Thus, the implementation uses process input stream file ! descriptor as USID, by simply casting the fd value to USID type. ! There are two special USID values. One, `USID_ERROR', indicates that ! the stream pair cannot be created. The second, `USID_DONTHASH', ! indicates that streams are created, but the event stream does not wish ! to be able to find the process by its USID. Specifically, if an event ! stream implementation never calls `get_process_from_usid', this value ! should always be returned, to prevent accumulating useless information ! on USID to process relationship.  ! File: internals.info, Node: Converting Events, Next: Dispatching Events; The Command Builder, Prev: Stream Pairs, Up: Events and the Event Loop ! 33.9 Converting Events ! ====================== ! `character_to_event()', `event_to_character()', `event-to-character', ! and `character-to-event' convert between characters and keypress events ! corresponding to the characters. If the event was not a keypress, ! `event_to_character()' returns -1 and `event-to-character' returns ! `nil'. These functions convert between character representation and ! the split-up event representation (keysym plus mod keys). !  ! File: internals.info, Node: Dispatching Events; The Command Builder, Next: Focus Handling, Prev: Converting Events, Up: Events and the Event Loop ! 33.10 Dispatching Events; The Command Builder ! ============================================= ! Not yet documented.  ! File: internals.info, Node: Focus Handling, Next: Editor-Level Control Flow Modules, Prev: Dispatching Events; The Command Builder, Up: Events and the Event Loop ! 33.11 Focus Handling ! ==================== ! Ben's capsule lecture on focus: ! In GNU Emacs `select-frame' never changes the window-manager frame ! focus. All it does is change the "selected frame". This is similar to ! what happens when we call `select-device' or `select-console'. ! Whenever an event comes in (including a keyboard event), its frame is ! selected; therefore, evaluating `select-frame' in `*scratch*' won't ! cause any effects because the next received event (in the same frame) ! will cause a switch back to the frame displaying `*scratch*'. ! Whenever a focus-change event is received from the window manager, it ! generates a `switch-frame' event, which causes the Lisp function ! `handle-switch-frame' to get run. This basically just runs ! `select-frame' (see below, however). ! In GNU Emacs, if you want to have an operation run when a frame is ! selected, you supply an event binding for `switch-frame' (and then ! maybe call `handle-switch-frame', or something ...). ! In XEmacs, we *do* change the window-manager frame focus as a result ! of `select-frame', but not until the next time an event is received, so ! that a function that momentarily changes the selected frame won't cause ! WM focus flashing. (#### There's something not quite right here; this ! is causing the wrong-cursor-focus problems that you occasionally see. ! But the general idea is correct.) This approach is winning for people ! who use the explicit-focus model, but is trickier to implement. ! We also don't make the `switch-frame' event visible but instead have ! `select-frame-hook', which is a better approach. ! There is the problem of surrogate minibuffers, where when we enter ! the minibuffer, you essentially want to temporarily switch the WM focus ! to the frame with the minibuffer, and switch it back when you exit the ! minibuffer. ! GNU Emacs solves this with the crockish `redirect-frame-focus', ! which says "for keyboard events received from FRAME, act like they're ! coming from FOCUS-FRAME". I think what this means is that, when a ! keyboard event comes in and the event manager is about to select the ! event's frame, if that frame has its focus redirected, the redirected-to ! frame is selected instead. That way, if you're in a minibufferless ! frame and enter the minibuffer, then all Lisp functions that run see the ! selected frame as the minibuffer's frame rather than the minibufferless ! frame you came from, so that (e.g.) your typing actually appears in the ! minibuffer's frame and things behave sanely. ! There's also some weird logic that switches the redirected frame ! focus from one frame to another if Lisp code explicitly calls ! `select-frame' (but not if `handle-switch-frame' is called), and saves ! and restores the frame focus in window configurations, etc. etc. All ! of this logic is heavily `#if 0''d, with lots of comments saying "No, ! this approach doesn't seem to work, so I'm trying this ... is it ! reasonable? Well, I'm not sure ..." that are a red flag indicating ! crockishness. ! Because of our way of doing things, we can avoid all this crock. ! Keyboard events never cause a select-frame (who cares what frame they're ! associated with? They come from a console, only). We change the actual ! WM focus to a surrogate minibuffer frame, so we don't have to do any ! internal redirection. In order to get the focus back, I took the ! approach in `minibuf.el' of just checking to see if the frame we moved ! to is still the selected frame, and move back to the old one if so. ! Conceivably we might have to do the weird "tracking" that GNU Emacs does ! when `select-frame' is called, but I don't think so. If the selected ! frame moved from the minibuffer frame, then we just leave it there, ! figuring that someone knows what they're doing. Because we don't have ! any redirection recorded anywhere, it's safe to do this, and we don't ! end up with unwanted redirection. !  ! File: internals.info, Node: Editor-Level Control Flow Modules, Prev: Focus Handling, Up: Events and the Event Loop ! 33.12 Editor-Level Control Flow Modules ! ======================================= ! `event-Xt.c' ! `event-msw.c' ! `event-stream.c' ! `event-tty.c' ! `events-mod.h' ! `gpmevent.c' ! `gpmevent.h' ! `events.c' ! `events.h' ! These implement the handling of events (user input and other system ! notifications). ! `events.c' and `events.h' define the "event" Lisp object type and ! primitives for manipulating it. ! `event-stream.c' implements the basic functions for working with ! event queues, dispatching an event by looking it up in relevant keymaps ! and such, and handling timeouts; this includes the primitives ! `next-event' and `dispatch-event', as well as related primitives such ! as `sit-for', `sleep-for', and `accept-process-output'. ! (`event-stream.c' is one of the hairiest and trickiest modules in ! XEmacs. Beware! You can easily mess things up here.) ! `event-Xt.c' and `event-tty.c' implement the low-level interfaces ! onto retrieving events from Xt (the X toolkit) and from TTY's (using ! `read()' and `select()'), respectively. The event interface enforces a ! clean separation between the specific code for interfacing with the ! operating system and the generic code for working with events, by ! defining an API of basic, low-level event methods; `event-Xt.c' and ! `event-tty.c' are two different implementations of this API. To add ! support for a new operating system (e.g. NeXTstep), one merely needs to ! provide another implementation of those API functions. ! Note that the choice of whether to use `event-Xt.c' or `event-tty.c' ! is made at compile time! Or at the very latest, it is made at startup ! time. `event-Xt.c' handles events for _both_ X and TTY frames; ! `event-tty.c' is only used when X support is not compiled into XEmacs. ! The reason for this is that there is only one event loop in XEmacs: ! thus, it needs to be able to receive events from all different kinds of ! frames. ! `keymap.c' ! `keymap.h' ! `keymap.c' and `keymap.h' define the "keymap" Lisp object type and ! associated methods and primitives. (Remember that keymaps are objects ! that associate event descriptions with functions to be called to ! "execute" those events; `dispatch-event' looks up events in the ! relevant keymaps.) ! `cmdloop.c' ! `cmdloop.c' contains functions that implement the actual editor ! command loop--i.e. the event loop that cyclically retrieves and ! dispatches events. This code is also rather tricky, just like ! `event-stream.c'. ! `macros.c' ! `macros.h' ! These two modules contain the basic code for defining keyboard ! macros. These functions don't actually do much; most of the code that ! handles keyboard macros is mixed in with the event-handling code in ! `event-stream.c'. ! `minibuf.c' ! This contains some miscellaneous code related to the minibuffer ! (most of the minibuffer code was moved into Lisp by Richard Mlynarik). ! This includes the primitives for completion (although filename ! completion is in `dired.c'), the lowest-level interface to the ! minibuffer (if the command loop were cleaned up, this too could be in ! Lisp), and code for dealing with the echo area (this, too, was mostly ! moved into Lisp, and the only code remaining is code to call out to ! Lisp or provide simple bootstrapping implementations early in temacs, ! before the echo-area Lisp code is loaded). !  ! File: internals.info, Node: Asynchronous Events; Quit Checking, Next: Lstreams, Prev: Events and the Event Loop, Up: Top ! 34 Asynchronous Events; Quit Checking ! ************************************* ! * Menu: ! * Signal Handling:: ! * Control-G (Quit) Checking:: ! * Profiling:: ! * Asynchronous Timeouts:: ! * Exiting:: !  ! File: internals.info, Node: Signal Handling, Next: Control-G (Quit) Checking, Prev: Asynchronous Events; Quit Checking, Up: Asynchronous Events; Quit Checking ! 34.1 Signal Handling ! ==================== !  ! File: internals.info, Node: Control-G (Quit) Checking, Next: Profiling, Prev: Signal Handling, Up: Asynchronous Events; Quit Checking ! 34.2 Control-G (Quit) Checking ! ============================== ! _Note_: The code to handle QUIT is divided between `lisp.h' and ! `signal.c'. There is also some special-case code in the async timer ! code in `event-stream.c' to notice when the poll-for-quit (and ! poll-for-sigchld) timers have gone off. ! Here's an overview of how this convoluted stuff works: ! 1. Scattered throughout the XEmacs core code are calls to the macro ! QUIT; This macro checks to see whether a `C-g' has recently been ! pressed and not yet handled, and if so, it handles the `C-g' by ! calling `signal_quit()', which invokes the standard `Fsignal()' ! code, with the error being `Qquit'. Lisp code can establish ! handlers for this (using `condition-case'), but normally there is ! no handler, and so execution is thrown back to the innermost ! enclosing event loop. (One of the things that happens when ! entering an event loop is that a `condition-case' is established ! that catches *all* calls to `signal', including this one.) ! 2. How does the QUIT macro check to see whether `C-g' has been ! pressed; obviously this needs to be extremely fast. Now for some ! history. In early Lemacs as inherited from the FSF going back 15 ! years or more, there was a great fondness for using SIGIO (which ! is sent whenever there is I/O available on a given socket, tty, ! etc.). In fact, in GNU Emacs, perhaps even today, all reading of ! events from the X server occurs inside the SIGIO handler! This is ! crazy, but not completely relevant. What is relevant is that ! similar stuff happened inside the SIGIO handler for `C-g': it ! searched through all the pending (i.e. not yet delivered to XEmacs ! yet) X events for one that matched `C-g'. When it saw a match, it ! set Vquit_flag to Qt. On TTY's, `C-g' is actually mapped to be the ! interrupt character (i.e. it generates SIGINT), and XEmacs's ! handler for this signal sets Vquit_flag to Qt. Then, sometime ! later after the signal handlers finished and a QUIT macro was ! called, the macro noticed the setting of `Vquit_flag' and used ! this as an indication to call `signal_quit()'. What ! `signal_quit()' actually does is set `Vquit_flag' to Qnil (so that ! we won't get repeated interruptions from a single `C-g' press) and ! then calls the equivalent of (signal 'quit nil). ! 3. Another complication is introduced in that Vquit_flag is actually ! exported to Lisp as `quit-flag'. This allows users some level of ! control over whether and when `C-g' is processed as quit, esp. in ! combination with `inhibit-quit'. This is another Lisp variable, ! and if set to non-nil, it inhibits `signal_quit()' from getting ! called, meaning that the `C-g' gets essentially ignored. But not ! completely: Because the resetting of `quit-flag' happens only in ! `signal_quit()', which isn't getting called, the `C-g' press is ! still noticed, and as soon as `inhibit-quit' is set back to nil, a ! quit will be signalled at the next QUIT macro. Thus, what ! `inhibit-quit' really does is defer quits until after the quit- ! inhibitted period. ! 4. Another consideration, introduced by XEmacs, is critical quitting. ! If you press `Control-Shift-G' instead of just `C-g', `quit-flag' ! is set to `critical' instead of to t. When QUIT processes this ! value, it *ignores* the value of `inhibit-quit'. This allows you ! to quit even out of a quit-inhibitted section of code! ! Furthermore, when `signal_quit()' notices that it was invoked as a ! result of a critical quit, it automatically invokes the debugger ! (which otherwise would only happen when `debug-on-quit' is set to ! t). ! 5. Well, I explained above about how `quit-flag' gets set correctly, ! but I began with a disclaimer stating that this was the old way of ! doing things. What's done now? Well, first of all, the SIGIO ! handler (which formerly checked all pending events to see if ! there's a `C-g') now does nothing but set a flag - or actually two ! flags, something_happened and quit_check_signal_happened. There ! are two flags because the QUIT macro is now used for more than ! just handling QUIT; it's also used for running asynchronous ! timeout handlers that have recently expired, and perhaps other ! things. The idea here is that the QUIT macros occur extremely ! often in the code, but only occur at places that are relatively ! safe - in particular, if an error occurs, nothing will get ! completely trashed. ! 6. Now, let's look at QUIT again. ! 7. UNFINISHED. Note, however, that as of the point when this ! comment got committed to CVS (mid-2001), the interaction between ! reading `C-g' as an event and processing it as QUIT was overhauled ! to (for the first time) be understandable and actually work ! correctly. Now, the way things work is that if `C-g' is pressed ! while XEmacs is blocking at the top level, waiting for a user ! event, it will be read as an event; otherwise, it will cause QUIT. ! (This includes times when XEmacs is blocking, but not waiting for ! a user event, e.g. `accept-process-output' and ! `wait_delaying_user_events()'.) Formerly, this was supposed to ! happen, but didn't always due to a bizarre and broken scheme, ! documented in `next_event_internal' like this: ! If we read a `C-g', then set `quit-flag' but do not discard ! the `C-g'. The callers of `next_event_internal()' will do ! one of two things: ! 1. set `Vquit_flag' to Qnil. (`next-event' does this.) This ! will cause the ^G to be treated as a normal keystroke. ! 2. not change `Vquit_flag' but attempt to enqueue the ^G, ! at which point it will be discarded. The next time QUIT ! is called, it will notice that `Vquit_flag' was set. ! This required weirdness in `enqueue_command_event_1' like this: ! put the event on the typeahead queue, unless the event is the ! quit char, in which case the `QUIT' which will occur on the ! next trip through this loop is all the processing we should ! do - leaving it on the queue would cause the quit to be ! processed twice. ! And further weirdness elsewhere, none of which made any sense, and ! didn't work, because (e.g.) it required that QUIT never happen ! anywhere inside `next_event_internal()' or any callers when `C-g' ! should be read as a user event, which was impossible to implement ! in practice. ! Now what we do is fairly simple. Callers of ! `next_event_internal()' that want `C-g' read as a user event call ! `begin_dont_check_for_quit()'. `next_event_internal()', when it ! gets a `C-g', simply sets `Vquit_flag' (just as when a `C-g' is ! detected during the operation of `QUIT' or `QUITP'), and then ! tries to `QUIT'. This will fail if blocked by the previous call, ! at which point `next_event_internal()' will return the `C-g' as an ! event. To unblock things, first set `Vquit_flag' to nil (it was ! set to t when the `C-g' was read, and if we don't reset it, the ! next call to `QUIT' will quit), and then `unbind_to()' the depth ! returned by `begin_dont_check_for_quit()'. It makes no difference ! is `QUIT' is called a zillion times in `next_event_internal()' or ! anywhere else, because it's blocked and will never signal. ! 34.2.1 Reentrancy Problems due to QUIT Checking ! ----------------------------------------------- ! Checking for QUIT can do quite a long of things - since it pumps the ! event loop, this may cause arbitrary code to get executed, garbage ! collection to happen. etc. (In fact, garbage collection cannot happen ! because it is inhibited.) This has led to crashes when functions get ! called reentrantly when not expecting it. Example: ! Crash - reentrant `re_match_2()' ! -------------------------------- ! /* dont_check_for_quit is set in three circumstances: ! (1) when we are in the process of changing the window ! configuration. The frame might be in an inconsistent state, ! which will cause assertion failures if we check for QUIT. ! (2) when we are reading events, and want to read the C-g ! as an event. The normal check for quit will discard the C-g, ! which would be bad. ! (3) when we're going down with a fatal error. we're most likely ! in an inconsistent state, and we definitely don't want to be ! interrupted. */ ! /* We should *not* conditionalize on Vinhibit_quit, or ! critical-quit (Control-Shift-G) won't work right. */ ! /* WARNING: Even calling check_quit(), without actually dispatching ! a quit signal, can result in arbitrary Lisp code getting executed ! -- at least under Windows. (Not to mention obvious Lisp ! invocations like asynchronous timer callbacks.) Here's a sample ! stack trace to demonstrate: ! NTDLL! DbgBreakPoint@0 address 0x77f9eea9 ! assert_failed(const char * 0x012d036c, int 4596, const char * 0x012d0354) line 3478 ! re_match_2_internal(re_pattern_buffer * 0x012d6780, const unsigned char * 0x00000000, int 0, const unsigned char * 0x022f9328, int 34, int 0, re_registers * 0x012d53d0 search_regs, int 34) line 4596 + 41 bytes ! re_search_2(re_pattern_buffer * 0x012d6780, const char * 0x00000000, int 0, const char * 0x022f9328, int 34, int 0, int 34, re_registers * 0x012d53d0 search_regs, int 34) line 4269 + 37 bytes ! re_search(re_pattern_buffer * 0x012d6780, const char * 0x022f9328, int 34, int 0, int 34, re_registers * 0x012d53d0 search_regs) line 4031 + 37 bytes ! string_match_1(long 31222628, long 30282164, long 28377092, buffer * 0x022fde00, int 0) line 413 + 69 bytes ! Fstring_match(long 31222628, long 30282164, long 28377092, long 28377092) line 436 + 34 bytes ! Ffuncall(int 3, long * 0x008297f8) line 3488 + 168 bytes ! execute_optimized_program(const unsigned char * 0x020ddc50, int 6, long * 0x020ddf50) line 744 + 16 bytes ! funcall_compiled_function(long 34407748, int 1, long * 0x00829aec) line 516 + 53 bytes ! Ffuncall(int 2, long * 0x00829ae8) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x020ddc90, int 4, long * 0x020ddf90) line 744 + 16 bytes ! funcall_compiled_function(long 34407720, int 1, long * 0x00829e28) line 516 + 53 bytes ! Ffuncall(int 2, long * 0x00829e24) line 3523 + 17 bytes ! mapcar1(long 15, long * 0x00829e48, long 34447820, long 34187868) line 2929 + 11 bytes ! Fmapcar(long 34447820, long 34187868) line 3035 + 21 bytes ! Ffuncall(int 3, long * 0x00829f20) line 3488 + 93 bytes ! execute_optimized_program(const unsigned char * 0x020c2b70, int 7, long * 0x020dd010) line 744 + 16 bytes ! funcall_compiled_function(long 34407580, int 2, long * 0x0082a210) line 516 + 53 bytes ! Ffuncall(int 3, long * 0x0082a20c) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x020cf810, int 6, long * 0x020cfb10) line 744 + 16 bytes ! funcall_compiled_function(long 34407524, int 0, long * 0x0082a580) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082a57c) line 3523 + 17 bytes ! run_hook_with_args_in_buffer(buffer * 0x022fde00, int 1, long * 0x0082a57c, int 0) line 3980 + 13 bytes ! run_hook_with_args(int 1, long * 0x0082a57c, int 0) line 3993 + 23 bytes ! Frun_hooks(int 1, long * 0x0082a57c) line 3847 + 19 bytes ! run_hook(long 34447484) line 4094 + 11 bytes ! unsafe_handle_wm_initmenu_1(frame * 0x01dbb000) line 736 + 11 bytes ! unsafe_handle_wm_initmenu(long 28377092) line 807 + 11 bytes ! condition_case_1(long 28377116, long (long)* 0x0101c827 unsafe_handle_wm_initmenu(long), long 28377092, long (long, long)* 0x01005fa4 mswindows_modal_loop_error_handler(long, long), long 28377092) line 1692 + 7 bytes ! mswindows_protect_modal_loop(long (long)* 0x0101c827 unsafe_handle_wm_initmenu(long), long 28377092) line 1194 + 32 bytes ! mswindows_handle_wm_initmenu(HMENU__ * 0x00010199, frame * 0x01dbb000) line 826 + 17 bytes ! mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 278, unsigned int 65945, long 0) line 3089 + 31 bytes ! USER32! UserCallWinProc@20 + 24 bytes ! USER32! DispatchClientMessage@20 + 47 bytes ! USER32! __fnDWORD@4 + 34 bytes ! NTDLL! KiUserCallbackDispatcher@12 + 19 bytes ! USER32! DispatchClientMessage@20 address 0x77e163cc ! USER32! DefWindowProcW@16 + 34 bytes ! qxeDefWindowProc(HWND__ * 0x000501da, unsigned int 274, unsigned int 61696, long 98) line 1188 + 22 bytes ! mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 274, unsigned int 61696, long 98) line 3362 + 21 bytes ! USER32! UserCallWinProc@20 + 24 bytes ! USER32! DispatchClientMessage@20 + 47 bytes ! USER32! __fnDWORD@4 + 34 bytes ! NTDLL! KiUserCallbackDispatcher@12 + 19 bytes ! USER32! DispatchClientMessage@20 address 0x77e163cc ! USER32! DefWindowProcW@16 + 34 bytes ! qxeDefWindowProc(HWND__ * 0x000501da, unsigned int 262, unsigned int 98, long 540016641) line 1188 + 22 bytes ! mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 262, unsigned int 98, long 540016641) line 3362 + 21 bytes ! USER32! UserCallWinProc@20 + 24 bytes ! USER32! DispatchMessageWorker@8 + 244 bytes ! USER32! DispatchMessageW@4 + 11 bytes ! qxeDispatchMessage(const tagMSG * 0x0082c684 {msg=0x00000106 wp=0x00000062 lp=0x20300001}) line 989 + 10 bytes ! mswindows_drain_windows_queue() line 1345 + 9 bytes ! emacs_mswindows_quit_p() line 3947 ! event_stream_quit_p() line 666 ! check_quit() line 686 ! check_what_happened() line 437 ! re_match_2_internal(re_pattern_buffer * 0x012d5a18, const unsigned char * 0x00000000, int 0, const unsigned char * 0x02235000, int 23486, int 14645, re_registers * 0x012d53d0 search_regs, int 23486) line 4717 + 14 bytes ! re_search_2(re_pattern_buffer * 0x012d5a18, const char * 0x02235000, int 23486, const char * 0x0223b38e, int 0, int 14645, int 8841, re_registers * 0x012d53d0 search_regs, int 23486) line 4269 + 37 bytes ! search_buffer(buffer * 0x022fde00, long 29077572, long 13789, long 23487, long 1, int 1, long 28377092, long 28377092, int 0) line 1224 + 89 bytes ! search_command(long 29077572, long 46975, long 28377116, long 28377092, long 28377092, int 1, int 1, int 0) line 1054 + 151 bytes ! Fre_search_forward(long 29077572, long 46975, long 28377116, long 28377092, long 28377092) line 2147 + 31 bytes ! Ffuncall(int 4, long * 0x0082ceb0) line 3488 + 216 bytes ! execute_optimized_program(const unsigned char * 0x02047810, int 13, long * 0x02080c10) line 744 + 16 bytes ! funcall_compiled_function(long 34187208, int 3, long * 0x0082d1b8) line 516 + 53 bytes ! Ffuncall(int 4, long * 0x0082d1b4) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x01e96a10, int 6, long * 0x020ae510) line 744 + 16 bytes ! funcall_compiled_function(long 34186676, int 3, long * 0x0082d4a0) line 516 + 53 bytes ! Ffuncall(int 4, long * 0x0082d49c) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02156b50, int 4, long * 0x020c2db0) line 744 + 16 bytes ! funcall_compiled_function(long 34186564, int 2, long * 0x0082d780) line 516 + 53 bytes ! Ffuncall(int 3, long * 0x0082d77c) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x0082d964, int 3, long * 0x020c2d70) line 744 + 16 bytes ! Fbyte_code(long 29405156, long 34352480, long 7) line 2392 + 38 bytes ! Feval(long 34354440) line 3290 + 187 bytes ! condition_case_1(long 34354572, long (long)* 0x01087232 Feval(long), long 34354440, long (long, long)* 0x01084764 run_condition_case_handlers(long, long), long 28377092) line 1692 + 7 bytes ! condition_case_3(long 34354440, long 28377092, long 34354572) line 1779 + 27 bytes ! execute_rare_opcode(long * 0x0082dc7c, const unsigned char * 0x01b090af, int 143) line 1269 + 19 bytes ! execute_optimized_program(const unsigned char * 0x01b09090, int 6, long * 0x020ae590) line 654 + 17 bytes ! funcall_compiled_function(long 34186620, int 0, long * 0x0082df68) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082df64) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02195470, int 1, long * 0x020c2df0) line 744 + 16 bytes ! funcall_compiled_function(long 34186508, int 0, long * 0x0082e23c) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082e238) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x01e5d410, int 6, long * 0x0207d410) line 744 + 16 bytes ! funcall_compiled_function(long 34186312, int 1, long * 0x0082e524) line 516 + 53 bytes ! Ffuncall(int 2, long * 0x0082e520) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02108fb0, int 2, long * 0x020c2e30) line 744 + 16 bytes ! funcall_compiled_function(long 34186340, int 0, long * 0x0082e7fc) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082e7f8) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x020fe150, int 2, long * 0x01e6f510) line 744 + 16 bytes ! funcall_compiled_function(long 31008124, int 0, long * 0x0082ebd8) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082ebd4) line 3523 + 17 bytes ! run_hook_with_args_in_buffer(buffer * 0x022fde00, int 1, long * 0x0082ebd4, int 0) line 3980 + 13 bytes ! run_hook_with_args(int 1, long * 0x0082ebd4, int 0) line 3993 + 23 bytes ! Frun_hooks(int 1, long * 0x0082ebd4) line 3847 + 19 bytes ! Ffuncall(int 2, long * 0x0082ebd0) line 3509 + 14 bytes ! execute_optimized_program(const unsigned char * 0x01ef2210, int 5, long * 0x01da8e10) line 744 + 16 bytes ! funcall_compiled_function(long 31020440, int 2, long * 0x0082eeb8) line 516 + 53 bytes ! Ffuncall(int 3, long * 0x0082eeb4) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x0082f09c, int 3, long * 0x01d89390) line 744 + 16 bytes ! Fbyte_code(long 31102388, long 30970752, long 7) line 2392 + 38 bytes ! Feval(long 31087568) line 3290 + 187 bytes ! condition_case_1(long 30961240, long (long)* 0x01087232 Feval(long), long 31087568, long (long, long)* 0x01084764 run_condition_case_handlers(long, long), long 28510180) line 1692 + 7 bytes ! condition_case_3(long 31087568, long 28510180, long 30961240) line 1779 + 27 bytes ! execute_rare_opcode(long * 0x0082f450, const unsigned char * 0x01ef23ec, int 143) line 1269 + 19 bytes ! execute_optimized_program(const unsigned char * 0x01ef2310, int 6, long * 0x01da8f10) line 654 + 17 bytes ! funcall_compiled_function(long 31020412, int 1, long * 0x0082f740) line 516 + 53 bytes ! Ffuncall(int 2, long * 0x0082f73c) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x020fe650, int 3, long * 0x01d8c490) line 744 + 16 bytes ! funcall_compiled_function(long 31020020, int 2, long * 0x0082fa14) line 516 + 53 bytes ! Ffuncall(int 3, long * 0x0082fa10) line 3523 + 17 bytes ! Fcall_interactively(long 29685180, long 28377092, long 28377092) line 1008 + 22 bytes ! Fcommand_execute(long 29685180, long 28377092, long 28377092) line 2929 + 17 bytes ! execute_command_event(command_builder * 0x01be1900, long 36626492) line 4048 + 25 bytes ! Fdispatch_event(long 36626492) line 4341 + 70 bytes ! Fcommand_loop_1() line 582 + 9 bytes ! command_loop_1(long 28377092) line 495 ! condition_case_1(long 28377188, long (long)* 0x01064fb9 command_loop_1(long), long 28377092, long (long, long)* 0x010649d0 cmd_error(long, long), long 28377092) line 1692 + 7 bytes ! command_loop_3() line 256 + 35 bytes ! command_loop_2(long 28377092) line 269 ! internal_catch(long 28457612, long (long)* 0x01064b20 command_loop_2(long), long 28377092, int * volatile 0x00000000) line 1317 + 7 bytes ! initial_command_loop(long 28377092) line 305 + 25 bytes ! STACK_TRACE_EYE_CATCHER(int 1, char * * 0x01b63ff0, char * * 0x01ca5300, int 0) line 2501 ! main(int 1, char * * 0x01b63ff0, char * * 0x01ca5300) line 2938 ! XEMACS! mainCRTStartup + 180 bytes ! _start() line 171 ! KERNEL32! BaseProcessStart@4 + 115547 bytes ! ! [explain dont_check_for_quit() et al] ! !  ! File: internals.info, Node: Profiling, Next: Asynchronous Timeouts, Prev: Control-G (Quit) Checking, Up: Asynchronous Events; Quit Checking ! ! 34.3 Profiling ! ============== ! ! We implement our own profiling scheme so that we can determine things ! like which Lisp functions are occupying the most time. Any standard ! OS-provided profiling works on C functions, which is not always that ! useful - and inconvenient, since it requires compiling with profile ! info and can't be retrieved dynamically, as XEmacs is running. ! ! The basic idea is simple. We set a profiling timer using setitimer ! (ITIMER_PROF), which generates a SIGPROF every so often. (This runs not ! in real time but rather when the process is executing or the system is ! running on behalf of the process - at least, that is the case under ! Unix. Under MS Windows and Cygwin, there is no `setitimer()', so we ! simulate it using multimedia timers, which run in real time. To make ! the results a bit more realistic, we ignore ticks that go off while ! blocking on an event wait. Note that Cygwin does provide a simulation ! of `setitimer()', but it's in real time anyway, since Windows doesn't ! provide a way to have process-time timers, and furthermore, it's broken, ! so we don't use it.) When the signal goes off, we see what we're in, and ! add 1 to the count associated with that function. ! ! It would be nice to use the Lisp allocation mechanism etc. to keep ! track of the profiling information (i.e. to use Lisp hash tables), but ! we can't because that's not safe - updating the timing information ! happens inside of a signal handler, so we can't rely on not being in ! the middle of Lisp allocation, garbage collection, `malloc()', etc. ! Trying to make it work would be much more work than it's worth. ! Instead we use a basic (non-Lisp) hash table, which will not conflict ! with garbage collection or anything else as long as it doesn't try to ! resize itself. Resizing itself, however (which happens as a result of ! a `puthash()'), could be deadly. To avoid this, we make sure, at ! points where it's safe (e.g. `profile_record_about_to_call()' - ! recording the entry into a function call), that the table always has ! some breathing room in it so that no resizes will occur until at least ! that many items are added. This is safe because any new item to be ! added in the sigprof would likely have the ! `profile_record_about_to_call()' called just before it, and the ! breathing room is checked. ! In general: any entry that the sigprof handler puts into the table ! comes from a backtrace frame (except "Processing Events at Top Level", ! and there's only one of those). Either that backtrace frame was added ! when profiling was on (in which case `profile_record_about_to_call()' ! was called and the breathing space updated), or when it was off - and in ! this case, no such frames can have been added since the last time ! `start-profile' was called, so when `start-profile' is called we make ! sure there is sufficient breathing room to account for all entries ! currently on the stack. ! Jan 1998: In addition to timing info, I have added code to remember ! call counts of Lisp funcalls. The `profile_increase_call_count()' ! function is called from `Ffuncall()', and serves to add data to ! Vcall_count_profile_table. This mechanism is much simpler and ! independent of the SIGPROF-driven one. It uses the Lisp allocation ! mechanism normally, since it is not called from a handler. It may even ! be useful to provide a way to turn on only one profiling mechanism, but ! I haven't done so yet. -hniksic ! Dec 2002: Total overhaul of the interface, making it sane and easier ! to use. -ben ! Feb 2003: Lots of rewriting of the internal code. Add ! GC-consing-usage, total GC usage, and total timing to the information ! tracked. Track profiling overhead and allow the ability to have ! internal sections (e.g. internal-external conversion, byte-char ! conversion) that are treated like Lisp functions for the purpose of ! profiling. -ben ! BEWARE: If you are modifying this file, be *very* careful. Correctly ! implementing the "total" values is very tricky due to the possibility of ! recursion and of functions already on the stack when starting to ! profile/still on the stack when stopping.  ! File: internals.info, Node: Asynchronous Timeouts, Next: Exiting, Prev: Profiling, Up: Asynchronous Events; Quit Checking ! 34.4 Asynchronous Timeouts ! ========================== !  ! File: internals.info, Node: Exiting, Prev: Asynchronous Timeouts, Up: Asynchronous Events; Quit Checking ! 34.5 Exiting ! ============ ! Ben's capsule summary about expected and unexpected exits from XEmacs. ! Expected exits occur when the user directs XEmacs to exit, for ! example by pressing the close button on the only frame in XEmacs, or by ! typing `C-x C-c'. This runs `save-buffers-kill-emacs', which saves any ! necessary buffers, and then exits using the primitive `kill-emacs'. ! However, unexpected exits occur in a few different ways: ! * A memory access violation or other hardware-generated exception ! occurs. This is the worst possible problem to deal with, because ! the fault can occur while XEmacs is in any state whatsoever, even ! quite unstable ones. As a result, we need to be *extremely* ! careful what we do. ! * We are using one X display (or if we've used more, we've closed the ! others already), and some hardware or other problem happens and ! suddenly we've lost our connection to the display. In this ! situation, things are not so dire as in the last one; our code ! itself isn't trashed, so we can continue execution as normal, ! after having set things up so that we can exit at the appropriate ! time. Our exit still needs to be of the emergency nature; we have ! no displays, so any attempts to use them will fail. We simply ! want to auto-save (the single most important thing to do during ! shut-down), do minimal cleanup of stuff that has an independent ! existence outside of XEmacs, and exit. ! Currently, both unexpected exit scenarios described above set ! `preparing_for_armageddon' to indicate that nonessential and possibly ! dangerous things should not be done, specifically: ! - no garbage collection. ! - no hooks are run. ! - no messages of any sort from autosaving. ! - autosaving tries harder, ignoring certain failures. ! - existing frames are not deleted. ! (Also, all places that set `preparing_for_armageddon' also set ! `dont_check_for_quit'. This happens separately because it's also ! necessary to set other variables to make absolutely sure no quitting ! happens.) ! In the first scenario above (the access violation), we also set ! `fatal_error_in_progress'. This causes more things to not happen: ! - assertion failures do not abort. ! - printing code does not do code conversion or gettext when printing ! to stdout/stderr. !  ! File: internals.info, Node: Lstreams, Next: Subprocesses, Prev: Asynchronous Events; Quit Checking, Up: Top ! 35 Lstreams ! *********** ! An "lstream" is an internal Lisp object that provides a generic ! buffering stream implementation. Conceptually, you send data to the ! stream or read data from the stream, not caring what's on the other end ! of the stream. The other end could be another stream, a file ! descriptor, a stdio stream, a fixed block of memory, a reallocating ! block of memory, etc. The main purpose of the stream is to provide a ! standard interface and to do buffering. Macros are defined to read or ! write characters, so the calling functions do not have to worry about ! blocking data together in order to achieve efficiency. ! * Menu: ! * Creating an Lstream:: Creating an lstream object. ! * Lstream Types:: Different sorts of things that are streamed. ! * Lstream Functions:: Functions for working with lstreams. ! * Lstream Methods:: Creating new lstream types. !  ! File: internals.info, Node: Creating an Lstream, Next: Lstream Types, Prev: Lstreams, Up: Lstreams - 35.1 Creating an Lstream - ======================== ! Lstreams come in different types, depending on what is being interfaced ! to. Although the primitive for creating new lstreams is ! `Lstream_new()', generally you do not call this directly. Instead, you ! call some type-specific creation function, which creates the lstream ! and initializes it as appropriate for the particular type. ! All lstream creation functions take a MODE argument, specifying what ! mode the lstream should be opened as. This controls whether the ! lstream is for input and output, and optionally whether data should be ! blocked up in units of MULE characters. Note that some types of ! lstreams can only be opened for input; others only for output; and ! others can be opened either way. #### Richard Mlynarik thinks that ! there should be a strict separation between input and output streams, ! and he's probably right. ! ! MODE is a string, one of ! ! `"r"' ! Open for reading. ! ! `"w"' ! Open for writing. ! ! `"rc"' ! Open for reading, but "read" never returns partial MULE characters. ! ! `"wc"' ! Open for writing, but never writes partial MULE characters. ! !  ! File: internals.info, Node: Lstream Types, Next: Lstream Functions, Prev: Creating an Lstream, Up: Lstreams ! ! 35.2 Lstream Types ! ================== ! ! stdio ! ! filedesc ! ! lisp-string ! ! fixed-buffer ! ! resizing-buffer ! ! dynarr ! ! lisp-buffer ! ! print ! ! decoding ! encoding !  ! File: internals.info, Node: Lstream Functions, Next: Lstream Methods, Prev: Lstream Types, Up: Lstreams ! 35.3 Lstream Functions ! ====================== ! -- Function: Lstream * Lstream_new (Lstream_implementation *IMP, const ! char *MODE) ! Allocate and return a new Lstream. This function is not really ! meant to be called directly; rather, each stream type should ! provide its own stream creation function, which creates the stream ! and does any other necessary creation stuff (e.g. opening a file). ! -- Function: void Lstream_set_buffering (Lstream *LSTR, ! Lstream_buffering BUFFERING, int BUFFERING_SIZE) ! Change the buffering of a stream. See `lstream.h'. By default the ! buffering is `STREAM_BLOCK_BUFFERED'. ! -- Function: int Lstream_flush (Lstream *LSTR) ! Flush out any pending unwritten data in the stream. Clear any ! buffered input data. Returns 0 on success, -1 on error. ! -- Macro: int Lstream_putc (Lstream *STREAM, int C) ! Write out one byte to the stream. This is a macro and so it is ! very efficient. The C argument is only evaluated once but the ! STREAM argument is evaluated more than once. Returns 0 on ! success, -1 on error. ! -- Macro: int Lstream_getc (Lstream *STREAM) ! Read one byte from the stream. This is a macro and so it is very ! efficient. The STREAM argument is evaluated more than once. ! Return value is -1 for EOF or error. ! -- Macro: void Lstream_ungetc (Lstream *STREAM, int C) ! Push one byte back onto the input queue. This will be the next ! byte read from the stream. Any number of bytes can be pushed back ! and will be read in the reverse order they were pushed back--most ! recent first. (This is necessary for consistency--if there are a ! number of bytes that have been unread and I read and unread a ! byte, it needs to be the first to be read again.) This is a macro ! and so it is very efficient. The C argument is only evaluated ! once but the STREAM argument is evaluated more than once. ! -- Function: int Lstream_fputc (Lstream *STREAM, int C) ! -- Function: int Lstream_fgetc (Lstream *STREAM) ! -- Function: void Lstream_fungetc (Lstream *STREAM, int C) ! Function equivalents of the above macros. ! -- Function: Bytecount Lstream_read (Lstream *STREAM, void *DATA, ! Bytecount SIZE) ! Read SIZE bytes of DATA from the stream. Return the number of ! bytes read. 0 means EOF. -1 means an error occurred and no bytes ! were read. ! -- Function: Bytecount Lstream_write (Lstream *STREAM, void *DATA, ! Bytecount SIZE) ! Write SIZE bytes of DATA to the stream. Return the number of ! bytes written. -1 means an error occurred and no bytes were ! written. ! -- Function: void Lstream_unread (Lstream *STREAM, void *DATA, ! Bytecount SIZE) ! Push back SIZE bytes of DATA onto the input queue. The next call ! to `Lstream_read()' with the same size will read the same bytes ! back. Note that this will be the case even if there is other ! pending unread data. ! -- Function: int Lstream_close (Lstream *STREAM) ! Close the stream. All data will be flushed out. ! -- Function: void Lstream_reopen (Lstream *STREAM) ! Reopen a closed stream. This enables I/O on it again. This is not ! meant to be called except from a wrapper routine that reinitializes ! variables and such--the close routine may well have freed some ! necessary storage structures, for example. ! -- Function: void Lstream_rewind (Lstream *STREAM) ! Rewind the stream to the beginning. !  ! File: internals.info, Node: Lstream Methods, Prev: Lstream Functions, Up: Lstreams ! 35.4 Lstream Methods ! ==================== ! -- Lstream Method: Bytecount reader (Lstream *STREAM, unsigned char ! *DATA, Bytecount SIZE) ! Read some data from the stream's end and store it into DATA, which ! can hold SIZE bytes. Return the number of bytes read. A return ! value of 0 means no bytes can be read at this time. This may be ! because of an EOF, or because there is a granularity greater than ! one byte that the stream imposes on the returned data, and SIZE is ! less than this granularity. (This will happen frequently for ! streams that need to return whole characters, because ! `Lstream_read()' calls the reader function repeatedly until it has ! the number of bytes it wants or until 0 is returned.) The lstream ! functions do not treat a 0 return as EOF or do anything special; ! however, the calling function will interpret any 0 it gets back as ! EOF. This will normally not happen unless the caller calls ! `Lstream_read()' with a very small size. ! This function can be `NULL' if the stream is output-only. ! -- Lstream Method: Bytecount writer (Lstream *STREAM, const unsigned ! char *DATA, Bytecount SIZE) ! Send some data to the stream's end. Data to be sent is in DATA ! and is SIZE bytes. Return the number of bytes sent. This ! function can send and return fewer bytes than is passed in; in that ! case, the function will just be called again until there is no ! data left or 0 is returned. A return value of 0 means that no ! more data can be currently stored, but there is no error; the data ! will be squirreled away until the writer can accept data. (This is ! useful, e.g., if you're dealing with a non-blocking file ! descriptor and are getting `EWOULDBLOCK' errors.) This function ! can be `NULL' if the stream is input-only. ! -- Lstream Method: int rewinder (Lstream *STREAM) ! Rewind the stream. If this is `NULL', the stream is not seekable. ! -- Lstream Method: int seekable_p (Lstream *STREAM) ! Indicate whether this stream is seekable--i.e. it can be rewound. ! This method is ignored if the stream does not have a rewind ! method. If this method is not present, the result is determined ! by whether a rewind method is present. ! -- Lstream Method: int flusher (Lstream *STREAM) ! Perform any additional operations necessary to flush the data in ! this stream. ! -- Lstream Method: int pseudo_closer (Lstream *STREAM) ! -- Lstream Method: int closer (Lstream *STREAM) ! Perform any additional operations necessary to close this stream ! down. May be `NULL'. This function is called when ! `Lstream_close()' is called or when the stream is ! garbage-collected. When this function is called, all pending data ! in the stream will already have been written out. ! -- Lstream Method: Lisp_Object marker (Lisp_Object LSTREAM, void ! (*MARKFUN) (Lisp_Object)) ! Mark this object for garbage collection. Same semantics as a ! standard `Lisp_Object' marker. This function can be `NULL'. !  ! File: internals.info, Node: Subprocesses, Next: Interface to MS Windows, Prev: Lstreams, Up: Top ! 36 Subprocesses ! *************** ! The fields of a process are: ! `name' ! A string, the name of the process. ! `command' ! A list containing the command arguments that were used to start ! this process. ! `filter' ! A function used to accept output from the process instead of a ! buffer, or `nil'. ! `sentinel' ! A function called whenever the process receives a signal, or `nil'. ! `buffer' ! The associated buffer of the process. ! `pid' ! An integer, the Unix process ID. ! `childp' ! A flag, non-`nil' if this is really a child process. It is `nil' ! for a network connection. ! `mark' ! A marker indicating the position of the end of the last output ! from this process inserted into the buffer. This is often but not ! always the end of the buffer. ! `kill_without_query' ! If this is non-`nil', killing XEmacs while this process is still ! running does not ask for confirmation about killing the process. ! `raw_status_low' ! `raw_status_high' ! These two fields record 16 bits each of the process status ! returned by the `wait' system call. ! `status' ! The process status, as `process-status' should return it. ! `tick' ! `update_tick' ! If these two fields are not equal, a change in the status of the ! process needs to be reported, either by running the sentinel or by ! inserting a message in the process buffer. ! `pty_flag' ! Non-`nil' if communication with the subprocess uses a PTY; `nil' ! if it uses a pipe. ! `infd' ! The file descriptor for input from the process. ! `outfd' ! The file descriptor for output to the process. ! `subtty' ! The file descriptor for the terminal that the subprocess is using. ! (On some systems, there is no need to record this, so the value is ! `-1'.) ! `tty_name' ! The name of the terminal that the subprocess is using, or `nil' if ! it is using pipes. !  ! File: internals.info, Node: Interface to MS Windows, Next: Interface to the X Window System, Prev: Subprocesses, Up: Top ! 37 Interface to MS Windows ! ************************** ! * Menu: ! * Different kinds of Windows environments:: ! * Windows Build Flags:: ! * Windows I18N Introduction:: ! * Modules for Interfacing with MS Windows:: !  ! File: internals.info, Node: Different kinds of Windows environments, Next: Windows Build Flags, Prev: Interface to MS Windows, Up: Interface to MS Windows ! 37.1 Different kinds of Windows environments ! ============================================ ! (a) operating system (OS) vs. window system vs. Win32 API vs. C runtime library (CRT) vs. and compiler ! ...................................................................................................... ! There are various Windows operating systems (Windows NT, 2000, XP, 95, ! 98, ME, etc.), which come in two basic classes: Windows NT (NT, 2000, ! XP, and all future versions) and 9x (95, 98, ME). 9x-class operating ! systems are a kind of hodgepodge of a 32-bit upper layer on top of a ! 16-bit MS-DOS-compatible lower layer. NT-class operating systems are ! written from the ground up as 32-bit (there are also 64-bit versions ! available now), and provide many more features and much greater ! stability, since there is full memory protection between all processes ! and the between processes and the system. NT-class operating systems ! also provide emulation for DOS programs inside of a "sandbox" (i.e. a ! walled-off environment in which one DOS program can screw up another ! one, but there is theoretically no way for a DOS program to screw up the ! OS itself). From the perspective of XEmacs, the different between NT ! and 9x is very important in Unicode support (not really provided under ! 9x - see `intl-win32.c') and subprocess creation, among other things. ! The operating system provides the framework for accessing files and ! devices and running programs. From the perspective of a program, the ! operating system provides a set of services. At the lowest level, the ! way to call these services is dependent on the processor the OS is ! running on, but a portable interface is provided to C programs through ! functions called "system calls". Under Windows, this interface is ! called the Win32 API, and includes file-manipulation calls such as ! `CreateFile()' and `ReadFile()', process-creation calls such as ! `CreateProcess()', etc. ! This concept of system calls goes back to Unix, where similar ! services are available but through routines with different, simpler ! names, such as `open()', `read()', `fork()', `execve()', etc. In ! addition, Unix provides a higher layer of routines, called the C ! Runtime Library (CRT), which provide higher-level, more convenient ! versions of the same services (e.g. "stream-oriented" file routines ! such as `fopen()' and `fread()') as well as various other utility ! functions, such as string-manipulation routines (e.g. `strcpy()' and ! `strcmp()'). ! For compatibility, a C Runtime Library (CRT) is also provided under ! Windows, which provides a partial implementation of both the Unix CRT ! and the Unix system-call API, implemented using the Win32 API. The CRT ! sources come with Visual C++ (VC++). For example, under VC++ 6, look in ! the CRT/SRC directory, e.g. for me (ben): /Program Files/Microsoft ! Visual Studio/VC98/CRT/SRC. The CRT is provided using either MSVCRT ! (dynamically linked) or `LIBC.LIB' (statically linked). ! The window system provides the framework for creating overlapped ! windows and unifying signals provided by various devices (input devices ! such as the keyboard and mouse, timers, etc.) into a single event queue ! (or "message queue", under Windows). Like the operating system, the ! window system can be viewed from the perspective of a program as a set ! of services provided by an API of function calls. Under Windows, ! window-system services are also available through the Win32 API, while ! under UNIX the window system is typically a separate component (e.g. the ! X Windowing System, aka X Windows or X11). The term "GUI" ("graphical ! user interface") is often used to refer to the services provided by the ! window system, or to a windowing interface provided by a program. ! The Win32 API is implemented by various dynamic libraries, or DLL's. ! The most important are KERNEL32, USER32, and GDI32. KERNEL32 implements ! the basic file-system and process services. USER32 implements the ! fundamental window-system services such as creating windows and handling ! messages. GDI32 implements higher-level drawing capabilities - fonts, ! colors, lines, etc. ! C programs are compiled into executables using a compiler. Under ! Unix, a compiler usually comes as part of the operating system, but not ! under Windows, where the compiler is a separate product. Even under ! Unix, people often install their own compilers, such as gcc. Under ! Windows, the Microsoft-standard compiler is Visual C++ (VC++). ! It is possible to provide an emulation of any API using any other, as ! long as the underlying API provides the suitable functionality. This is ! what Cygwin (www.cygwin.com) does. It provides a fairly complete POSIX ! emulation layer (POSIX is a government standard for Unix behavior) on ! top of MS Windows - in particular, providing the file-system, process, ! tty, and signal semantics that are part of a modern, standard Unix ! operating system. Cygwin does this using its own DLL, `cygwin1.dll', ! which makes calls to the Win32 API services in `kernel32.dll'. Cygwin ! also provides its own implementation of the C runtime library, called ! `newlib' (`libcygwin.a'; `libc.a' and `libm.a' are symlinked to it), ! which is implemented on top of the Unix system calls provided in ! `cygwin1.dll'. In addition, Cygwin provides static import libraries ! that give you direct access to the Win32 API - XEmacs uses this to ! provide GUI support under Cygwin. Cygwin provides a version of GCC ! (the GNU Project C compiler) that is set up to automatically link with ! the appropriate Cygwin libraries. Cygwin also provides, as optional ! components, pre-compiled binaries for a great number of open-source ! programs compiled under the Cygwin environment. This includes all of ! the standard Unix file-system, text-manipulation, development, ! networking, database, etc. utilities, a version of X Windows that uses ! the Win32 API underlyingly (see below), and compilations of nearly all ! other common open-source packages (Apache, TeX, [X]Emacs, Ghostscript, ! GTK, ImageMagick, etc.). ! Similarly, you can emulate the functionality of X Windows using the ! Win32 component of the Win32 API. Cygwin provides a package to do this, ! from the XFree86 project. Other versions of X under Windows also exist, ! such as the MicroImages MI/X server. Each version potentially can come ! comes with its own header and library files, allowing you to compile ! X-Windows programs. ! All of these different operating system and emulation layers can make ! for a fair amount of confusion, so: ! (b) CRT is not the same as VC++ ! ............................... ! Note that the CRT is *NOT* (completely) part of VC++. True, if you link ! statically, the CRT (in the form of `LIBC.LIB', which comes with VC++) ! will be inserted into the executable (.EXE), but otherwise the CRT will ! be separate. The dynamic version of the CRT is provided by `MSVCRT.DLL' ! (or `MSVCRTD.DLL', for debugging), which comes with Windows. Hence, ! it's possible to use a different compiler and still link with MSVCRT - ! which is exactly what MinGW does. ! (c) CRT is not the same as the Win32 API ! ........................................ ! Note also that the CRT is totally separate from the Win32 API. They ! provide different functions and are implemented in different DLL's. ! They are also different levels - the CRT is implemented on top of ! Win32. Sometimes the CRT and Win32 both have their own versions of ! similar concepts, such as locales. These are typically maintained ! separately, and can get out of sync. Do not assume that changing a ! setting in the CRT will have any effect on Win32 API routines using a ! similar concept unless the CRT docs specifically say so. Do not assume ! that behavior described for CRT functions applies to Win32 API or ! vice-versa. Note also that the CRT knows about and is implemented on ! top of the Win32 API, while the Win32 API knows nothing about the CRT. ! (d) MinGW is not the same as Cygwin ! ................................... ! As described in (b), Microsoft's version of the CRT (`MSVCRT.DLL') is ! provided as part of Windows, separate from VC++, which must be ! purchased. Hence, it is possible to write MSVCRT to provide CRT ! services without using VC++. This is what MinGW (www.mingw.org) does - ! it is a port of GCC that will use MSVCRT. The reason one might want to ! do this is (a) it is free, and (b) it does not require a separately ! installed DLL, as Cygwin does. (#### Maybe MinGW targets CRTDLL, not ! MSVCRT? If so, what is CRTDLL, and how does it differ from MSVCRT and ! `LIBC.LIB'?) Primarily, what MinGW provides is patches to GCC (now ! integrated into the standard distribution) and its own header files and ! import libraries that are compatible with MSVCRT. The best way to think ! of MinGW is as simply another Windows compiler, like how there used to ! be Microsoft and Borland compilers. Because MinGW programs use all the ! same libraries as VC++ programs, and hence the same services are ! available, programs that compile under VC++ should compile under MinGW ! with very little change, whereas programs that compile under Cygwin will ! look quite different. ! The confusion between MinGW and Cygwin is the confusion between the ! environment that a compiler runs under and the target environment of a ! program, i.e. the environment that a program is compiled to run under. ! It's theoretically possible, for example, to compile a program under ! Windows and generate a binary that can only be run under Linux, or ! vice-versa - or, for that matter, to use Windows, running on an Intel ! machine to write and a compile a program that will run on the Mac OS, ! running on a PowerPC machine. This is called cross-compiling, and while ! it may seem rather esoteric, it is quite normal when you want to ! generate a program for a machine that you cannot develop on - for ! example, a program that will run on a Palm Pilot. Originally, this is ! how MinGW worked - you needed to run GCC under a Cygwin environment and ! give it appropriate flags, telling it to use the MinGW headers and ! target `MSVCRT.DLL' rather than `CYGWIN1.DLL'. (In fact, Cygwin ! standardly comes with MinGW's header files.) This was because GCC was ! written with Unix in mind and relied on a large amount of Unix-specific ! functionality. To port GCC to Windows without using a POSIX emulation ! layer would mean a lot of rewriting of GCC. Eventually, however, this ! was done, and it GCC was itself compiled using MinGW. The result is ! that currently you can develop MinGW applications either under Cygwin ! or under native Windows. ! (e) Operating system is not the same as window system ! ..................................................... ! As per the above discussion, we can use either Native Windows (the OS ! part of Win32 provided by `KERNEL32.DLL' and the Windows CRT as ! provided by MSVCRT or CLL) or Cygwin to provide operating-system ! functionality, and we can use either Native Windows (the windowing part ! of Win32 as provided by `USER32.DLL' and `GDI32.DLL') or X11 to provide ! window-system functionality. This gives us four possible build ! environments. It's currently possible to build XEmacs with at least ! three of these combinations - as far as I know native + X11 is no ! longer supported, although it used to be (support used to exist in ! `xemacs.mak' for linking with some X11 libraries available from ! somewhere, but it was bit-rotting and you could always use Cygwin; #### ! what happens if we try to compile with MinGW, native OS + X11?). This ! may still seem confusing, so: ! Native OS + native windowing ! We call `CreateProcess()' to run subprocesses (`process-nt.c'), ! and `CreateWindowEx()' to create a top-level window ! (`frame-msw.c'). We use `nt/xemacs.mak' to compile with VC++, ! linking with the Windows CRT (`MSVCRT.DLL' or `LIBC.LIB') and with ! the various Win32 DLL's (`KERNEL32.DLL', `USER32.DLL', ! `GDI32.DLL'); or we use `src/Makefile[.in.in]' to compile with ! GCC, telling it (e.g. -mno-cygwin, see `s/mingw32.h') to use MinGW ! (which will end up linking with `MSVCRT.DLL'), and linking GCC ! with -lshell32 -lgdi32 -luser32 etc. (see `configure.in'). ! Cygwin + native windowing ! We call `fork()'/`execve()' to run subprocesses ! (`process-unix.c'), and `CreateWindowEx()' to create a top-level ! window (`frame-msw.c'). We use `src/Makefile[in.in]' to compile ! with GCC (it will end up linking with `CYGWIN1.DLL') and link GCC ! with -lshell32 -lgdi32 -luser32 etc. (see `configure.in'). ! Cygwin + X11 ! We call `fork()'/`execve()' to run subprocesses ! (`process-unix.c'), and `XtCreatePopupShell()' to create a ! top-level window (`frame-x.c'). We use `src/Makefile[.in.in]' to ! compile with GCC (it will end up linking with `CYGWIN1.DLL') and ! link GCC with -lXt, -lX11, etc. (see `configure.in'). ! Finally, if native OS + X11 were possible, it might look something ! like ! [Native OS + X11] ! We call `CreateProcess()' to run subprocesses (`process-nt.c'), ! and `XtCreatePopupShell()' to create a top-level window ! (`frame-x.c'). We use `nt/xemacs.mak' to compile with VC++, ! linking with the Windows CRT (`MSVCRT.DLL' or `LIBC.LIB') and with ! the various X11 DLL's (`XT.DLL', `XLIB.DLL', etc.); or we use ! `src/Makefile[.in.in]' to compile with GCC, telling it (e.g. ! -mno-cygwin, see `s/mingw32.h') to use MinGW (which will end up ! linking with `MSVCRT.DLL'), and linking GCC with -lXt, -lX11, etc. ! (see `configure.in'). ! One of the reasons that we maintain the ability to build under Cygwin ! and X11 on Windows, when we have native support, is that it allows ! Windows compilers to test under a Unix-like environment.  ! File: internals.info, Node: Windows Build Flags, Next: Windows I18N Introduction, Prev: Different kinds of Windows environments, Up: Interface to MS Windows ! 37.2 Windows Build Flags ! ======================== ! `CYGWIN' ! for Cygwin-only stuff. ! `WIN32_NATIVE' ! Win32 native OS-level stuff (files, process, etc.). Applies ! whenever linking against the native C libraries - i.e. all ! compilations with VC++ and with MINGW, but never Cygwin. ! `HAVE_X_WINDOWS' ! for X Windows (regardless of whether under MS Win) ! `HAVE_MS_WINDOWS' ! MS Windows native windowing system (anything related to the ! appearance of the graphical screen). May or may not apply to any ! of VC++, MINGW, Cygwin. ! Finally, there's also the MINGW build environment, which uses GCC ! (similar to Cygwin), but native MS Windows libraries rather than a ! POSIX emulation layer (the Cygwin approach). This environment defines ! WIN32_NATIVE, but also defines MINGW, which is used mostly because uses ! its own include files (related to Cygwin), which have a few things ! messed up. ! Formerly, we had a whole host of flags. Here's the conversion, for ! porting code from GNU Emacs and such: ! Old Constant New Constant ! --------------------------------------------------------------- ! `WINDOWSNT' `WIN32_NATIVE' ! `WIN32' `WIN32_NATIVE' ! `_WIN32' `WIN32_NATIVE' ! `HAVE_WIN32' `WIN32_NATIVE' ! `DOS_NT' `WIN32_NATIVE' ! `HAVE_NTGUI' `WIN32_NATIVE', unless it ends up already bracketed ! by this ! `HAVE_FACES' always true ! `MSDOS' determine whether this code is really specific to ! MS-DOS (and not Windows - e.g. DJGPP code); if so, ! delete the code; otherwise, convert to `WIN32_NATIVE' ! (we do not support MS-DOS w/DOS Extender under XEmacs) ! `__CYGWIN__' `CYGWIN' ! `__CYGWIN32__' `CYGWIN' ! `__MINGW32__' `MINGW'  ! File: internals.info, Node: Windows I18N Introduction, Next: Modules for Interfacing with MS Windows, Prev: Windows Build Flags, Up: Interface to MS Windows ! 37.3 Windows I18N Introduction ! ============================== ! *Abstract:* This page provides an overview of the aspects of the Win32 ! internationalization API that are relevant to XEmacs, including the ! basic distinction between multibyte and Unicode encodings. Also ! included are pointers to how XEmacs should make use of this API. ! The Win32 API is quite well-designed in its handling of strings ! encoded for various character sets. The API is geared around the idea ! that two different methods of encoding strings should be supported. ! These methods are called multibyte and Unicode, respectively. The ! multibyte encoding is compatible with ASCII strings and is a more ! efficient representation when dealing with strings containing primarily ! ASCII characters, but it has a great number of serious deficiencies and ! limitations, including that it is very difficult and error-prone to work ! with strings in this encoding, and any particular string in a multibyte ! encoding can only contain characters from a very limited number of ! character sets. The Unicode encoding rectifies all of these ! deficiencies, but it is not compatible with ASCII strings (in other ! words, an existing program will not be able to handle the encoded ! strings unless it is explicitly modified to do so), and it takes up ! twice as much memory space as multibyte encodings when encoding a purely ! ASCII string. ! Multibyte encodings use a variable number of bytes (either one or ! two) to represent characters. ASCII characters are also represented by ! a single byte with its high bit not set, and non-ASCII characters are ! represented by one or two bytes, the first of which always has its high ! bit set. (The second byte, when it exists, may or may not have its high ! bit set.) There is no single multibyte encoding. Instead, there is ! generally one encoding per non-ASCII character set. Such an encoding is ! capable of representing (besides ASCII characters, of course) only ! characters from one (or possibly two) particular character sets. ! Multibyte encoding makes processing of strings very difficult. For ! example, given a pointer to the beginning of a character within a ! string, finding the pointer to the beginning of the previous character ! may require backing up all the way to the beginning of the string, and ! then moving forward. Also, an operation such as separating out the ! components of a path by searching for backslashes will fail if it's ! implemented in the simplest (but not multibyte-aware) fashion, because ! it may find what appears to be a backslash, but which is actually the ! second byte of a two-byte character. Also, the limited number of ! character sets that any particular multibyte encoding can represent ! means that loss of data is likely if a string is converted from the ! XEmacs internal format into a multibyte format. ! For these reasons, the C code in XEmacs should never do any sort of ! work with multibyte encoded strings (or with strings in any external ! encoding for that matter). Strings should always be maintained in the ! internal encoding, which is predictable, and converted to an external ! encoding only at the point where the string moves from the XEmacs C ! code and enters a system library function. Similarly, when a string is ! returned from a system library function, it should be immediately ! converted into the internal coding before any operations are done on it. ! Unicode, unlike multibyte encodings, is a fixed-width encoding where ! every character is represented using 16 bits. It is also capable of ! encoding all the characters from all the character sets in common use in ! the world. The predictability and completeness of the Unicode encoding ! makes it a very good encoding for strings that may contain characters ! from many character sets mixed up with each other. At the same time, of ! course, it is incompatible with routines that expect ASCII characters ! and also incompatible with general string manipulation routines, which ! will encounter a great number of what would appear to be embedded nulls ! in the string. It also takes twice as much room to encode strings ! containing primarily ASCII characters. This is why XEmacs does not use ! Unicode or similar encoding internally for buffers. ! The Win32 API cleverly deals with the issue of 8 bit vs. 16 bit ! characters by declaring a type called `"TCHAR"' which specifies a ! generic character, either 8 bits or 16 bits. Generally `TCHAR' is ! defined to be the same as the simple C type `char', unless the ! preprocessor constant `UNICODE' is defined, in which case `TCHAR' is ! defined to be `WCHAR', which is a 16 bit type. Nearly all functions in ! the Win32 API that take strings are defined to take strings that are ! actually arrays of `TCHAR's. There is a type `LPTSTR' which is defined ! to be a string of `TCHAR's and another type `LPCTSTR' which is a const ! string of `TCHAR's. The theory is that any program that uses `TCHAR's ! exclusively to represent characters and does not make assumptions about ! the size of a `TCHAR' or the way that the characters are encoded should ! work transparently regardless of whether the `UNICODE' preprocessor ! constant is defined, which is to say, regardless of whether 8 bit ! multibyte or 16 bit Unicode characters are being used. The way that ! this is actually implemented is that every Win32 API function that takes ! a string as an argument actually maps to one of two functions which are ! suffixed with an `A' (which stands for ANSI, and means multibyte ! strings) or `W' (which stands for wide, and means Unicode strings). ! The mapping is, of course, controlled by the same `UNICODE' ! preprocessor constant. Generally all structures containing strings in ! them actually map to one of two different kinds of structures, with ! either an `A' or a `W' suffix after the structure name. ! Unfortunately, not all of the implementations of the Win32 API ! implement all of the functionality described above. In particular, ! Windows 95 does not implement very much Unicode functionality. It does ! implement functions to convert multibyte-encoded strings to and from ! Unicode strings, and provides Unicode versions of certain low-level ! functions like `ExtTextOut()'. In fact, all of the rest of the Unicode ! versions of API functions are just stubs that return an error. ! Conversely, all versions of Windows NT completely implement all the ! Unicode functionality, but some versions (especially versions before ! Windows NT 4.0) don't implement much of the multibyte functionality. ! For this reason, as well as for general code cleanliness, XEmacs needs ! to be written in such a way that it works with or without the `UNICODE' ! preprocessor constant being defined. ! Getting XEmacs to run when all strings are Unicode primarily ! involves removing any assumptions made about the size of characters. ! Remember what I said earlier about how the point of conversion between ! internally and externally encoded strings should occur at the point of ! entry or exit into or out of a library function. With this in mind, an ! externally encoded string in XEmacs can be treated simply as an ! arbitrary sequence of bytes of some length which has no particular ! relationship to the length of the string in the internal encoding. ! #### The rest of this is *out-of-date* and needs to be written to ! reference the actual coding systems or aliases that we currently use. ! [[ To facilitate this, the enum `external_data_format', which is ! declared in `lisp.h', is expanded to contain three new formats, which ! are `FORMAT_LOCALE', `FORMAT_UNICODE' and `FORMAT_TSTR'. ! `FORMAT_LOCALE' always causes encoding into a multibyte string ! consistent with the encoding of the current locale. The functions to ! handle locales are different under Unix and Windows and locales are a ! process property under Unix and a thread property under Windows, but ! the concepts are basically the same. `FORMAT_UNICODE' of course causes ! encoding into Unicode and `FORMAT_TSTR' logically maps to either ! `FORMAT_LOCALE' or `FORMAT_UNICODE' depending on the `UNICODE' ! preprocessor constant. ! Under Unix the behavior of `FORMAT_TSTR' is undefined and this ! particular format should not be used. Under Windows however ! `FORMAT_TSTR' should be used for pretty much all of the Win32 API ! calls. The other two formats should only be used in particular APIs ! that specifically call for a multibyte or Unicode encoded string ! regardless of the `UNICODE' preprocessor constant. String constants ! that are to be passed directly to Win32 API functions, such as the ! names of window classes, need to be bracketed in their definition with ! a call to the macro `TEXT'. This awfully named macro, which comes out ! of the Win32 API, appropriately makes a string of either regular or ! wide chars, which is to say this string may be prepended with an `L' ! (causing it to be a wide string) depending on the `UNICODE' ! preprocessor constant. ! By the way, if you're wondering what happened to `FORMAT_OS', I ! think that this format should go away entirely because it is too vague ! and should be replaced by more specific formats as they are defined. ]] ! Use Qnative for Unix conversion, Qmswindows_tstr for Windows ... ! String constants that are to be passed directly to Win32 API ! functions, such as the names of window classes, need to be bracketed in ! their definition with a call to the macro XETEXT. This appropriately ! makes a string of either regular or wide chars, which is to say this ! string may be prepended with an L (causing it to be a wide string) ! depending on XEUNICODE_P.  ! File: internals.info, Node: Modules for Interfacing with MS Windows, Prev: Windows I18N Introduction, Up: Interface to MS Windows ! 37.4 Modules for Interfacing with MS Windows ! ============================================ ! There are two different general Windows-related include files in src. ! Uses are approximately: ! `syswindows.h' ! Wrapper around `', including missing defines as ! necessary. Includes stuff needed on both Cygwin and native ! Windows, regardless of window system chosen. Includes definitions ! needed for Unicode conversion/encapsulation, and other ! Mule-related stuff, plus various other prototypes and ! Windows-specific, but not GUI-specific, stuff. ! `console-msw.h' ! Used on both Cygwin and native Windows, but only when native window ! system (as opposed to X) chosen. Includes `syswindows.h'. ! Summary of files: ! `console-msw.h' ! include file for native windowing (otherwise, `console-x.h', etc.) ! `console-msw.c, frame-msw.c, etc.' ! native windowing, as above ! `process-nt.c' ! subprocess support for native OS (otherwise, `process-unix.c') ! `nt.c' ! support routines used under native OS ! `win32.c' ! support routines used under both OS environments ! `syswindows.h' ! support header for both environments ! `nt/xemacs.mak' ! Makefile for VC++ (otherwise, `src/Makefile.in.in') ! `s/windowsnt.h' ! s header for basic native-OS defines, VC++ compiler ! `s/mingw32.h' ! s header for basic native-OS defines, GCC/MinGW compiler ! `s/cygwin.h' ! s header for basic Cygwin defines ! `s/win32-native.h' ! s header for basic native-OS defines, all compilers ! `s/win32-common.h' ! s header for defines for both OS environments ! `intl-win32.c' ! internationalization functions for both OS environments ! `intl-encap-win32.c' ! Unicode encapsulation functions for both OS environments ! `intl-auto-encap-win32.c' ! Auto-generated Unicode encapsulation functions ! `intl-auto-encap-win32.h' ! Auto-generated Unicode encapsulation headers  ! File: internals.info, Node: Interface to the X Window System, Next: Dumping, Prev: Interface to MS Windows, Up: Top ! 38 Interface to the X Window System ! *********************************** ! Mostly undocumented. ! * Menu: ! * Lucid Widget Library:: An interface to various widget sets. ! * Modules for Interfacing with X Windows:: !  ! File: internals.info, Node: Lucid Widget Library, Next: Modules for Interfacing with X Windows, Prev: Interface to the X Window System, Up: Interface to the X Window System ! 38.1 Lucid Widget Library ! ========================= ! Lwlib is extremely poorly documented and quite hairy. The author(s) ! blame that on X, Xt, and Motif, with some justice, but also sufficient ! hypocrisy to avoid drawing the obvious conclusion about their own work. ! ! The Lucid Widget Library is composed of two more or less independent ! pieces. The first, as the name suggests, is a set of widgets. These ! widgets are intended to resemble and improve on widgets provided in the ! Motif toolkit but not in the Athena widgets, including menubars and ! scrollbars. Recent additions by Andy Piper integrate some "modern" ! widgets by Edward Falk, including checkboxes, radio buttons, progress ! gauges, and index tab controls (aka notebooks). ! ! The second piece of the Lucid widget library is a generic interface ! to several toolkits for X (including Xt, the Athena widget set, and ! Motif, as well as the Lucid widgets themselves) so that core XEmacs ! code need not know which widget set has been used to build the ! graphical user interface. ! * Menu: ! * Generic Widget Interface:: The lwlib generic widget interface. ! * Scrollbars:: ! * Menubars:: ! * Checkboxes and Radio Buttons:: ! * Progress Bars:: ! * Tab Controls::  ! File: internals.info, Node: Generic Widget Interface, Next: Scrollbars, Prev: Lucid Widget Library, Up: Lucid Widget Library ! ! 38.1.1 Generic Widget Interface ! ------------------------------- ! ! In general in any toolkit a widget may be a composite object. In Xt, ! all widgets have an X window that they manage, but typically a complex ! widget will have widget children, each of which manages a subwindow of ! the parent widget's X window. These children may themselves be ! composite widgets. Thus a widget is actually a tree or hierarchy of ! widgets. ! For each toolkit widget, lwlib maintains a tree of `widget_values' ! which mirror the hierarchical state of Xt widgets (including Motif, ! Athena, 3D Athena, and Falk's widget sets). Each `widget_value' has ! `contents' member, which points to the head of a linked list of its ! children. The linked list of siblings is chained through the `next' ! member of `widget_value'. ! +-----------+ ! | composite | ! +-----------+ ! | ! | contents ! V ! +-------+ next +-------+ next +-------+ ! | child |----->| child |----->| child | ! +-------+ +-------+ +-------+ ! | ! | contents ! V ! +-------------+ next +-------------+ ! | grand child |----->| grand child | ! +-------------+ +-------------+ ! The `widget_value' hierarchy of a composite widget with two simple ! children and one composite child. ! The `widget_instance' structure maintains the inverse view of the ! tree. As for the `widget_value', siblings are chained through the ! `next' member. However, rather than naming children, the ! `widget_instance' tree links to parents. ! +-----------+ ! | composite | ! +-----------+ ! A ! | parent ! | ! +-------+ next +-------+ next +-------+ ! | child |----->| child |----->| child | ! +-------+ +-------+ +-------+ ! A ! | parent ! | ! +-------------+ next +-------------+ ! | grand child |----->| grand child | ! +-------------+ +-------------+ ! The `widget_value' hierarchy of a composite widget with two simple ! children and one composite child. ! This permits widgets derived from different toolkits to be updated ! and manipulated generically by the lwlib library. For instance ! `update_one_widget_instance' can cope with multiple types of widget and ! multiple types of toolkit. Each element in the widget hierarchy is ! updated from its corresponding `widget_value' by walking the ! `widget_value' tree. This has desirable properties. For example, ! `lw_modify_all_widgets' is called from `glyphs-x.c' and updates all the ! properties of a widget without having to know what the widget is or ! what toolkit it is from. Unfortunately this also has its hairy ! properties; the lwlib code quite complex. And of course lwlib has to ! know at some level what the widget is and how to set its properties. ! The `widget_instance' structure also contains a pointer to the root ! of its tree. Widget instances are further confi !  ! File: internals.info, Node: Scrollbars, Next: Menubars, Prev: Generic Widget Interface, Up: Lucid Widget Library ! 38.1.2 Scrollbars ! ----------------- !  ! File: internals.info, Node: Menubars, Next: Checkboxes and Radio Buttons, Prev: Scrollbars, Up: Lucid Widget Library ! 38.1.3 Menubars ! --------------- !  ! File: internals.info, Node: Checkboxes and Radio Buttons, Next: Progress Bars, Prev: Menubars, Up: Lucid Widget Library ! 38.1.4 Checkboxes and Radio Buttons ! ----------------------------------- !  ! File: internals.info, Node: Progress Bars, Next: Tab Controls, Prev: Checkboxes and Radio Buttons, Up: Lucid Widget Library ! 38.1.5 Progress Bars ! -------------------- !  ! File: internals.info, Node: Tab Controls, Prev: Progress Bars, Up: Lucid Widget Library ! 38.1.6 Tab Controls ! -------------------  ! File: internals.info, Node: Modules for Interfacing with X Windows, Prev: Lucid Widget Library, Up: Interface to the X Window System ! ! 38.2 Modules for Interfacing with X Windows ! =========================================== ! ! Emacs.ad.h ! ! A file generated from `Emacs.ad', which contains XEmacs-supplied ! fallback resources (so that XEmacs has pretty defaults). ! EmacsFrame.c ! EmacsFrame.h ! EmacsFrameP.h ! These modules implement an Xt widget class that encapsulates a frame. ! This is for ease in integrating with Xt. The EmacsFrame widget covers ! the entire X window except for the menubar; the scrollbars are ! positioned on top of the EmacsFrame widget. ! *Warning:* Abandon hope, all ye who enter here. This code took an ! ungodly amount of time to get right, and is likely to fall apart ! mercilessly at the slightest change. Such is life under Xt. ! EmacsManager.c ! EmacsManager.h ! EmacsManagerP.h ! These modules implement a simple Xt manager (i.e. composite) widget ! class that simply lets its children set whatever geometry they want. ! It's amazing that Xt doesn't provide this standardly, but on second ! thought, it makes sense, considering how amazingly broken Xt is. ! EmacsShell-sub.c ! EmacsShell.c ! EmacsShell.h ! EmacsShellP.h ! These modules implement two Xt widget classes that are subclasses of ! the TopLevelShell and TransientShell classes. This is necessary to deal ! with more brokenness that Xt has sadistically thrust onto the backs of ! developers. ! xgccache.c ! xgccache.h ! These modules provide functions for maintenance and caching of GC's ! (graphics contexts) under the X Window System. This code is junky and ! needs to be rewritten. ! select-msw.c ! select-x.c ! select.c ! select.h ! This module provides an interface to the X Window System's concept of ! "selections", the standard way for X applications to communicate with ! each other. ! xintrinsic.h ! xintrinsicp.h ! xmmanagerp.h ! xmprimitivep.h ! These header files are similar in spirit to the `sys*.h' files and ! buffer against different implementations of Xt and Motif. ! * `xintrinsic.h' should be included in place of `'. ! * `xintrinsicp.h' should be included in place of `'. ! * `xmmanagerp.h' should be included in place of `'. ! * `xmprimitivep.h' should be included in place of `'. ! xmu.c ! xmu.h ! These files provide an emulation of the Xmu library for those systems ! (i.e. HPUX) that don't provide it as a standard part of X. ! ExternalClient-Xlib.c ! ExternalClient.c ! ExternalClient.h ! ExternalClientP.h ! ExternalShell.c ! ExternalShell.h ! ExternalShellP.h ! extw-Xlib.c ! extw-Xlib.h ! extw-Xt.c ! extw-Xt.h ! These files provide the "external widget" interface, which allows an ! XEmacs frame to appear as a widget in another application. To do this, ! you have to configure with `--external-widget'. ! `ExternalShell*' provides the server (XEmacs) side of the connection. ! `ExternalClient*' provides the client (other application) side of ! the connection. These files are not compiled into XEmacs but are ! compiled into libraries that are then linked into your application. ! `extw-*' is common code that is used for both the client and server. ! Don't touch this code; something is liable to break if you do.  ! File: internals.info, Node: Dumping, Next: Future Work, Prev: Interface to the X Window System, Up: Top ! ! 39 Dumping ! ********** ! * Menu: ! * Dumping Justification:: ! * Overview:: ! * Data descriptions:: ! * Dumping phase:: ! * Reloading phase:: ! * Remaining issues:: !  ! File: internals.info, Node: Dumping Justification, Next: Overview, Prev: Dumping, Up: Dumping ! 39.1 Dumping Justification ! ========================== ! The C code of XEmacs is just a Lisp engine with a lot of built-in ! primitives useful for writing an editor. The editor itself is written ! mostly in Lisp, and represents around 100K lines of code. Loading and ! executing the initialization of all this code takes a bit a time (five ! to ten times the usual startup time of current xemacs) and requires ! having all the lisp source files around. Having to reload them each ! time the editor is started would not be acceptable. ! ! The traditional solution to this problem is called dumping: the build ! process first creates the lisp engine under the name `temacs', then ! runs it until it has finished loading and initializing all the lisp ! code, and eventually creates a new executable called `xemacs' including ! both the object code in `temacs' and all the contents of the memory ! after the initialization. ! ! This solution, while working, has a huge problem: the creation of the ! new executable from the actual contents of memory is an extremely ! system-specific process, quite error-prone, and which interferes with a ! lot of system libraries (like malloc). It is even getting worse ! nowadays with libraries using constructors which are automatically ! called when the program is started (even before `main()') which tend to ! crash when they are called multiple times, once before dumping and once ! after (IRIX 6.x `libz.so' pulls in some C++ image libraries thru ! dependencies which have this problem). Writing the dumper is also one ! of the most difficult parts of porting XEmacs to a new operating system. ! Basically, `dumping' is an operation that is just not officially ! supported on many operating systems. ! ! The aim of the portable dumper is to solve the same problem as the ! system-specific dumper, that is to be able to reload quickly, using only ! a small number of files, the fully initialized lisp part of the editor, ! without any system-specific hacks. !  ! File: internals.info, Node: Overview, Next: Data descriptions, Prev: Dumping Justification, Up: Dumping ! 39.2 Overview ! ============= ! The portable dumping system has to: ! 1. At dump time, write all initialized, non-quickly-rebuildable data ! to a file [Note: currently named `xemacs.dmp', but the name will ! change], along with all information needed for the reloading. ! 2. When starting xemacs, reload the dump file, relocate it to its new ! starting address if needed, and reinitialize all pointers to this ! data. Also, rebuild all the quickly rebuildable data. ! Note: As of 21.5.18, the dump file has been moved inside of the ! executable, although there are still problems with this on some systems. !  ! File: internals.info, Node: Data descriptions, Next: Dumping phase, Prev: Overview, Up: Dumping ! 39.3 Data descriptions ! ====================== ! The more complex task of the dumper is to be able to write memory blocks ! on the heap (lisp objects, i.e. lrecords, and C-allocated memory, such ! as structs and arrays) to disk and reload them at a different address, ! updating all the pointers they include in the process. This is done by ! using external data descriptions that give information about the layout ! of the blocks in memory. ! ! The specification of these descriptions is in lrecord.h. A ! description of an lrecord is an array of struct memory_description. ! Each of these structs include a type, an offset in the block and some ! optional parameters depending on the type. For instance, here is the ! string description: ! ! static const struct memory_description string_description[] = { ! { XD_BYTECOUNT, offsetof (Lisp_String, size) }, ! { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT(0, 1) }, ! { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, ! { XD_END } ! }; ! ! The first line indicates a member of type Bytecount, which is used by ! the next, indirect directive. The second means "there is a pointer to ! some opaque data in the field `data'". The length of said data is ! given by the expression `XD_INDIRECT(0, 1)', which means "the value in ! the 0th line of the description (welcome to C) plus one". The third ! line means "there is a Lisp_Object member `plist' in the Lisp_String ! structure". `XD_END' then ends the description. ! ! This gives us all the information we need to move around what is ! pointed to by a memory block (C or lrecord) and, by transitivity, ! everything that it points to. The only missing information for dumping ! is the size of the block. For lrecords, this is part of the ! lrecord_implementation, so we don't need to duplicate it. For C blocks ! we use a struct sized_memory_description, which includes a size field ! and a pointer to an associated array of memory_description.  ! File: internals.info, Node: Dumping phase, Next: Reloading phase, Prev: Data descriptions, Up: Dumping ! ! 39.4 Dumping phase ! ================== ! ! Dumping is done by calling the function `pdump()' (in `dumper.c') which ! is invoked from Fdump_emacs (in `emacs.c'). This function performs a ! number of tasks. ! ! * Menu: ! ! * Object inventory:: ! * Address allocation:: ! * The header:: ! * Data dumping:: ! * Pointers dumping:: !  ! File: internals.info, Node: Object inventory, Next: Address allocation, Prev: Dumping phase, Up: Dumping phase ! 39.4.1 Object inventory ! ----------------------- ! The first task is to build the list of the objects to dump. This ! includes: ! * lisp objects ! * other memory blocks (C structures, arrays. etc) ! We end up with one `pdump_block_list_elt' per object group (arrays ! of C structs are kept together) which includes a pointer to the first ! object of the group, the per-object size and the count of objects in the ! group, along with some other information which is initialized later. ! These entries are linked together in `pdump_block_list' structures ! and can be enumerated thru either: ! 1. the `pdump_object_table', an array of `pdump_block_list', one per ! lrecord type, indexed by type number. ! 2. the `pdump_opaque_data_list', used for the opaque data which does ! not include pointers, and hence does not need descriptions. ! 3. the `pdump_desc_table', which is a vector of ! `memory_description'/`pdump_block_list' pairs, used for non-opaque ! C memory blocks. ! This uses a marking strategy similar to the garbage collector. Some ! differences though: ! 1. We do not use the mark bit (which does not exist for generic ! memory blocks anyway); we use a big hash table instead. ! 2. We do not use the mark function of lrecords but instead rely on the ! external descriptions. This happens essentially because we need to ! follow pointers to generic memory blocks and opaque data in ! addition to Lisp_Object members. ! This is done by `pdump_register_object()', which handles Lisp_Object ! variables, and `pdump_register_block()' which handles generic memory ! blocks (C structures, arrays, etc.), which both delegate the ! description management to `pdump_register_sub()'. ! The hash table doubles as a map object to pdump_block_list_elmt (i.e. ! allows us to look up a pdump_block_list_elmt with the object it points ! to). Entries are added with `pdump_add_block()' and looked up with ! `pdump_get_block()'. There is no need for entry removal. The hash ! value is computed quite simply from the object pointer by ! `pdump_make_hash()'. ! The roots for the marking are: ! 1. the `staticpro''ed variables (there is a special ! `staticpro_nodump()' call for protected variables we do not want to ! dump). ! 2. the Lisp_Object variables registered via ! `dump_add_root_lisp_object' (`staticpro()' is equivalent to ! `staticpro_nodump()' + `dump_add_root_lisp_object()'). ! 3. the data-segment memory blocks registered via `dump_add_root_block' ! (for blocks with relocatable pointers), or `dump_add_opaque' (for ! "opaque" blocks with no relocatable pointers; this is just a ! shortcut for calling `dump_add_root_block' with a NULL ! description). ! 4. the pointer variables registered via `dump_add_root_block_ptr', ! each of which points to a block of heap memory (generally a C ! structure or array). Note that `dump_add_root_block_ptr' is not ! technically necessary, as a pointer variable can be seen as a ! special case of a data-segment memory block and registered using ! `dump_add_root_block'. Doing it this way, however, would require ! another level of static structures declared. Since pointer ! variables are quite common, `dump_add_root_block_ptr' is provided ! for convenience. Note also that internally we have to treat it ! separately from `dump_add_root_block' rather than writing the ! former as a call to the latter, since we don't have support for ! creating and using memory descriptions on the fly - they must all ! be statically declared in the data-segment. ! This does not include the GCPRO'ed variables, the specbinds, the ! catchtags, the backlist, the redisplay or the profiling info, since we ! do not want to rebuild the actual chain of lisp calls which end up to ! the dump-emacs call, only the global variables. ! Weak lists and weak hash tables are dumped as if they were their ! non-weak equivalent (without changing their type, of course). This has ! not yet been a problem. !  ! File: internals.info, Node: Address allocation, Next: The header, Prev: Object inventory, Up: Dumping phase ! 39.4.2 Address allocation ! ------------------------- ! The next step is to allocate the offsets of each of the objects in the ! final dump file. This is done by `pdump_allocate_offset()' which is ! called indirectly by `pdump_scan_by_alignment()'. ! The strategy to deal with alignment problems uses these facts: ! 1. real world alignment requirements are powers of two. ! 2. the C compiler is required to adjust the size of a struct so that ! you can have an array of them next to each other. This means you ! can have an upper bound of the alignment requirements of a given ! structure by looking at which power of two its size is a multiple. ! 3. the non-variant part of variable size lrecords has an alignment ! requirement of 4. ! Hence, for each lrecord type, C struct type or opaque data block the ! alignment requirement is computed as a power of two, with a minimum of ! 2^2 for lrecords. `pdump_scan_by_alignment()' then scans all the ! `pdump_block_list_elmt''s, the ones with the highest requirements ! first. This ensures the best packing. ! The maximum alignment requirement we take into account is 2^8. ! `pdump_allocate_offset()' only has to do a linear allocation, ! starting at offset 256 (this leaves room for the header and keeps the ! alignments happy).  ! File: internals.info, Node: The header, Next: Data dumping, Prev: Address allocation, Up: Dumping phase ! 39.4.3 The header ! ----------------- ! The next step creates the file and writes a header with a signature and ! some random information in it. The `reloc_address' field, which ! indicates at which address the file should be loaded if we want to avoid ! post-reload relocation, is set to 0. It then seeks to offset 256 (base ! offset for the objects). !  ! File: internals.info, Node: Data dumping, Next: Pointers dumping, Prev: The header, Up: Dumping phase ! 39.4.4 Data dumping ! ------------------- ! The data is dumped in the same order as the addresses were allocated by ! `pdump_dump_data()', called from `pdump_scan_by_alignment()'. This ! function copies the data to a temporary buffer, relocates all pointers ! in the object to the addresses allocated in step Address Allocation, ! and writes it to the file. Using the same order means that, if we are ! careful with lrecords whose size is not a multiple of 4, we are ensured ! that the object is always written at the offset in the file allocated ! in step Address Allocation. !  ! File: internals.info, Node: Pointers dumping, Prev: Data dumping, Up: Dumping phase ! 39.4.5 Pointers dumping ! ----------------------- ! A bunch of tables needed to reassign properly the global pointers are ! then written. They are: ! 1. the pdump_root_block_ptrs dynarr ! 2. the pdump_opaques dynarr ! 3. a vector of all the offsets to the objects in the file that ! include a description (for faster relocation at reload time) ! 4. the pdump_root_objects and pdump_weak_object_chains dynarrs. ! For each of the dynarrs we write both the pointer to the variables ! and the relocated offset of the object they point to. Since these ! variables are global, the pointers are still valid when restarting the ! program and are used to regenerate the global pointers. ! The `pdump_weak_object_chains' dynarr is a special case. The ! variables it points to are the head of weak linked lists of lisp objects ! of the same type. Not all objects of this list are dumped so the ! relocated pointer we associate with them points to the first dumped ! object of the list, or Qnil if none is available. This is also the ! reason why they are not used as roots for the purpose of object ! enumeration. ! Some very important information like the `staticpros' and ! `lrecord_implementations_table' are handled indirectly using ! `dump_add_opaque' or `dump_add_root_block_ptr'. ! This is the end of the dumping part. !  ! File: internals.info, Node: Reloading phase, Next: Remaining issues, Prev: Dumping phase, Up: Dumping ! 39.5 Reloading phase ! ==================== ! 39.5.1 File loading ! ------------------- ! The file is mmap'ed in memory (which ensures a PAGESIZE alignment, at ! least 4096), or if mmap is unavailable or fails, a 256-bytes aligned ! malloc is done and the file is loaded. ! Some variables are reinitialized from the values found in the header. ! The difference between the actual loading address and the ! reloc_address is computed and will be used for all the relocations. ! 39.5.2 Putting back the pdump_opaques ! ------------------------------------- ! The memory contents are restored in the obvious and trivial way. ! 39.5.3 Putting back the pdump_root_block_ptrs ! --------------------------------------------- ! The variables pointed to by pdump_root_block_ptrs in the dump phase are ! reset to the right relocated object addresses. ! 39.5.4 Object relocation ! ------------------------ ! All the objects are relocated using their description and their offset ! by `pdump_reloc_one'. This step is unnecessary if the reloc_address is ! equal to the file loading address. ! 39.5.5 Putting back the pdump_root_objects and pdump_weak_object_chains ! ----------------------------------------------------------------------- ! Same as Putting back the pdump_root_block_ptrs. ! 39.5.6 Reorganize the hash tables ! --------------------------------- ! Since some of the hash values in the lisp hash tables are ! address-dependent, their layout is now wrong. So we go through each of ! them and have them resorted by calling `pdump_reorganize_hash_table'. !  ! File: internals.info, Node: Remaining issues, Prev: Reloading phase, Up: Dumping ! 39.6 Remaining issues ! ===================== ! The build process will have to start a post-dump xemacs, ask it the ! loading address (which will, hopefully, be always the same between ! different xemacs invocations) [[unfortunately, not true on Linux with ! the ExecShield feature]] and relocate the file to the new address. ! This way the object relocation phase will not have to be done, which ! means no writes in the objects and that, because of the use of mmap, the ! dumped data will be shared between all the xemacs running on the ! computer. ! ! Some executable signature will be necessary to ensure that a given ! dump file is really associated with a given executable, or random ! crashes will occur. Maybe a random number set at compile or configure ! time thru a define. This will also allow for having ! differently-compiled xemacsen on the same system (mule and no-mule ! comes to mind). ! The DOC file contents should probably end up in the dump file. !  ! File: internals.info, Node: Future Work, Next: Future Work Discussion, Prev: Dumping, Up: Top ! 40 Future Work ! ************** ! * Menu: ! * Future Work -- General Suggestions:: ! * Future Work -- Elisp Compatibility Package:: ! * Future Work -- Drag-n-Drop:: ! * Future Work -- Standard Interface for Enabling Extensions:: ! * Future Work -- Better Initialization File Scheme:: ! * Future Work -- Keyword Parameters:: ! * Future Work -- Property Interface Changes:: ! * Future Work -- Toolbars:: ! * Future Work -- Menu API Changes:: ! * Future Work -- Removal of Misc-User Event Type:: ! * Future Work -- Mouse Pointer:: ! * Future Work -- Extents:: ! * Future Work -- Version Number and Development Tree Organization:: ! * Future Work -- Improvements to the `xemacs.org' Website:: ! * Future Work -- Keybindings:: ! * Future Work -- Byte Code Snippets:: ! * Future Work -- Lisp Stream API:: ! * Future Work -- Multiple Values:: ! * Future Work -- Macros:: ! * Future Work -- Specifiers:: ! * Future Work -- Display Tables:: ! * Future Work -- Making Elisp Function Calls Faster:: ! * Future Work -- Lisp Engine Replacement:: ! * Future Work -- Better Rendering Support::  ! File: internals.info, Node: Future Work -- General Suggestions, Next: Future Work -- Elisp Compatibility Package, Prev: Future Work, Up: Future Work ! 40.1 Future Work - General Suggestions ! ====================================== ! Jamie Zawinski's XEmacs Wishlist ! -------------------------------- ! This document is based on Jamie Zawinski's xemacs wishlist ! (http://www.jwz.org/doc/xemacs-wishlist.html). Throughout this ! page, "I" refers to Jamie. ! ! The list has been substantially reformatted and edited to fit the ! needs of this site. If you have any soul at all, you'll go check ! out the original. OK? You should also check out some other ! wishlists ! (http://www.xemacs.org/Releases/Public-21.2/execution.html#wishlists). ! ! About the List ! .............. ! ! I've ranked these (roughly) from easiest to hardest; though of all of ! them, I think the debugger improvements would be the most useful. I ! think the combination of emacs+gdb is the best Unix development ! environment currently available, but it's still lamentably primitive ! and extremely frustrating (much like Unix itself), especially if you ! know what kinds of features more modern integrated debuggers have. ! ! XEmacs Wishlist ! ............... ! ! *Improve the keyboard macro system.* ! Keyboard macros are one of the most useful concepts that emacs has ! to offer, but there's room for improvement. ! ! *Make it possible to embed one macro inside of another.* ! Often, I'll define a keyboard macro, and then realize that ! I've left something out, or that there's more that I need to ! do; for example, I may define a macro that does something to ! the current line, and then realize that I want to apply it to ! a lot of lines. So, I'd like this to work: ! ! C-x ( ! ; start macro #1 ! ... ! ; (do stuff) ! C-x ) ! ; done with macro #1 ! ... ! ; (do stuff) ! C-x ( ! ; start macro #2 ! C-x e ! ; execute macro #1 (splice it into macro #2) ! C-s foo ! ; move forward to the next spot ! C-x ) ! ; done with macro #2 ! C-u 1000 C-x e ! ; apply the new macro ! ! That is, simply, one should be able to wrap new text around an ! existing macro. I can't tell you how many times I've defined ! a complex macro but left out the "`C-n C-a'" at the end... ! ! Yes, you can accomplish this with M-x name-last-kbd-macro, but ! that's a pain. And it's also more permanent than I'd often ! like. ! ! *Make it possible to correct errors when defining a macro.* ! Right now, the act of defining a macro stops if you get an ! error while defining it, and all of the characters you've ! already typed into the macro are gone. It needn't be that ! way. I think that, when that first error occurs, the user ! should be given the option of taking the last command off of ! the macro and trying again. ! ! The macro-reader knows where the bounds of multi-character ! command sequences are, and it could even keep track of the ! corresponding undo records; rubbing out the previous entry on ! the macro could also undo any changes that command had made. ! (This should also work if the macro spans multiple buffers, ! and should restore window configurations as well.) ! ! You'd want multi-level undo for this as well, so maybe the ! way to go would be to add some new key sequence which was ! used only as the back-up-inside-a-keyboard-macro-definition ! command. ! ! I'm not totally sure that this would end up being very usable; ! maybe it would be too hard to deal with. Which brings us to: ! ! *Make it possible to edit a keyboard macro after it has been defined.* ! I only just discovered `edit-kbd-macro' (`C-x C-k'). It is ! very, very cool. ! ! The trick it does of showing the command which will be ! executed is somewhat error-prone, as it can only look up ! things in the current map or the global map; if the macro ! changed buffers, it wouldn't be displaying the right ! commands. (One of the things I often use macros for is ! operating on many files at once, by bringing up a dired buffer ! of those files, editing them, and then moving on to the next.) ! ! However, if the act of recording a macro also kept track of ! the actual commands that had gotten executed, it could make ! use of that info as well. ! ! Another way of editing a macro, other than as text in a ! buffer, would be to have a command which single-steps a ! macro: you would lean on the space bar to watch the macro ! execute one character (command?) at a time, and then when ! you reached the point you wanted to change, you could do some ! gesture to either: insert some keystrokes into the middle of ! the macro and then continue; or to replace the rest of the ! macro from here to the end; or something. ! ! Another similar hack might be to convert a macro to the ! equivalent lisp code, so that one could tweak it later in ! ways that would be too hard to do from the keyboard (wrapping ! parts of it in `while' loops or something.) (`M-x ! insert-kbd-macro' isn't really what I'm talking about here: I ! mean insert the list of commands, not the list of keystrokes.) ! ! *Save my wrists!* ! In the spirit of the ``teach-extended-commands-p'' variable, it ! would be interesting if emacs would keep track of what are the ! commands I use most often, perhaps grouped by proximity or mode - ! it would then be more obvious which commands were most likely ! candidates for placement on a toolbar, or popup menu, or just a ! more convenient key binding. ! ! Bonus points if it figures out that I type "`bt\n'" and ! "`ret\ny\n'" into my `*gdb*' buffer about a hundred thousand times ! a day. ! ! *XmCreateFileSelectionBox* ! The thing that "File/Open..." pops up has excellent _hack_ value, ! but as a user interface, it's an abomination. Isn't it time ! someone added a real file selection dialog already? (For the ! Motifly-challenged, the Athena-based file selector that GhostView ! uses seems adequate.) ! ! *Improve the toolbar system.* ! It's great that XEmacs has a toolbar, but it's damn near impossible ! to customize it. ! ! *Make it easy to define new toolbar buttons.* ! Currently, to define a toolbar button that has a text ! equivalent, one must edit a pixmap, and put the text there! ! That's prohibitive. One should be able to add some kind of ! generic toolbar button, with a plain icon or none at all, but ! which has a text label, without having to use a paint program. ! ! *Make it easy to have customized, mode-local toolbars.* ! In my `c-mode-hook', for example, I can add a couple of new ! keybindings, and delete a few others, and to do that, I don't ! have to duplicate the entire definition of the `c-mode-map'. ! Making mode-local additions and subtractions to the toolbars ! should be as easy. ! ! *Make it easy to have customized, mode-local popup menus.* ! The same situation holds for the right-mouse-button popup ! menu; one should be able to add new commands to those menus ! without difficulty. One problem is that each mode which does ! have a popup menu implements it in a different way... ! ! *Make the External Widget work.* ! About half of the work is done to make a replacement for the ! `XmText' widget which offloads editing responsibility to an ! external Emacs process. Someone should finish that. The benefit ! here would be that then, any Motif program could be linked such ! that all editing happened with a real Emacs behind it. (If you're ! Athena-minded, flavor with `Text' instead of `XmText' - it's ! probably easy to make it work with both.) ! ! The part of this that is done already is the ability to run an ! Emacs screen on a Window object that has been created by another ! process (this is what the `ExternalClient.c' and `ExternalShell.c' ! stuff is.) What is left to be done is, adding the ! text-widget-editor aspects of this. ! ! First, the emacs screen being displayed on that window would have ! to be one without a modeline, and one which behaved sensibly in ! the context of "I am a small multi-line text area embedded in a ! dialog box" as opposed to "I am a full-on text editor and lord of ! all that I survey." ! ! Second, the API that the (non-emacs-aware) user of the `XmText' ! widget expects would need to be implemented: give the caller the ! ability to pull the edited text string back out, and so on. The ! idea here being, hooking up emacs as the widget editor should be as ! transparent as possible. ! ! *Bring the debugger interface into the eighties.* ! Some of you may have seen my `gdb-highlight.el' package, that I ! posted to gnu.emacs.sources last month. I think it's really cool, ! but there should be a lot more work in that direction. For those ! of you who haven't seen it, what it does is watch text that gets ! inserted into the `*gdb*' buffer and make very nearly everything ! be clickable and have a context-sensitive menu. Generally, the ! types that are noticed are: ! ! * function names; ! ! * variable and parameter names; ! ! * structure slots; ! ! * source file names; ! ! * type names; ! ! * breakpoint numbers; ! ! * stack frame numbers. ! ! Any time one of those objects is presented in the `*gdb*' buffer, ! it is mousable. Clicking middle button on it takes some default ! action (edits the function, selects the stack frame, disables the ! breakpoint, ...) Clicking the right button pops up a menu of ! commands, including commands specific to the object under the ! mouse, and/or other objects on the same line. ! ! So that's all well and good, and I get far more joy out of what ! this code does for me than I expected, but there are still a bunch ! of limitations. The debugger interface needs to do much, much more. ! ! *Make gdbsrc-mode not suck.* ! The idea behind `gdbsrc-mode' is on the side of the angels: ! one should be able to focus on the source code and not on the ! debugger buffer, absolutely. But the implementation is just ! awful. ! ! First and foremost, it should not change "modes" (in the more ! general sense). Any commands that it defines should be on ! keys which are exclusively used for that purpose, not keys ! which are normally self-inserting. I can't be the only person ! who usually has occasion to actually _edit_ the sources which ! the debugger has chosen to display! Switching into and out of ! `gdbsrc-mode' is prohibitive. ! ! I want to be looking at my sources at all times, yet I don't ! want to have to give up my source-editing gestures. I think ! the right way to accomplish this is to put the gdbsrc ! commands on the toolbar and on popup menus; or to let the ! user define their own keys (I could see devoting my ! key to "step", or something common like that.) ! ! Also it's extremely frustrating that one can't turn off ! gdbsrc mode once it has been loaded, without exiting and ! restarting emacs; that alone means that I'd probably never ! take the time to learn how to use it, without first having ! taken the time to repair it... ! ! *Make it easier access to variable values.* ! I want to be able to double-click on a variable name to ! highlight it, and then drag it to the debugger window to have ! its value printed. ! ! I want gestures that let me write as well as read: for ! example, to store value A into slot B. ! ! *Make all breakpoints visible.* ! Any time there is a running gdb which has breakpoints, the ! buffers holding the lines on which those breakpoints are set ! should have icons in them. These icons should be ! context-sensitive: I should be able to pop up a menu to ! enable or disable them, to delete them, to change their ! commands or conditions. ! ! I should also be able to _move_ them. It's annoying when you ! have a breakpoint with a complex condition or command on it, ! and then you realize that you really want it to be at a ! different location. I want to be able to drag-and-drop the ! icon to its new home. ! ! *Make a debugger status display window.* ! * I want a window off to the side that shows persistent ! information - it should have a pane which is a ! drag-editable, drag-reorderable representation of the ! elements on gdb's "display" list; they should be ! displayed here instead of being just dumped in with the ! rest of the output in the `*gdb*' buffer. ! ! * I want a pane that displays the current call-stack and ! nothing else. I want a pane that displays the arguments ! and locals of the currently-selected frame and nothing ! else. I want these both to update as I move around on ! the stack. ! ! * Since the unfortunate reality is that excavating this ! information from gdb can be slow, it would be a good ! idea for these panes to have a toggle button on them ! which meant "stop updating", so that when I want to move ! fast, I can, but I can easily get the display back when ! I need it again. ! ! The reason for all of this is that I spend entirely too much ! time scrolling around in the `*gdb*' buffer; with ! gdb-highlight, I can just click on a line in the backtrace ! output to go to that frame, but I find that I spend a lot of ! time _looking_ for that backtrace: since it's mixed in with ! all the other random output, I waste time looking around for ! things (and usually just give up and type "`bt'" again, then ! thrash around as the buffer scrolls, and I try to find the ! lower frames that I'm interested in, as they have invariably ! scrolled off the window already... ! ! *Save and restore breakpoints across emacs/debugger sessions.* ! This would be especially handy given that gdb leaks like a ! sieve, and with a big program, I only get a few dozen ! relink-and-rerun attempts before gdb has blown my swap space. ! ! *Keep breakpoints in sync with source lines.* ! When a program is recompiled and then reloaded into gdb, the ! breakpoints often end up in less-than-useful places. For ! example, when I edit text which occurs in a file anywhere ! before a breakpoint, emacs is aware that the line of the bp ! hasn't changed, but just that it is in a different place ! relative to the top of the file. Gdb doesn't know this, so ! your breakpoints end up getting set in the wrong places ! (usually the maximally inconvenient places, like _after_ a ! loop instead of _inside_ it). But emacs knows, so emacs should ! inform the debugger, and move the breakpoints back to the ! places they were intended to be. ! ! (Possibly the OOBR stuff does some of this, but can't tell, because ! I've never been able to get it to do anything but beep at me and ! mumble about environments. I find it pretty funny that the manual ! keeps explaining to me how intuitive it is, without actually ! giving me a clue how to launch it...) ! ! *Add better dialog box features.* ! It'd be nice to be able to create more complex dialog boxes from ! emacs-lisp: ones with checkboxes, radio button groups, text ! fields, and popup menus. ! ! *Add embeddable dialog boxes.* ! One of the things that the now-defunct Energize code (the C side of ! it, that is) could do was embed a dialog box between the toolbar ! and the main text area - buffers could have control panels ! associated with them, that had all kinds of complex behavior. ! ! *Make the mark-stack be visible.* ! You know, I've encountered people who have been using emacs for ! years, and never use the mark stack for navigation. I can't live ! without it; "`C-u C-SPC'" is among my most common gestures. ! ! 1. It would be a lot easier to realize what's going to happen ! if the marks on the mark stack were visible. They could be ! displayed as small "caret" glyphs, for example; something ! large enough to be visible, but not easily mistaken for a ! character or for the cursor. ! ! 2. The marks and the selected region should be visible in the ! scrollbar as well - I don't remember where I first saw this ! idea, but it's very cool: there's a second, ! less-strongly-rendered "thumb" in the scrollbar which ! indicates the position and size of the selection; and there ! are tiny tick-marks which indicate the positions of the saved ! points. ! ! 3. Markers which are in registers (`point-to-register', `C-x ! /') should be displayed differently (more prominent.) ! ! 4. It'd be cool if you could pick up markers and move them ! around, to adjust the points you'll be coming back to later. ! ! *Write a new garbage collector.* ! The emacs GC is very primitive; it is also, fortunately, a rather ! well isolated module, and it would not be a very big task to swap ! it with a new one (once that new one was written, that is.) Someone ! should go bone up on modern GC techniques, and then just dive right ! in... ! ! *Add support for lexical scope to the emacs-lisp runtime.* ! Yadda yadda, this list goes to eleven. ! ! Subject: *Re: XEmacs wishlist* Date: Wed, 14 May 1997 16:18:23 -0700 ! From: Jamie Zawinski Newsgroups: comp.emacs.xemacs, ! comp.emacs ! ! Andreas Schwab wrote: ! ! _Use `C-u C-x (': _ ! ! _start-kbd-macro: ! Non-nil arg (prefix arg) means append to last macro defined; This ! begins by re-executing that macro as if you typed it again. _ ! ! Cool, I didn't know it did that... ! ! But it only lets you append. I often want to prepend, or embed the ! macro multiple times (motion 1, C-x e, motion 2, C-x e, motion 3.) ! ! 21.2 Showstoppers ! ----------------- ! ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! DISTRIBUTION ISSUES ! ! A. Unified Source Tarball. ! ! Packages go under root/lib/xemacs/xemacs-packages and no one ever has ! to mess with -package-path and the result can be moved from one ! directory to another pre- or post-install. ! ! Unified Binary Tarballs with Packages. ! ! Same principles as above. ! ! If people complain, we can also provide split binary tarballs ! (architecture dependent and independent) and place these files in a ! subdirectory so as not to confuse the majority just looking for one ! tarball. ! ! Under Windows, we need to provide a WISE-style GUI setup program. ! It's already there but needs some work so you can select "all" packages ! easily (should be the default). ! ! Parallel Root and Package Trees. ! ! If the user downloads separately, the main source and the packages, ! he will naturally untar them into the same directory. This results in ! the parallel root and package structure. We should support this as a ! "last resort," i.e., if we find no packages anywhere and are about to ! resign ourselves to not having packages, then look for a parallel ! package tree. The user who sets things up like this should be able to ! either run in place or "make install" and get a proper installed ! XEmacs. Never should the user have to touch -package-path. ! ! II. WINDOWS PRINTING ! ! Looks like the internals are done but not the GUI. This must be ! working in 21.2. ! ! III. WINDOWS MULE ! ! Basic support should be there. There's already a patch to get things ! started and I'll be doing more work to make this real. ! ! IV. GUTTER ETC. ! ! This stuff needs to be "stable" and generally free from bugs. Any ! APIs we create need to be well-reviewed or marked clearly as ! experimental. ! ! V. PORTABLE DUMPER ! ! Last bits need to be cleaned up. This should be made the "default" ! for a while to flush-out problems. Under Microsoft Windows, Portable ! Dumper must be the default in 21.2 because of the problems with the ! existing dump process. ! ! COMMENT: I'd like to feature freeze this pretty soon and create a ! 21.3 tree where all of my major overhauls of Mule-related stuff will go ! in. At the same time or around, we need to do the move-around in the ! repository (or create a new one) and "upgrade" to the latest CVS server. !  ! File: internals.info, Node: Future Work -- Elisp Compatibility Package, Next: Future Work -- Drag-n-Drop, Prev: Future Work -- General Suggestions, Up: Future Work ! 40.2 Future Work - Elisp Compatibility Package ! ============================================== ! Author: Ben Wing (mailto:ben@xemacs.org) ! A while ago I created a package called Sysdep, which aimed to be a ! forward compatibility package for Elisp. The idea was that instead of ! having to write your package using the oldest version of Emacs that you ! wanted to support, you could use the newest XEmacs API, and then simply ! load the Sysdep package, which would automatically define the new API in ! terms of older APIs as necessary. The idea of this package was good, ! but its design wasn't perfect, and it wasn't widely adopted. I propose ! a new package called Compat that corrects the design flaws in Sysdep, ! and hopefully will be adopted by most of the major packages. ! ! In addition, this package will provide macros that can be used to ! bracket code as necessary to disable byte compiler warnings generated as ! a result of supporting the APIs of different versions of Emacs; or ! rather the Compat package strives to provide useful constructs to make ! doing this support easier, and these constructs have the side effect of ! not causing spurious byte compiler warnings. The idea here is that it ! should be possible to create well-written, clean, and understandable ! Elisp that supports both older and newer APIs, and has no byte compiler ! warnings. Currently many warnings are unavoidable, and as a result, ! they are simply ignored, which also causes a lot of legitimate warnings ! to be ignored. ! ! The approach taken by the Sysdep package to make sure that the newest ! API was always supported was fairly simple: when the Sysdep package was ! loaded, it checked for the existence of new API functions, and if they ! weren't defined, it defined them in terms of older API functions that ! were defined. This had the advantage that the checks for which API ! functions were defined were done only once at load time rather than each ! time the function was called. However, the fact that the new APIs were ! globally defined caused a lot of problems with unwanted interactions, ! both with other versions of the Sysdep package provided as part of other ! packages, and simply with compatibility code of other sorts in packages ! that would determine whether an API existed by checking for the ! existence of certain functions within that API. In addition, the Sysdep ! package did not scale well because it defined all of the functions that ! it supported, regardless of whether or not they were used. ! ! The Compat package remedies the first problem by ensuring that the ! new APIs are defined only within the lexical scope of the packages that ! actually make use of the Compat package. It remedies the second problem ! by ensuring that only definitions of functions that are actually used ! are loaded. This all works roughly according to the following scheme: ! ! 1. Part of the Compat package is a module called the Compat ! generator. This module is actually run as an additional step ! during byte compilation of a package that uses Compat. This can ! happen either through the makefile or through the use of an ! `eval-when-compile' call within the package code itself. What the ! generator does is scan all of the Lisp code in the package, ! determine which function calls are made that the Compat package ! knows about, and generates custom `compat' code that conditionally ! defines just these functions when the package is loaded. The ! custom `compat' code can either be written to a separate Lisp file ! (for use with multi-file packages), or inserted into the beginning ! of the Lisp file of a single file package. (In the latter case, ! the package indicates where this generated code should go through ! the use of magic comments that mark the beginning and end of the ! section. Some will say that doing this trick is bad juju, but I ! have done this sort of thing before, and it works very well in ! practice). ! ! 2. The functions in the custom `compat' code have their names ! prefixed with both the name of the package and the word `compat', ! ensuring that there will be no name space conflicts with other ! functions in the same package, or with other packages that make ! use of the Compat package. ! ! 3. The actual definitions of the functions in the custom `compat' ! code are determined at run time. When the equivalent API already ! exists, the wrapper functions are simply defined directly in terms ! of the actual functions, so that the only run time overhead from ! using the Compat package is one additional function call. ! (Alternatively, even this small overhead could be avoided by ! retrieving the definitions of the actual functions and supplying ! them as the definitions of the wrapper functions. However, this ! appears to me to not be completely safe. For example, it might ! have bad interactions with the advice package). ! ! 4. The code that wants to make use of the custom `compat' code is ! bracketed by a call to the construct `compat-execute'. What this ! actually does is lexically bind all of the function names that are ! being redefined with macro functions by using the Common Lisp ! macro macrolet. (The definition of this macro is in the CL ! package, but in order for things to work on all platforms, the ! definition of this macro will presumably have to be copied and ! inserted into the custom `compat' code). ! ! ! In addition, the Compat package should define the macro ! `compat-if-fboundp'. Similar macros such as `compile-when-fboundp' and ! `compile-case-fboundp' could be defined using similar principles). The ! `compat-if-fboundp' macro behaves just like an `(if (fboundp ...) ...)' ! clause when executed, but in addition, when it's compiled, it ensures ! that the code inside the `if-true' sub-block will not cause any byte ! compiler warnings about the function in question being unbound. I ! think that the way to implement this would be to make ! `compat-if-fboundp' be a macro that does what it's supposed to do, but ! which defines its own byte code handler, which ensures that the ! particular warning in question will be suppressed. (Actually ensuring ! that just the warning in question is suppressed, and not any others, ! might be rather tricky. It certainly requires further thought). ! ! Note: An alternative way of avoiding both warnings about unbound ! functions and warnings about obsolete functions is to just call the ! function in question by using `funcall', instead of calling the ! function directly. This seems rather inelegant to me, though, and ! doesn't make it obvious why the function is being called in such a ! roundabout manner. Perhaps the Compat package should also provide a ! macro `compat-funcall', which works exactly like `funcall', but which ! indicates to anyone reading the code why the code is expressed in such ! a fashion. ! ! If you're wondering how to implement the part of the Compat generator ! where it scans Lisp code to find function calls for functions that it ! wants to do something about, I think the best way is to simply process ! the code using the Lisp function `read' and recursively descend any ! lists looking for function names as the first element of any list ! encountered. This might extract out a few more functions than are ! actually called, but it is almost certainly safer than doing anything ! trickier like byte compiling the code, and attempting to look for ! function calls in the result. (It could also be argued that the names ! of the functions should be extracted, not only from the first element of ! lists, but anywhere `symbol' occurs. For example, to catch places ! where a function is called using `funcall' or `apply'. However, such ! uses of functions would not be affected by the surrounding macrolet ! call, and so there doesn't appear to be any point in extracting them).  ! File: internals.info, Node: Future Work -- Drag-n-Drop, Next: Future Work -- Standard Interface for Enabling Extensions, Prev: Future Work -- Elisp Compatibility Package, Up: Future Work ! 40.3 Future Work - Drag-n-Drop ============================== ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! *Abstract:* I propose completely redoing the drag-n-drop interface ! to make it powerful and extensible enough to support such concepts as ! drag over and drag under visuals and context menus invoked when a drag ! is done with the right mouse button, to allow drop handlers to be ! defined for all sorts of graphical elements including buffers, extents, ! mode lines, toolbar items, menubar items, glyphs, etc., and to allow ! different packages to add and remove drop handlers for the same drop ! sites without interfering with each other. The changes are extensive ! enough that I think they can only be implemented in version 22, and the ! drag-n-drop interface should remain experimental until then. ! ! The new drag-n-drop interface centers around the twin concepts of ! "drop site" and "drop handler". A "drop site" specifies a particular ! graphical element where an object can be dropped onto, and a "drop ! handler" encapsulates all of the behavior that happens when such an ! object is dragged over and dropped onto a drop site. ! ! Each drop site has an object associated with it which is passed to ! functions that are part of the drop handlers associated with that site. ! The type of this object depends on the graphical element that comprises ! the drop site. The drop site object can be a buffer, an extent, a ! glyph, a menu path, a toolbar item path, etc. (These last two object ! types are defined in Lisp Interface Changes (lisp-interface.html) in ! the sections on menu and toolbar API changes. If we wanted to allow ! drops onto other kinds of drop sites, for example mode lines, we would ! have to create corresponding path objects). Each such object type ! should be able to be accessed using the generalized property interface ! defined above, and should have a property called `drop-handlers' ! associated with it that specifies all of the drop handlers associated ! with the drop site. Normally, this property is not accessed directly, ! but instead by using the drop handler API defined below, and Lisp ! packages should not make any assumptions about the format of the data ! contained in the `drop-handlers' property. ! ! Each drop handler has an object of type `drop-handler' associated ! with it, whose primary purpose is to be a container for the various ! properties associated with a particular drop handler. These could ! include, for example, a function invoked when the drop occurs, a context ! menu invoked when a drop occurs as a result of a drag with the right ! mouse button, functions invoked when a dragged object enters, leaves, or ! moves within a drop site, the shape that the mouse pointer changes to ! when an object is dragged over a drop site that allows this particular ! object to be dropped onto it, the MIME types (actually a regular ! expression matching the MIME types) of the allowable objects that can be ! dropped onto the drop site, a "package tag" (a symbol specifying the ! package that created the drop handler, used for identification ! purposes), etc. The drop handler object is passed to the functions that ! are invoked as a result of a drag or a drop, most likely indirectly as ! one of the properties of the drag or drop event passed to the function. ! Properties of a drop handler object are accessed and modified in the ! standard fashion using the generalized property interface. ! ! A drop handler is added to a drop site using the `add-drop-handler' ! function. The drop handler itself can either be created separately ! using the `make-drop-handler' function and then passed in as one of the ! parameters to `add-drop-handler', or it will be created automatically ! by the `add-drop-handler' function, if the drop handler argument is ! omitted, but keyword arguments corresponding to the valid keyword ! properties for a drop handler are specified in the `add-drop-handler' ! call. Other functions, such as `find-drop-handler', `add-drop-handler' ! (when specifying a drop handler before which the drop handler in ! question is to be added), `remove-drop-handler' etc. should be defined ! with obvious semantics. All of these functions take or return a drop ! site object which, as mentioned above, can be one of several object ! types corresponding to graphical elements. Defined drop handler ! functions locate a particular drop handler using either the `MIME-type' ! or `package-tag' property of the drop handler, as defined above. ! ! Logically, the drop handlers associated with a particular drop site ! are an ordered list. The first drop handler whose specified MIME type ! matches the MIME type of the object being dragged or dropped controls ! what happens to this object. This is important particularly because the ! specified MIME type of the drop handler can be a regular expression ! that, for example, matches all audio objects with any sub-type. ! ! In the current drag-n-drop API, there is a distinction made between ! objects with an associated MIME type and objects with an associated URL. ! I think that this distinction is arbitrary, and should not exist. All ! objects should have a MIME type associated with them, and a new ! XEmacs-specific MIME type should be defined for URLs, file names, etc. ! as necessary. I am not even sure that this is necessary, however, as ! the MIME specification may specify a general concept of a pointer or ! link to an object, which is exactly what we want. Also in some cases ! (for example, the name of a file that is locally available), the pointer ! or link will have another MIME type associated with it, which is the ! type of the object that is being pointed to. I am not quite sure how we ! should handle URL and file name objects being dragged, but I am positive ! that it needs to be integrated with the mechanism used when an object ! itself is being dragged or dropped. ! ! As is described in a separate page (misc-user-event.html), the ! `misc-user-event' event type should be removed and split up into a ! number of separate event types. Two such event types would be ! `drag-event' and `drop-event'. A drop event is used when an object is ! actually dropped, and a drag event is used if a function is invoked as ! part of the dragging process. (Such a function would typically be used ! to control what are called "drag under visuals", which are changes to ! the appearance of the drop site reflecting the fact that a compatible ! object is being dragged over it). The drag events and drop events ! encapsulate all of the information that is pertinent to the drag or ! drop action occurring, including such information as the actual MIME ! type of the object in question, the drop handler that caused a function ! to be invoked, the mouse event (or possibly even a keyboard event) ! corresponding to the user's action that is causing the drag or drop, ! etc. This event is always passed to any function that is invoked as a ! result of the drag or drop. There should never be any need to refer to ! the `current-mouse-event' variable, and in fact, this variable should ! not be changed at all during a drag or a drop. ! !  ! File: internals.info, Node: Future Work -- Standard Interface for Enabling Extensions, Next: Future Work -- Better Initialization File Scheme, Prev: Future Work -- Drag-n-Drop, Up: Future Work ! ! 40.4 Future Work - Standard Interface for Enabling Extensions ! ============================================================= ! ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! *Abstract:* Apparently, if you know the name of a package (for ! example, `fusion'), you can load it using the `require' function, but ! there's no standard way to turn it on or turn it off. The only way to ! figure out how to do that is to go read the source file, where ! hopefully the comments at the start tell you the appropriate magic ! incantations that you need to run in order to turn the extension on or ! off. There really needs to be standard functions, such as ! `enable-extension' and `disable-extension', to do this sort of thing. ! It seems like a glaring omission that this isn't currently present, and ! it's really surprising to me that nobody has remarked on this. ! ! The easy part of this is defining the interface, and I think it ! should be done as soon as possible. When the package is loaded, it ! simply calls some standard function in the package system, and passes ! it the names of enable and disable functions, or perhaps just one ! function that takes an argument specifying whether to enable or ! disable. In any case, this data is kept in a table which is used by the ! `enable-extension' and `disable-extension' function. There should also ! be functions such as `extension-enabled-p' and ! `enabled-extension-list', and so on with obvious semantics. The hard ! part is actually getting packages to obey this standard interface, but ! this is mitigated by the fact that the changes needed to support this ! interface are so simple. ! ! I have been conceiving of these enabling and disabling functions as ! turning the feature on or off globally. It's probably also useful to ! have a standard interface returning a extension on or off in just the ! particular buffer. Perhaps then the appropriate interface would involve ! registering a single function that takes an argument that specifies ! various things, such as turn off globally, turn on globally, turn on or ! off in the current buffer, etc. ! ! Part of this interface should specify the correct way to define ! global key bindings. The correct rule for this, of course, is that the ! key bindings should not happen when the package is loaded, which is ! often how things are currently done, but only when the extension is ! actually enabled. The key bindings should go away when the extension is ! disabled. I think that in order to support this properly, we should ! expand the keymap interface slightly, so that in addition to other ! properties associated with each key binding is a list of shadow ! bindings. Then there should be a function called ! `define-key-shadowing', which is just like `define-key' but which also ! remembers the previous key binding in a shadow list. Then there can be ! another function, something like `undefine-key', which restores the ! binding to the most recently added item on the shadow list. There are ! already hash tables associated with each key binding, and it should be ! easy to stuff additional values, such as a shadow list, into the hash ! table. Probably there should also be functions called ! `global-set-key-shadowing' and `global-unset-key-shadowing' with ! obvious semantics. ! ! Once this interface is defined, it should be easy to expand the ! custom package so it knows about this interface. Then it will be ! possible to put all sorts of extensions on the options menu so that ! they could be turned off and turned on very easily, and then when you ! save the options out to a file, the design settings for whether these ! extensions are enabled or not are saved out with it. A whole lot of ! custom junk that's been added to a lot of different packages could be ! removed. After doing this, we might want to think of a way to classify ! extensions according to how likely we think the user will want to use ! them. This way we can avoid the problem of having a list of 100 ! extensions and the user not being able to figure out which ones might ! be useful. Perhaps the most useful extensions would appear immediately ! on the extensions menu, and the less useful ones would appear in a ! submenu of that, and another submenu might contain even less useful ! extensions. Of course the package authors might not be too happy with ! this, but the users probably will be. I think this at least deserves a ! thought, although it's possible you might simply want to maintain a ! list on the web site of extensions and a judgment on first of all, how ! commonly a user might want this extension, and second of all, how well ! written and bug-free the package is. Both of these sorts of judgments ! could be obtained by doing user surveys if need be. ! !  ! File: internals.info, Node: Future Work -- Better Initialization File Scheme, Next: Future Work -- Keyword Parameters, Prev: Future Work -- Standard Interface for Enabling Extensions, Up: Future Work ! ! 40.5 Future Work - Better Initialization File Scheme ! ==================================================== ! ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! *Abstract:* A proposal is outlined for converting XEmacs to use the ! `.xemacs' subdirectory for its initialization files instead of putting ! them in the user's home directory. In the process, a general ! pre-initialization scheme is created whereby all of the initialization ! parameters, such as the location of the initialization files, whether ! these files are loaded or not, where the initial frame is created, etc. ! that are currently specified by command line arguments, by environment ! variables, and other means, can be specified in a uniform way using ! Lisp code. Reasonable default behavior for everything will still be ! provided, and the older, simpler means can be used if desired. ! Compatibility with the current location and name of the initialization ! file, and the current ill-chosen use for the `.xemacs' directory is ! maintained, and the problem of how to gracefully migrate a user from the ! old scheme into the new scheme while still allowing the user to use GNU ! Emacs or older versions of XEmacs is solved. A proposal for changing ! the way that the initial frame is mapped is also outlined; this would ! allow the user's initialization file to control the way that the initial ! frame appears without resorting to hacks, while still making echo area ! messages visible as they appear, and allowing the user to debug errors ! in the initialization file. ! ! Principles in the new scheme ! ---------------------------- ! ! 1. XEmacs has a defined "pre-initialization process". This process, ! whose purpose is to compute the values of the parameters that ! control how the initializiaton process proceeds, occurs as early ! as possible after the Lisp engine has been initialized, and in ! particular, it occurs before any devices have been opened, or ! before any initialization parameters are set that could reasonably ! be expected to be changed. In fact, the pre-initialization ! process should take care of setting these parameters. The code ! that implements the pre-initialization process should be written ! in Lisp and should be called from the Lisp function ! `normal-top-level', and the general way that the user customizes ! this process should also be done using Lisp code. ! ! 2. The pre-initialization process involves a number of properties, ! for example the directory containing the user initialization files ! (normally the `.xemacs' subdirectory), the name of the user init ! file, the name of the custom init file, where and what type the ! initial device is, whether and when the initial frame is mapped, ! etc. A standard interface is provided for getting and setting the ! values of these properties using functions such as ! `set-pre-init-property', `pre-init-property', etc. At various ! points during the pre-initialization process, the value of many of ! these properties can be undecided, which means that at the end of ! the process, the value of these properties will be derived from ! other properties in some fashion that is specific to each property. ! ! 3. The default values of these properties are set first from the ! registry under Windows, then from environment variables, then from ! command line switches, such as `-q' and `-nw'. ! ! 4. One of the command line switches is `-pre-init', whose value is a ! Lisp expression to be evaluated at pre-initialization time, ! similar to the `-eval' command line switch. This allows any ! pre-initialization property to be set from the command line. ! ! 5. Let's define the term "to determine a pre-initialization ! property" to mean if the value of a property is undetermined, it ! is computed and set according to a rule that is specific to the ! property. Then after the pre-init properties are initialized from ! the registry, from the environment variables, from command line ! arguments, two of the pre-init properties (specifically the init ! file directory and the location of the "pre-init file") are ! determined. The purpose of the pre-init file is to contain Lisp ! code that is run at pre-initialization time, and to control how ! the initialization proceeds. It is a bit similar to the standard ! init file, but the code in the pre-init file shouldn't do anything ! other than set pre-init properties. Executing any code that does ! I/O might not produce expected results because the only device that ! will exist at the time is probably a stream device connected to the ! standard I/O of the XEmacs process. ! ! 6. After the pre-init file has been run, all of the rest of the ! pre-init properties are determined, and these values are then used ! to control the initialization process. Some of the rules used in ! determining specific properties are: ! ! 1. If the `.xemacs' sub-directory exists, and it's not ! obviously a package root (which probably means that it ! contains a file like `init.el' or `pre-init.el', or if ! neither of those files is present, then it doesn't contain ! any sub-directories or files that look like what would be in ! a package root), then it becomes the value of the init file ! directory. Otherwise the user's home directory is used. ! ! 2. If the init file directory is the user's home directory, ! then the init file is called `.emacs'. Otherwise, it's ! called `init.el'. ! ! 3. If the init file directory is the user's home directory, ! then the pre-init file is called `.xemacs-pre-init.el'. ! Otherwise it's called `pre-init.el'. (One of the reasons for ! this rule has to do with the dialog box that might be ! displayed at startup. This will be described below.) ! ! 4. If the init file directory is the user's home directory, ! then the custom init file is called `.xemacs-custom-init.el'. ! Otherwise, it's called `custom-init.el'. ! ! ! 7. After the first normal device is created, but before any frames ! are created on it, the XEmacs initialization code checks to see if ! the old init file scheme is being used, which is to say that the ! init file directory is the same as the user's home directory. If ! that's the case, then normally a dialog box comes up (or a ! question is asked on the terminal if XEmacs is being run in a ! non-windowing mode) which asks if the user wants to migrate his ! initialization files to the new scheme. The possible responses ! are *Yes*, *No*, and *No, and don't ask this again*. If this last ! response is chosen, then the file `.xemacs-pre-init.el' in the ! user's home directory is created or appended to with a line of ! Lisp code that sets up a pre-init property indicating that this ! dialog box shouldn't come up again. If the *Yes* option is ! chosen, then any package root files in `.xemacs' are moved into ! `.xemacs/packages', the file `.emacs' is moved into ! `.xemacs/init.el' and `.emacs' in the home directory becomes a ! symlink to this file. This way some compatibility is still ! maintained with GNU Emacs and older versions of XEmacs. The code ! that implements this has to be written very carefully to make sure ! that it doesn't accidentally delete or mess up any of the files ! that get moved around. ! ! ! The custom init file ! -------------------- ! ! The "custom init file" is where the custom package writes its options. ! This obviously needs to be a separate file from the standard init file. ! It should also be loaded before the init file rather than after, as is ! usually done currently, so that the init file can override these ! options if it wants to. ! ! Frame mapping ! ------------- ! ! In addition to the above scheme, the way that XEmacs handles mapping the ! initial frame should be changed. However, this change perhaps should be ! delayed to a later version of XEmacs because of the user visible changes ! that it entails and the possible breakage in people's init files that ! might occur. (For example, if the rest of the scheme is implemented in ! 21.2, then this part of the scheme might want to be delayed until ! version 22.) The basic idea is that the initial frame is not created ! before the initialization file is run, but instead a banner frame is ! created containing the XEmacs logo, a button that allows the user to ! cancel the execution of the init file and an area where messages that ! are output in the process of running this file are displayed. This area ! should contain a number of lines, which makes it better than the current ! scheme where only the last message is visible. After the init file is ! done, the initial frame is mapped. This way the init file can make face ! changes and other such modifications that affect initial frame and then ! have the initial frame correctly come up with these changes and not see ! any frame dancing or other problems that exist currently. ! ! There should be a function that allows the initialization file to ! explicitly create and map the first frame if it wants to. There should ! also be a pre-init property that controls whether the banner frame ! appears (of course it defaults to true) a property controlling when the ! initial frame is created (before or after the init file, defaulting to ! after), and a property controlling whether the initial frame is mapped ! (normally true, but will be false if the `-unmapped' command line ! argument is given). ! ! If an error occurs in the init file, then the initial frame should ! always be created and mapped at that time so that the error is displayed ! and the debugger has a place to be invoked. ! !  ! File: internals.info, Node: Future Work -- Keyword Parameters, Next: Future Work -- Property Interface Changes, Prev: Future Work -- Better Initialization File Scheme, Up: Future Work ! ! 40.6 Future Work - Keyword Parameters ! ===================================== ! ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! NOTE: These changes are partly motivated by the various ! user-interface changes elsewhere in this document, and partly for Mule ! support. In general the various APIs in this document would benefit ! greatly from built-in keywords. ! ! I would like to make keyword parameters an integral part of Elisp. ! The idea here is that you use the `&key' identifier in the ! parameter list of a function and all of the following parameters ! specified are keyword parameters. This means that when these arguments ! are specified in a function call, they are immediately preceded in the ! argument list by a "keyword", which is a symbol beginning with the `:' ! character. This allows any argument to be specified independently of ! any other argument with no need to place the arguments in any ! particular order. This is particularly useful for functions that take ! many optional parameters; using keyword parameters makes the code much ! cleaner and easier to understand. ! ! The `cl' package already provides keyword parameters of a sort, but ! I would like to make this more integrated and useable in a standard ! fashion. The interface that I am proposing is essentially compatible ! with the keyword interface in Common Lisp, but it may be a subset of the ! Common Lisp functionality, especially in the first implementation. ! There is one departure from the Common Lisp specification that I would ! like to make in order to make it much easier to add keyword parameters ! to existing functions with optional parameters, and in general, to make ! optional and keyword parameters coexist more easily. The Common Lisp ! specification indicates that if a function has both optional and keyword ! parameters, the optional parameters are always processed before the ! keyword parameters. This means, for example, that if a function has ! three required parameters, two optional parameters, and some number of ! keyword parameters following, and the program attempts to call this ! function by passing in the three required arguments, and then some ! keyword arguments, the first keyword specified and the argument ! following it get assigned to the first and second optional parameters as ! specified in the function definition. This is certainly not what is ! intended, and means that if a function defines both optional and keyword ! parameters, any calls of this function must specify `nil' for all of ! the optional arguments before using any keywords. If the function ! definition is later changed to add more optional parameters, all ! existing calls to this function that use any keyword arguments will ! break. This problem goes away if we simply process keyword parameters ! before the optional parameters. ! ! The primary changes needed to support the keyword syntax are: ! ! 1. The subr object type needs to be modified to contain additional ! slots for the number and names of any keyword parameters. ! ! 2. The implementation of the `funcall' function needs to be modified ! so that it knows how to process keyword parameters. This is the ! only place that will require very much intricate coding, and much ! of the logic that would need to be added can be lifted directly ! from the `cl' code. ! ! 3. A new macro, similar to the `DEFUN' macro, and probably called ! `DEFUN_WITH_KEYWORDS', needs to be defined so that built-in Lisp ! primitives containing keywords can be created. Now, the ! `DEFUN_WITH_KEYWORDS' macro should take an additional parameter ! which is a string, which consists of the part of the lambda list ! declaration for this primitive that begins with the `&key' ! specifier. This string is parsed in the `DEFSUBR' macro during ! XEmacs initialization, and is converted into the appropriate ! structure that needs to be stored into the subr object. In ! addition, the MAX_ARGS parameter of the `DEFUN' macro needs to be ! incremented by the number of keyword parameters and these ! parameters are passed to the C function simply as extra parameters ! at the end. The `DEFSUBR' macro can sort out the actual number of ! required, optional and keyword parameters that the function takes, ! once it has parsed the keyword parameter string. (An alternative ! that might make the declaration of a primitive a little bit easier ! to understand would involve adding another parameter to the ! `DEFUN_WITH_KEYWORDS' macro that specifies the number of keyword ! parameters. However, this would require some additional ! complexity in the preprocessor definition of the ! `DEFUN_WITH_KEYWORDS' macro, and probably isn't worth ! implementing). ! ! 4. The byte compiler would have to be modified slightly so that it ! knows about keyword parameters when it parses the parameter ! declaration of a function. For example, so that it issues the ! correct warnings concerning calls to that function with incorrect ! arguments. ! ! 5. The `make-docfile' program would have to be modified so that it ! generates the correct parameter lists for primitives defined using ! the `DEFUN_WITH_KEYWORDS' macro. ! ! 6. Possibly other aspects of the help system that deal with function ! descriptions might have to be modified. ! ! 7. A helper function might need to be defined to make it easier for ! primitives that use both the `&rest' and `&key' specifiers ! to parse their argument lists. ! ! ! Internal API for C primitives with keywords - necessary for many of the new Mule APIs being defined. ! ---------------------------------------------------------------------------------------------------- ! ! DEFUN_WITH_KEYWORDS (Ffoo, "foo", 2, 5, 6, ALLOW_OTHER_KEYWORDS, ! (ichi, ARG_NIL), (ni, ARG_NIL), (san, ARG_UNBOUND), 0, ! (arg1, arg2, arg3, arg4, arg5) ! ) ! { ! ... ! } ! ! -> C fun of 12 args: ! ! (arg1, ... arg5, ichi, ..., roku, other keywords) ! ! Circled in blue is actual example declaration ! ! DEFUN_WITH_KEYWORDS (Ffoo, "foo", 1,2,0 (bar, baz) <- arg list ! [ MIN ARGS, MAX ARGS, something that could be REST, SPECIFY_DEFAULT or ! REST_SPEC] ! ! [#KEYWORDS [ ALLOW_OTHER, SPECIFY_DEFAULT, ALLOW_OTHER_SPECIFY_DEFAULT ! 6, ALLOW_OTHER_SPECIFY_DEFAULT, ! ! (ichi, 0) (ni, 0), (san, DEFAULT_UNBOUND), (shi, "t"), (go, "5"), ! (roku, "(current-buffer)") ! <- specifies arguments, default values (string to be read into Lisp ! data during init; then forms evalled at fn ref time. ! ! ,0 <- [INTERACTIVE SPEC] ) ! ! LO = Lisp_Object ! ! -> LO Ffoo (LO bar, LO baz, LO ichi, LO ni, LO san, LO shi, LO go, ! LO roku, int numkeywords, LO *other_keywords) ! ! #define DEFUN_WITH_KEYWORDS (fun, funstr, minargs, maxargs, argspec, \ ! #args, num_keywords, keywordspec, keywords, intspec) \ ! LO fun (DWK_ARGS (maxargs, args) \ ! DWK_KEYWORDS (num_keywords, keywordspec, keywords)) ! ! #define DWK_KEYWORDS (num_keywords, keywordspec, keywords) \ ! DWK_KEYWORDS ## keywordspec (keywords) ! DWK_OTHER_KEYWORDS ## keywordspec) ! ! #define DWK_KEYWORDS_ALLOW_OTHER (x,y) ! DWK_KEYWORDS (x,y) ! ! #define DWK_KEYWORDS_ALLOW_OTHER_SPECIFICATIONS (x,y) ! DWK_KEYWORDS_SPECIFY_DEFAULT (x,y) ! ! #define DWK_KEYWORDS_SPECIFY_DEFAULT (numkey, key) ! ARGLIST_CAR ## numkey key ! #define ARGLT_GRZ (x,y) LO CAR x, LO CAR y !  ! File: internals.info, Node: Future Work -- Property Interface Changes, Next: Future Work -- Toolbars, Prev: Future Work -- Keyword Parameters, Up: Future Work ! 40.7 Future Work - Property Interface Changes ! ============================================= ! Author: Ben Wing (mailto:ben@xemacs.org) ! In my past work on XEmacs, I already expanded the standard property ! functions of `get', `put', and `remprop' to work on objects other than ! symbols and defined an additional function `object-plist' for this ! interface. I'd like to expand this interface further and advertise it ! as the standard way to make property changes in objects, especially the ! new objects that are going to be defined in order to support the added ! user interface features of version 22. My proposed changes are as ! follows: ! ! 1. A new concept associated with each property called a "default ! value" is introduced. (This concept already exists, but not in a ! well-defined way.) The default value is the value that the ! property assumes for certain value retrieval functions such as ! `get' when it is "unbound", which is to say that its value has not ! been explicitly specified. Note: the way to make a property ! unbound is to call `remprop'. Note also that for some built-in ! properties, setting the property to its default value is ! equivalent to making it unbound. ! ! 2. The behavior of the `get' function is modified. If the `get' ! function is called on a property that is unbound and the third, ! optional DEFAULT argument is `nil', then the default value of the ! property is returned. If the DEFAULT argument is not `nil', then ! whatever was specified as the value of this argument is returned. ! For the most part, this is upwardly compatible with the existing ! definition of `get' because all user-defined properties have an ! initial default value of `nil'. Code that calls the `get' ! function and specifies `nil' for the DEFAULT argument, and expects ! to get `nil' returned if the property is unbound, is almost ! certainly wrong anyway. ! ! 3. A new function, `get1' is defined. This function does not take a ! default argument like the `get' function. Instead, if the property ! is unbound, an error is signaled. Note: `get' can be implemented ! in terms of `get1'. ! ! 4. New functions `property-default-value' and `property-bound-p' are ! defined with the obvious semantics. ! ! 5. An additional function `property-built-in-p' is defined which ! takes two arguments, the first one being a symbol naming an object ! type, and the second one specifying a property, and indicates ! whether the property name has a built-in meaning for objects of ! that type. ! ! 6. It is not necessary, or even desirable, for all object types to ! allow user-defined properties. It is always possible to simulate ! user-defined properties for an object by using a weak hash table. ! Therefore, whether an object allows a user to define properties or ! not should depend on the meaning of the object. If an object does ! not allow user-defined properties, the `put' function should ! signal an error, such as `undefined-property', when given any ! property other than those that are predefined. ! ! 7. A function called `user-defined-properties-allowed-p' should be ! defined with the obvious semantics. (See the previous item.) ! ! 8. Three more functions should be defined, called ! `built-in-property-name-list', `property-name-list', and ! `user-defined-property-name-list'. ! ! ! Another idea: ! ! (define-property-method ! predicate object-type ! predicate cons :(KEYWORD) (all lists beginning with KEYWORD) ! ! :put putfun ! :get ! :remprop ! :object-props ! :clear-properties ! :map-properties ! e.g. (define-property-method 'hash-table ! :put #'(lambda (obj key value) (puthash key obj value))) !  ! File: internals.info, Node: Future Work -- Toolbars, Next: Future Work -- Menu API Changes, Prev: Future Work -- Property Interface Changes, Up: Future Work ! 40.8 Future Work - Toolbars ! =========================== ! * Menu: ! * Future Work -- Easier Toolbar Customization:: ! * Future Work -- Toolbar Interface Changes:: !  ! File: internals.info, Node: Future Work -- Easier Toolbar Customization, Next: Future Work -- Toolbar Interface Changes, Prev: Future Work -- Toolbars, Up: Future Work -- Toolbars ! 40.8.1 Future Work - Easier Toolbar Customization ! ------------------------------------------------- ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! *Abstract:* One of XEmacs' greatest strengths is its ability to be ! customized endlessly. Unfortunately, it is often too difficult to ! figure out how to do this. There has been some recent work like the ! Custom package, which helps in this regard, but I think there's a lot ! more work that needs to be done. Here are some ideas (which certainly ! could use some more thought). ! ! Although there is currently an `edit-toolbar' package, it is not ! well integrated with XEmacs, and in general it is much too hard to ! customize the way toolbars look. I would like to see an interface that ! works a bit like the way things work under Windows, where you can ! right-click on a toolbar to get a menu of options that allows you to ! change aspects of the toolbar. The general idea is that if you ! right-click on an item itself, you can do things to that item, whereas ! if you right-click on a blank part of a toolbar, you can change the ! properties of the toolbar. Some of the items on the right-click menu ! for a particular toolbar button should be specified by the button ! itself. Others should be standard. For example, there should be an ! *Execute* item which simply does what would happen if you left-click on ! a toolbar button. There should probably be a *Delete* item to get rid ! of the toolbar button and a *Properties* item, which brings up a ! property sheet that allows you to do things like change the icon and ! the command string that's associated with the toolbar button. ! ! The options to change the appearance of the toolbar itself should ! probably appear both on the context menu for specific buttons, and on ! the menu that appears when you click on a blank part of the toolbar. ! That way, if there isn't a blank part of the toolbar, you can still ! change the toolbar appearance. As for what appears in these items, in ! Outlook Express, for example, there are three different menu items, one ! of which is called *Buttons*, which brings up, or pops up a window ! which allows you to edit the toolbar, which for us could pop up a new ! frame, which is running `edit-toolbar.el'. The second item is called ! *Align*, which contains a submenu that says *Top*, *Bottom*, *Left*, ! and *Right*, which will be just like setting the default toolbar ! position. The third one says *Text Labels*, which would just let you ! select whether there are captions or not. I think all three of these ! are useful and are easy to implement in XEmacs. These things also need ! to be integrated with custom so that a user can control whether these ! options apply to all sessions, and in such a case can save the settings ! out to an options file. `edit-toolbar.el' in particular needs to ! integrate with custom. Currently it has some sort of hokey stuff of ! its own, which it saves out to a `.toolbar' file. Another useful ! option to have, once we draw the captions dynamically rather than using ! pre-generated ones, would be the ability to change the font size of the ! captions. I'm sure that Kyle, for one, would appreciate this. ! ! (This is incomplete.....) ! !  ! File: internals.info, Node: Future Work -- Toolbar Interface Changes, Prev: Future Work -- Easier Toolbar Customization, Up: Future Work -- Toolbars ! ! 40.8.2 Future Work - Toolbar Interface Changes ! ---------------------------------------------- ! ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! I propose changing the way that toolbars are specified to make them ! more flexible. ! ! 1. A new format for the vector that specifies a toolbar item is ! allowed. In this format, the first three items of the vector are ! required and are, respectively, a caption, a glyph list, and a ! callback. The glyph list and callback arguments are the same as ! in the current toolbar item specification, and the caption is a ! string specifying the caption text placed below the toolbar glyph. ! The caption text is required so that toolbar items can be ! identified for the purpose of retrieving and changing their ! property values. Putting the caption first also makes it easy to ! distinguish between the new and the old toolbar item vector ! formats. In the old format, the first item, the glyph list, is ! either a list or a symbol. In the new format, the first item is a ! string. In the new format, following the three required items, ! are optional keyword items specified using keywords in the same ! format as the menu item vector format. The keywords that should ! be predefined are: `:help-echo', `:context-menu', ! `:drop-handlers', and `:enabled-p'. The `:enabled-p' and ! `:help-echo' keyword arguments are the same as the third and ! fourth items in the old toolbar item vector format. The ! `:context-menu' keyword is a list in standard menu format that ! specifies additional items that will appear when the context menu ! for the toolbar item is popped up. (Typically, this happens when ! the right mouse button is clicked on the toolbar item). The ! `:drop-handlers' keyword is for use by the new drag-n-drop ! interface (see Drag-n-Drop Interface Changes (drag-n-drop.html) ), ! and is not normally specified or modified directly. ! ! 2. Conceivably, there could also be keywords that are associated ! with a toolbar itself, rather than with a particular toolbar item. ! These keyword properties would be specified using keywords and ! arguments that occur before any toolbar item vectors, similarly to ! how things are done in menu specifications. Possible properties ! could include `:captioned-p' (whether the captions are visible ! under the toolbar), `:glyphs-visible-p' (whether the toolbar ! glyphs are visible), and `:context-menu' (additional items that ! will appear on the context menus for all toolbar items and ! additionally will appear on the context menu that is popped up ! when the right mouse button is clicked over a portion of the ! toolbar that does not have any toolbar buttons in it). The ! current standard practice with regards to such properties seems to ! be to have separate specifiers, such as `left-toolbar-width', ! `right-toolbar-width', `left-toolbar-visible-p', ! `right-toolbar-visible-p', etc. It could easily be argued that ! there should be no such toolbar specifiers and that all such ! properties should be part of the toolbar instantiator itself. In ! this scheme, the only separate specifiers that would exist for ! individual properties would be default values. There are a lot of ! reasons why an interface change like this makes sense. For ! example, currently when VM sets its toolbar, it also sets the ! toolbar width and similar properties. If you change which edge of ! the frame the VM toolbar occurs in, VM will also have to go and ! modify all of the position-specific toolbar specifiers for all of ! the other properties associated with a toolbar. It doesn't really ! seem to make sense to me for the user to be specifying the width ! and visibility and such of specific toolbars that are attached to ! specific edges because the user should be free to move the ! toolbars around and expect that all of the toolbar properties ! automatically move with the toolbar. (It is also easy to imagine, ! for example, that a toolbar might not be attached to the edge of ! the frame at all, but might be floating somewhere on the user's ! screen). With an interface where these properties are separate ! specifiers, this has to be done manually. Currently, having the ! various toolbar properties be inside of toolbar instantiators ! makes them difficult to modify, but this will be different with ! the API that I propose below. ! ! 3. I propose an API for modifying toolbar and toolbar item ! properties, as well as making other changes to toolbar ! instantiators, such as inserting or deleting toolbar items. This ! API is based around the concept of a path. There are two kinds of ! paths here - "toolbar paths" and "toolbar item paths". Each kind ! of path is an object (of type `toolbar-path' and ! `toolbar-item-path', respectively) whose properties specify the ! location in a toolbar instantiator where changes to the ! instantiator can be made. A toolbar path, for example, would be ! created using the `make-toolbar-path' function, which takes a ! toolbar specifier (or optionally, a symbol, such as `left', ! `right', `default', or `nil', which refers to a particular ! toolbar), and optionally, parameters such as the locale and the ! tag set, which specify which actual instantiator inside of the ! toolbar specifier is to be modified. A toolbar item path is ! created similarly using a function called ! `make-toolbar-item-path', which takes a toolbar specifier and a ! string naming the caption of the toolbar item to be modified, as ! well as, of course, optionally the locale and tag set parameters ! and such. ! ! The usefulness of these path objects is as arguments to functions ! that will use them as pointers to the place in a toolbar ! instantiator where the modification should be made. Recall, for ! example, the generalized property interface described above. If a ! function such as `get' or `put' is called on a toolbar path or ! toolbar item path, it will use the information contained in the ! path object to retrieve or modify a property located at the end of ! the path. The toolbar path objects can also be passed to new ! functions that I propose defining, such as `add-toolbar-item', ! `delete-toolbar-item', and `find-toolbar-item'. These functions ! should be parallel to the functions for inserting, deleting, ! finding, etc. items in a menu. The toolbar item path objects can ! also be passed to the drop-handler functions defined in ! Drag-n-Drop Interface Changes (drag-n-drop.html) to retrieve or ! modify the drop handlers that are associated with a toolbar item. ! (The idea here is that you can drag an object and drop it onto a ! toolbar item, just as you could onto a buffer, an extent, a menu ! item, or any other graphical element). ! ! 4. We should at least think about allowing for separate default and ! buffer-local toolbars. The user should either be able to position ! these toolbars one above the other, or side by side, occupying a ! single toolbar line. In the latter case, the boundary between the ! toolbars should be draggable, and if a toolbar takes up more room ! than is allocated for it, there should be arrows that appear on ! one or both sides of the toolbar so that the items in the toolbar ! can be scrolled left or right. (For that matter, this sort of ! interface should exist even when there is only one toolbar that is ! on a particular toolbar line, because the toolbar may very well ! have more items than can be displayed at once, and it's silly in ! such a case if it's impossible to access the items that are not ! currently visible). ! ! 5. The default context menu for toolbars (which should be specified ! using a specifier called `default-toolbar-context-menu' according ! to the rules defined above) should contain entries allowing the ! user to modify the appearance of a toolbar. Entries would ! include, for example, whether the toolbar is captioned, whether ! the glyphs for the toolbar are visible (if the toolbar is ! captioned but its glyphs are not visible, the toolbar appears as ! nothing but text; you can set things up this way, for example, in ! Netscape), an option that brings up a package for editing the ! contents of a toolbar, an option to allow the caption face to be ! dchanged (perhaps thorough jan `edit-faces' or `custom' ! interface), etc.  ! File: internals.info, Node: Future Work -- Menu API Changes, Next: Future Work -- Removal of Misc-User Event Type, Prev: Future Work -- Toolbars, Up: Future Work ! 40.9 Future Work - Menu API Changes ! =================================== ! ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! 1. I propose making a specifier for the menubar associated with the ! frame. The specifier should be called `default-menubar' and ! should replace the existing `current-menubar' variable. This ! would increase the power of the menubar interface and bring it in ! line with the toolbar interface. (In order to provide proper ! backward compatibility, we might have to complete the symbol value ! handler mechanism (symbol-value-handlers.html)) ! ! 2. I propose an API for modifying menu instantiators similar to the ! API composed above for toolbar instantiators. A new object called ! a "menu path" (of type `menu-path') can be created using the ! `make-menu-path' function, and specifies a location in a particular ! menu instantiator where changes can be made. The first argument to ! `make-menu-path' specifies which menu to modify and can be a ! specifier, a value such as `nil' (which means to modify the default ! menubar associated with the selected frame), or perhaps some other ! kind of specification referring to some other menu, such as the ! context menus invoked by the right mouse button. The second ! argument to `make-menu-path', also required, is a list of zero or ! more strings that specifies the particular menu or menu item in ! the instantiator that is being referred to. The remaining ! arguments are optional and would be a locale, a tag set, etc. The ! menu path object can be passed to `get', `put' or other standard ! property functions to access or modify particular properties of a ! menu or a menu item. It can also be passed to expanded versions ! of the existing functions such as `find-menu-item', ! `delete-menu-item', `add-menu-button', etc. (It is really a shame ! that `add-menu-item' is an obsolete function because it is a much ! better name than `add-menu-button'). Finally, the menu path ! object can be passed to the drop-handler functions described in ! Drag-n-Drop Interface Changes (drag-n-drop.html) to access or ! modify the drop handlers that are associated with a particular ! menu item. ! ! 3. New keyword properties should be added to the menu item vector. ! These include `:help-echo', `:context-menu' and `:drop-handlers', ! with similar semantics to the corresponding keywords for toolbar ! items. (It may seem a bit strange at first to have a context menu ! associated with a particular menu item, but it is a user interface ! concept that exists both in Open Look and in Windows, and really ! makes a lot of sense if you give it a bit of thought). These ! properties may not actually be implemented at first, but at least ! the keywords for them should be defined. !  ! File: internals.info, Node: Future Work -- Removal of Misc-User Event Type, Next: Future Work -- Mouse Pointer, Prev: Future Work -- Menu API Changes, Up: Future Work ! 40.10 Future Work - Removal of Misc-User Event Type ! =================================================== ! Author: Ben Wing (mailto:ben@xemacs.org) ! *Abstract:* This page describes why the misc-user event type should ! be split up into a number of different event types, and how to do this. ! The misc-user event should not exist as a single event type. It ! should be split up into a number of different event types: one for ! scrollbar events, one for menu events, and one or two for drag-n-drop ! events. Possibly there will be other event types created in the ! future. The reason for this is that the misc-user event was a bad ! design choice when I made it, and it has only gotten worse with ! Oliver's attempts to add features to it to make it be used for ! drag-n-drop. I know that there was originally a separate drag-n-drop ! event type, and it was folded into the misc-user event type on my ! recommendation, but I have now realized the error of my ways. I had ! originally created a single event type in an attempt to prevent some ! Lisp programs from breaking because they might have a case statement ! over various event types, and would not be able to handle new event ! types appearing. I think now that these programs simply need to be ! written in a way to handle new event types appearing. It's not very ! hard to do this. You just use predicates instead of doing a case ! statement over the event type. If we preserve the existing predicate ! called `misc-user-event-p', and just make sure that it evaluates to ! true when given any user event type other than the standard simple ! ones, then most existing code will not break either when we split the ! event types up like this, or if we add any new event types in the ! future. ! ! More specifically, the only clean way to design the misc-user event ! type would be to add a sub-type field to it, and then have the nature ! of all the other fields in the event type be dependent on this ! sub-type. But then in essence, we'd just be reimplementing the whole ! event-type scheme inside of misc-user events, which would be rather ! pointless. !  ! File: internals.info, Node: Future Work -- Mouse Pointer, Next: Future Work -- Extents, Prev: Future Work -- Removal of Misc-User Event Type, Up: Future Work ! 40.11 Future Work - Mouse Pointer ! ================================= ! * Menu: ! * Future Work -- Abstracted Mouse Pointer Interface:: ! * Future Work -- Busy Pointer:: !  ! File: internals.info, Node: Future Work -- Abstracted Mouse Pointer Interface, Next: Future Work -- Busy Pointer, Prev: Future Work -- Mouse Pointer, Up: Future Work -- Mouse Pointer ! 40.11.1 Future Work - Abstracted Mouse Pointer Interface ! -------------------------------------------------------- ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! *Abstract:* We need to create a new image format that allows ! standard pointer shapes to be specified in a way that works on all ! Windows systems. I suggest that this be called `pointer', which has ! one tag associated with it, named `:data', and whose value is a string. ! The possible strings that can be specified here are predefined by ! XEmacs, and are guaranteed to work across all Windows systems. This ! means that we may need to provide our own definition for pointer shapes ! that are not standard on some systems. In particular, there are a lot ! more standard pointer shapes under X than under Windows, and most of ! these pointer shapes are fairly useful. There are also a few pointer ! shapes (I think the hand, for example) on Windows, but not on X. ! Converting the X pointer shapes to Windows should be easy because the ! definitions of the pointer shapes are simply XBM files, which we can ! read under Windows. Going the other way might be a little bit more ! difficult, but it should still not be that hard. ! ! While we're at it, we should change the image format currently called ! `cursor-font' to `x-cursor-font', because it only works under X ! Windows. We also need to change the format called `resource' to be ! `mswindows-resource'. At least in the case of `cursor-font', the old ! value should be maintained for compatibility as an obsolete alias. The ! `resource' format was added so recently that it's possible that we can ! just change it. ! !  ! File: internals.info, Node: Future Work -- Busy Pointer, Prev: Future Work -- Abstracted Mouse Pointer Interface, Up: Future Work -- Mouse Pointer ! ! 40.11.2 Future Work - Busy Pointer ! ---------------------------------- ! ! Author: Ben Wing (mailto:ben@xemacs.org) ! ! Automatically make the mouse pointer switch to a busy shape (watch ! signal) when XEmacs has been "busy" for more than, e.g. 2 seconds. ! Define the "busy time" as the time since the last time that XEmacs was ! ready to receive input from the user. An implementation might be: ! ! 1. Set up an asynchronous timeout, to signal after the busy time; ! these are triggered through a call to QUIT so they will be ! triggered even when the code is busy doing something. ! ! 2. We already have an "emacs_is_blocking" flag when we are waiting for ! input. In the same place, when we are about to block and wait for ! input (regardless of whether input is already present), maybe call ! a hook, which in this case would remove the timer and put back the ! normal mouse shape. Then when we exit the blocking stage (we got ! some input), call another hook, which in this case will start the ! timer. Note that we don't want these "blocking" hooks to be ! triggered just because of an accept-process-output or some similar ! thing that retrieves events, only to put them back onto a queue ! for later processing. Maybe we want some sort of flag that's ! bound by those routines saying that we aren't really waiting for ! input. Making that flag Lisp-accessible allows it to be set by ! similar sorts of Lisp routines (if there are any?) that loop ! retrieving events but defer them, or only drain the queue, or ! whatnot. #### Think about whether it would make some sense to try ! and be more clever in our determinations of what counts as "real ! waiting for user input", e.g. whether the event gets dispatched ! (unfortunately this occurs way too late, we want to know to remove ! the busy cursor *before* getting an event), maybe whether there ! are any events waiting to be processed or we'll truly block, etc. ! (e.g. one possibility if there is input on the queue already when ! we "block" for input, don't remove the busy- wait pointer, but ! trigger the removal of it when we dispatch a user event). !  ! File: internals.info, Node: Future Work -- Extents, Next: Future Work -- Version Number and Development Tree Organization, Prev: Future Work -- Mouse Pointer, Up: Future Work ! 40.12 Future Work - Extents ! =========================== ! * Menu: ! * Future Work -- Everything should obey duplicable extents:: !  ! File: internals.info, Node: Future Work -- Everything should obey duplicable extents, Prev: Future Work -- Extents, Up: Future Work -- Extents ! 40.12.1 Future Work - Everything should obey duplicable extents ! --------------------------------------------------------------- ! Author: Ben Wing (mailto:ben@xemacs.org) ! A lot of functions don't properly track duplicable extents. For ! example, the `concat' function does, but the `format' function does ! not, and extents in keymap prompts are not displayed either. All of ! the functions that generate strings or string-like entities should ! track the extents that are associated with the strings. Currently this ! is difficult because there is no general mechanism implemented for doing ! this. I propose such a general mechanism, which would not be hard to ! implement, and would be easy to use in other functions that build up ! strings. ! ! The basic idea is that we create a C structure that is analogous to a ! Lisp string in that it contains string data and lists of extents for ! that data. Unlike standard Lisp strings, however, this structure (let's ! call it `lisp_string_struct') can be incrementally updated and its ! allocation is handled explicitly so that no garbage is generated. (This ! is important for example, in the event-handling code which would want to ! use this structure, but needs to not generate any garbage for efficiency ! reasons). Both the string data and the list of extents in this string ! are handled using dynarrs so that it is easy to incrementally update ! this structure. Functions should exist to create and destroy instances ! of `lisp_string_struct' to generate a Lisp string from a ! `lisp_string_struct' and vice-versa to append a sub-string of a Lisp ! string to a `lisp_string_struct', to just append characters to a ! `lisp_string_struct', etc. The only thing possibly tricky about ! implementing these functions is implementing the copying of extents from ! a Lisp string into a `lisp_string_struct'. However, there is already a ! function `copy_string_extents()' that does basically this exact thing, ! and it should be easy to create a modified version of this function. --- 46,6367 ---- Foundation instead of in the original English.  ! File: internals.info, Node: List of changed files in new Mule workspace, Next: Changes to the MULE subsystems, Up: The Great Mule Merge of March 2002 ! 25.14.1 List of changed files in new Mule workspace ! --------------------------------------------------- ! This node lists the files that were touched in the Great Mule Merge. ! Deleted files ! ============= ! src/iso-wide.h ! src/mule-charset.h ! src/mule.c ! src/ntheap.h ! src/syscommctrl.h ! lisp/files-nomule.el ! lisp/help-nomule.el ! lisp/mule/mule-help.el ! lisp/mule/mule-init.el ! lisp/mule/mule-misc.el ! nt/config.h ! ! Other deleted files ! =================== ! ! These files were all zero-width and accidentally present. ! ! src/events-mod.h ! tests/Dnd/README.OffiX ! tests/Dnd/dragtest.el ! netinstall/README.xemacs ! lib-src/srcdir-symlink.stamp ! ! New files ! ========= ! ! CHANGES-ben-mule ! README.ben-mule-21-5 ! README.ben-separate-stderr ! TODO.ben-mule-21-5 ! etc/TUTORIAL.{cs,es,nl,sk,sl} ! etc/unicode/* ! lib-src/make-mswin-unicode.pl ! lisp/code-init.el ! lisp/resize-minibuffer.el ! lisp/unicode.el ! lisp/mule/china-util.el ! lisp/mule/cyril-util.el ! lisp/mule/devan-util.el ! lisp/mule/devanagari.el ! lisp/mule/ethio-util.el ! lisp/mule/indian.el ! lisp/mule/japan-util.el ! lisp/mule/korea-util.el ! lisp/mule/lao-util.el ! lisp/mule/lao.el ! lisp/mule/mule-locale.txt ! lisp/mule/mule-msw-init.el ! lisp/mule/thai-util.el ! lisp/mule/thai.el ! lisp/mule/tibet-util.el ! lisp/mule/tibetan.el ! lisp/mule/viet-util.el ! src/charset.h ! src/intl-auto-encap-win32.c ! src/intl-auto-encap-win32.h ! src/intl-encap-win32.c ! src/intl-win32.c ! src/intl-x.c ! src/mule-coding.c ! src/text.c ! src/text.h ! src/unicode.c ! src/s/win32-common.h ! src/s/win32-native.h ! Changed files ! ============= ! ! "Too numerous to mention." (Ben didn't write that, I did, but it's a ! good guess that's the intent....)  ! File: internals.info, Node: Changes to the MULE subsystems, Next: Pervasive changes throughout XEmacs sources, Prev: List of changed files in new Mule workspace, Up: The Great Mule Merge of March 2002 ! 25.14.2 Changes to the MULE subsystems ! -------------------------------------- ! configure changes ! ================= ! * file-coding always compiled in. eol detection is off by default on ! unix, non-mule, but can be enabled with configure option ! `--with-default-eol-detection' or command-line flag `-eol'. ! * code that selects which files are compiled is mostly moved to ! `Makefile.in.in'. see comment in `Makefile.in.in'. ! * vestigial i18n3 code deleted. ! * new cygwin mswin libs imm32 (input methods), mpr (user name ! enumeration). ! * check for `link', `symlink'. ! * `vfork'-related code deleted. ! * fix `configure.usage'. (delete `--with-file-coding', ! `--no-doc-file', add `--with-default-eol-detection', ! `--quick-build'). ! * `nt/config.h' has been eliminated and everything in it merged into ! `config.h.in' and `s/windowsnt.h'. see `config.h.in' for more ! info. ! * massive rewrite of `s/windowsnt.h', `m/windowsnt.h', ! `s/cygwin32.h', `s/mingw32.h'. common code moved into ! `s/win32-common.h', `s/win32-native.h'. ! * in `nt/xemacs.mak', `nt/config.inc.samp', variable is called ! `MULE', not `HAVE_MULE', for consistency with sources. ! * define `TABDLY', `TAB3' in `freebsd.h' (#### from where?) !  ! File: internals.info, Node: Pervasive changes throughout XEmacs sources, Next: Changes to specific subsystems, Prev: Changes to the MULE subsystems, Up: The Great Mule Merge of March 2002 ! 25.14.3 Pervasive changes throughout XEmacs sources ! --------------------------------------------------- ! * all `#ifdef FILE_CODING' statements removed from code. ! Changes to string processing ! ============================ ! * new `qxe()' string functions that accept `Intbyte *' as arguments. ! These work exactly like the standard `strcmp()', `strcpy()', ! `sprintf()', etc. except for the argument declaration differences. ! We use these whenever we have `Intbyte *' strings, which is quite ! often. ! * new fun `build_intstring()' takes an `Intbyte *'. also new funs ! `build_msg_intstring' (like `build_intstring()') and ! `build_msg_string' (like `build_string()') to do a `GETTEXT()' ! before building the string. (elimination of old ! `build_translated_string()', replaced by `build_msg_string()'). ! * function `intern_int()' for `Intbyte *' arguments, like `intern()'. ! * numerous places throughout code where `char *' replaced with ! something else, e.g. `Char_ASCII *', `Intbyte *', `Char_Binary *', ! etc. same with unsigned `char *', going to `UChar_Binary *', etc. !  ! File: internals.info, Node: Changes to specific subsystems, Next: Mule changes by theme, Prev: Pervasive changes throughout XEmacs sources, Up: The Great Mule Merge of March 2002 ! 25.14.4 Changes to specific subsystems ! -------------------------------------- ! Changes to the init code ! ======================== ! * lots of init code rewritten to be mule-correct. ! Changes to processes ! ==================== ! * always call `egetenv()', never `getenv()', for mule correctness. ! command line (`startup.el', `emacs.c') ! ====================================== ! * new option `-eol' to enable auto EOL detection under non-mule unix. ! * new option `-nuni' (`--no-unicode-lib-calls') to force use of ! non-Unicode API's under Windows NT, mostly for debugging purposes. !  ! File: internals.info, Node: Mule changes by theme, Next: File-coding rewrite, Prev: Changes to specific subsystems, Up: The Great Mule Merge of March 2002 ! 25.14.5 Mule changes by theme ! ----------------------------- ! ! * the code that handles the details of processing multilingual text ! has been consolidated to make it easier to extend it. it has been ! yanked out of various files (`buffer.h', `mule-charset.h', ! `lisp.h', `insdel.c', `fns.c', `file-coding.c', etc.) and put into ! `text.c' and `text.h'. `mule-charset.h' has also been renamed ! `charset.h'. all long comments concerning the representations and ! their processing have been consolidated into `text.c'. ! ! * major rewriting of file-coding. it's mostly abstracted into coding ! systems that are defined by methods (similar to devices and ! specifiers), with the ultimate aim being to allow non-i18n coding ! systems such as gzip. there is a "chain" coding system that ! allows multiple coding systems to be chained together. (it ! doesn't yet have the concept that either end of a coding system ! can be bytes or chars; this needs to be added.) ! ! * large amounts of code throughout the code base have been ! Mule-ized, not just Windows code. ! ! * total rewriting of OS locale code. it notices your locale at ! startup and sets the language environment accordingly, and calls ! `setlocale()' and sets `LANG' when you change the language ! environment. new language environment properties `locale', ! `mswindows-locale', `cygwin-locale', `native-coding-system', to ! determine langenv from locale and vice-versa; fix all language ! environments (lots of language files). langenv startup code ! rewritten. many new functions to convert between locales, ! language environments, etc. ! ! * major overhaul of the way default values for the various coding ! system variables are handled. all default values are collected ! into one location, a new file `code-init.el', which provides a ! unified mechanism for setting and querying what i call "basic ! coding system variables" (which may be aliases, parts of conses, ! etc.) and a mechanism of different configurations (Windows w/Mule, ! Windows w/o Mule, Unix w/Mule, Unix w/o Mule, unix w/o Mule but ! w/auto EOL), each of which specifies a set of default values. we ! determine the configuration at startup and set all the values in ! one place. (`code-init.el', `code-files.el', `coding.el', ...) ! ! * i copied the remaining language-specific files from fsf. i made ! some minor changes in certain cases but for the most part the ! stuff was just copied and may not work. ! * ms windows mule support, with full unicode support. required font, ! redisplay, event, other changes. ime support from ikeyama. ! Lisp-Visible Changes: ! ===================== ! * ensure that `escape-quoted' works correctly even without Mule ! support and use it for all auto-saves. (`auto-save.el', ! `fileio.c', `coding.el', `files.el') ! * new var `buffer-file-coding-system-when-loaded' specifies the ! actual coding system used when the file was loaded ! (`buffer-file-coding-system' is usually the same, but may be ! changed because it controls how the file is written out). use it ! in revert-buffer (`files.el', `code-files.el') and in new submenu ! File->Revert Buffer with Specified Encoding (`menubar-items.el'). ! * improve docs on how the coding system is determined when a file is ! read in; improved docs are in both `find-file' and ! `insert-file-contents' and a reference to where to find them is in ! `buffer-file-coding-system-for-read'. (`files.el', ! `code-files.el') ! * new (brain-damaged) FSF way of calling post-read-conversion (only ! one arg, not two) is supported, along with our two-argument way, ! as best we can. (`code-files.el') ! * add inexplicably missing var `default-process-coding-system'. use ! it. get rid of former hacked-up way of setting these defaults ! using `comint-exec-hook'. also fun ! `set-buffer-process-coding-system'. (`code-process.el', ! `code-cmds.el', `process.c') ! * remove function `set-default-coding-systems'; replace with ! `set-default-output-coding-systems', which affects only the output ! defaults (`buffer-file-coding-system', output half of ! `default-process-coding-system'). the input defaults should not be ! set by this because they should always remain `undecided' in normal ! circumstances. fix `prefer-coding-system' to use the new function ! and correct its docs. ! * fix bug in `coding-system-change-eol-conversion' (`code-cmds.el') ! * recognize all eol types in `prefer-coding-system' (`code-cmds.el') ! * rewrite `coding-system-category' to be correct (`coding.el') ! Internal Changes ! ================ ! * major improvements to eistring code, fleshing out of missing funs. ! * Separate encoding and decoding lstreams have been combined into a ! single coding lstream. Functions` make_encoding_*_stream' and ! `make_decoding_*_stream' have been combined into ! `make_coding_*_stream', which takes an argument specifying whether ! encode or decode is wanted. ! * remove last vestiges of I18N3, I18N4 code. ! * ascii optimization for strings: we keep track of the number of ! ascii chars at the beginning and use this to optimize byte<->char ! conversion on strings. ! * `mule-misc.el', `mule-init.el' deleted; code in there either ! deleted, rewritten, or moved to another file. ! * `mule.c' deleted. ! * move non-Mule-specific code out of `mule-cmds.el' into ! `code-cmds.el'. (`coding-system-change-text-conversion'; remove ! duplicate `coding-system-change-eol-conversion') ! * remove duplicate `set-buffer-process-coding-system' ! (`code-cmds.el') ! * add some commented-out code from FSF `mule-cmds.el' ! (`find-coding-systems-region-subset-p', ! `find-coding-systems-region', `find-coding-systems-string', ! `find-coding-systems-for-charsets', `find-multibyte-characters', ! `last-coding-system-specified', `select-safe-coding-system', ! `select-message-coding-system') (`code-cmds.el') ! * remove obsolete alias `pathname-coding-system', function ! `set-pathname-coding-system' (`coding.el') ! * remove coding-system property `doc-string'; split into ! `description' (short, for menu items) and `documentation' (long); ! correct coding system defns (`coding.el', `file-coding.c', lots of ! language files) ! * move coding-system-base into C and make use of internal info ! (`coding.el', `file-coding.c') ! * move `undecided' defn into C (`coding.el', `file-coding.c') ! * use `define-coding-system-alias', not `copy-coding-system' ! (`coding.el') ! * new coding system `iso-8859-6' for arabic ! * delete windows-1251 support from `cyrillic.el'; we do it ! automatically ! * remove `setup-*-environment' as per FSF 21 ! * rewrite `european.el' with lang envs for each language, so we can ! specify the locale ! * fix corruption in `greek.el' ! * sync `japanese.el' with FSF 20.6 ! * fix warnings in `mule-ccl.el' ! * move FSF compat Mule fns from `obsolete.el' to `mule-charset.el' ! * eliminate unused `truncate-string{-to-width}' ! * `make-coding-system' accepts (but ignores) the additional ! properties present in the fsf version, for compatibility. ! * i fixed the iso2022 handling so it will correctly read in files ! containing unknown charsets, creating a "temporary" charset which ! can later be overwritten by the real charset when it's defined. ! this allows iso2022 elisp files with literals in strange languages ! to compile correctly under mule. i also added a hack that will ! correctly read in and write out the emacs-specific "composition" ! escape sequences, i.e. `ESC 0' through `ESC 4'. this means that ! my workspace correctly compiles the new file `devanagari.el' that ! i added. ! * elimination of `string-to-char-list' (use `string-to-list') ! * elimination of junky `define-charset' ! Selection ! ========= ! * fix msw selection code for Mule. proper encoding for ! `RegisterClipboardFormat'. store selection as `CF_UNICODETEXT', ! which will get converted to the other formats. don't respond to ! destroy messages from `EmptyClipboard()'. ! Menubar ! ======= ! * new items `Open With Specified Encoding', `Revert Buffer with ! Specified Encoding' ! * split Mule menu into `Encoding' (non-Mule-specific; includes new ! item to control EOL auto-detection) and `International' submenus on ! `Options', `International' on `Help' ! Unicode support: ! ================ ! * translation tables added in `etc/unicode' ! * new files `unicode.c', `unicode.el' containing unicode coding ! systems and support; old code ripped out of `file-coding.c' ! * translation tables read in at startup (NEEDS WORK TO MAKE IT MORE ! EFFICIENT) ! * support `CF_TEXT', `CF_UNICODETEXT' in `select.el' ! * encapsulation code added so that we can support both Windows 9x ! and NT in a single executable, determining at runtime whether to ! call the Unicode or non-Unicode API. encapsulated routines in ! `intl-encap-win32.c' (non-auto-generated) and ! `intl-auto-encap-win32.[ch]' (auto-generated). code generator in ! `lib-src/make-mswin-unicode.pl'. changes throughout the code to ! use the wide structures (W suffix) and call the encapsulated Win32 ! API routines (`qxe' prefix). calling code needs to do proper ! conversion of text using new coding systems `Qmswindows_tstr', ! `Qmswindows_unicode', or `Qmswindows_multibyte'. (the first ! points to one of the other two.) !  ! File: internals.info, Node: File-coding rewrite, Next: General User-Visible Changes, Prev: Mule changes by theme, Up: The Great Mule Merge of March 2002 ! 25.14.6 File-coding rewrite ! --------------------------- ! The coding system code has been majorly rewritten. It's abstracted into ! coding systems that are defined by methods (similar to devices and ! specifiers). The types of conversions have also been generalized. ! Formerly, decoding always converted bytes to characters and encoding the ! reverse (these are now called "text file converters"), but conversion ! can now happen either to or from bytes or characters. This allows ! coding systems such as `gzip' and `base64' to be written. When ! specifying such a coding system to an operation that expects a text ! file converter (such as reading in or writing out a file), the ! appropriate coding systems to convert between bytes and characters are ! automatically inserted into the conversion chain as necessary. To ! facilitate creating such chains, a special coding system called "chain" ! has been created, which chains together two or more coding systems. ! Encoding detection has also been abstracted. Detectors are logically ! separate from coding systems, and each detector defines one or more ! categories. (For example, the detector for Unicode defines categories ! such as UTF-8, UTF-16, UCS-4, and UTF-7.) When a particular detector is ! given a piece of text to detect, it determines likeliness values (seven ! of them, from 3 [most likely] to -3 [least likely]; specific criteria ! are defined for each possible value). All detectors are run in parallel ! on a particular piece of text, and the results tabulated together to ! determine the actual encoding of the text. ! Encoding and decoding are now completely parallel operations, and the ! former "encoding" and "decoding" lstreams have been combined into a ! single "coding" lstream. Coding system methods that were formerly ! split in such a fashion have also been combined. !  ! File: internals.info, Node: General User-Visible Changes, Next: General Lisp-Visible Changes, Prev: File-coding rewrite, Up: The Great Mule Merge of March 2002 ! 25.14.7 General User-Visible Changes ! ------------------------------------ ! Search ! ====== + * make regex routines reentrant, since they're sometimes called + reentrantly. (see `regex.c' for a description of how.) all global + variables used by the regex routines get pushed onto a stack by the + callers before being set, and are restored when finished. redo the + preprocessor flags controlling `REL_ALLOC' in conjunction with + this. ! Menubar ! ======= ! * move menu-splitting code (`menu-split-long-menu', etc.) from ! `font-menu.el' to `menubar-items.el' and redo its algorithm; use ! in various items with long generated menus; rename to remove ! `font-' from beginning of functions but keep old names as aliases ! * new fn `menu-sort-menu' ! * redo items `Grep All Files in Current Directory {and Below}' using ! stuff from sample `init.el' ! * `Debug on Error' and friends now affect current session only; not ! saved ! * `maybe-add-init-button' -> `init-menubar-at-startup' and call ! explicitly from `startup.el' ! * don't use `charset-registry' in `msw-font-menu.el'; it's only for X ! Changes to key bindings ! ======================= ! These changes are primarily found in `keymap.c', `keydefs.el', and ! `help.el', but are found in many other files. ! * `M-home', `M-end' now move forward and backward in buffers; with ! , stay within current group (e.g. all C files; same grouping ! as the gutter tabs). (bindings ! `switch-to-{next/previous}-buffer[-in-group]' in `files.el') ! needed to move code from `gutter-items.el' to `buff-menu.el' ! that's used by these bindings, since `gutter-items.el' is loaded ! only when the gutter is active and these bindings (and hence the ! code) is not (any more) gutter specific. ! * new global vars global-tty-map and global-window-system-map ! specify key bindings for use only on TTY's or window systems, ! respectively. this is used to make `ESC ESC' be keyboard-quit on ! window systems, but `ESC ESC ESC' on TTY's, where ! keys may appear as `ESC ESC O A' or whatever. `C-z' on window ! systems is now `zap-up-to-char', and `iconify-frame' is moved to ! `C-Z'. `ESC ESC' is `isearch-quit'. (`isearch-mode.el') ! * document `global-{tty,window-system}-map' in various places; ! display them when you do `C-h b'. ! * fix up function documentation in general for keyboard primitives. ! e.g. key-bindings now contains a detailed section on the steps ! prior to looking up in keymaps, i.e. `function-key-map', ! `keyboard-translate-table'. etc. `define-key' and other obvious ! starting points indicate where to look for more info. ! * eliminate use and mention of grody `advertised-undo' and ! `deprecated-help'. (`simple.el', `startup.el', `picture.el', ! `menubar-items.el') !  ! File: internals.info, Node: General Lisp-Visible Changes, Next: User documentation, Prev: General User-Visible Changes, Up: The Great Mule Merge of March 2002 ! 25.14.8 General Lisp-Visible Changes ! ------------------------------------ ! gzip support ! ============ ! The gzip protocol is now partially supported as a coding system. ! * new coding system `gzip' (bytes -> bytes); unfortunately, not quite ! working yet because it handles only the raw zlib format and not the ! higher-level gzip format (the zlib library is brain-damaged in ! that it provides low-level, stream-oriented API's only for raw ! zlib, and for gzip you have only high-level API's, which aren't ! useful for xemacs). ! * configure support (`--with-zlib').  ! File: internals.info, Node: User documentation, Next: General internal changes, Prev: General Lisp-Visible Changes, Up: The Great Mule Merge of March 2002 ! 25.14.9 User documentation ! -------------------------- ! Tutorial ! ======== ! * massive rewrite; sync to FSF 21.0.106, switch focus to window ! systems, new sections on terminology and multiple frames, lots of ! fixes for current xemacs idioms. ! * german version from Adrian mostly matching my changes. ! * copy new tutorials from FSF (Spanish, Dutch, Slovak, Slovenian, ! Czech); not updated yet though. ! * eliminate `help-nomule.el' and `mule-help.el'; merge into one ! single tutorial function, fix lots of problems, put back in ! `help.el' where it belongs. (there was some random junk in ! `help-nomule.el', `string-width' and `make-char'. `string-width' ! is now in `subr.el' with a single definition, and `make-char' in ! `text.c'.) ! Sample init file ! ================ ! * remove forward/backward buffer code, since it's now standard. ! * when disabling `C-x C-c', make it display a message saying how to ! exit, not just beep and complain "undefined". !  ! File: internals.info, Node: General internal changes, Next: Ben's TODO list, Prev: User documentation, Up: The Great Mule Merge of March 2002 ! 25.14.10 General internal changes ! --------------------------------- ! Changes to gnuclient and gnuserv ! ================================ ! * clean up headers a bit. ! * use proper ms win idiom for checking for temp directory (`TEMP' or ! `TMP', not `TMPDIR'). ! Process changes ! =============== ! * Move `setenv' from packages; synch `setenv'/`getenv' with 21.0.105 ! Changes to I/O internals ! ======================== ! * use `PATH_MAX' consistently instead of `MAXPATHLEN', `MAX_PATH', ! etc. ! * all code that does preprocessor games with C lib I/O functions ! (open, read) has been removed. The code has been changed to call ! the correct function directly. Functions that accept `Intbyte *' ! arguments for filenames and such and do automatic conversion to or ! from external format will be prefixed `qxe...()'. Functions that ! are retrying in case of `EINTR' are prefixed `retry_...()'. ! `DONT_ENCAPSULATE' is long-gone. ! * never call `getcwd()' any more. use our shadowed value always. ! Changes to string processing ! ============================ ! * the `doprnt.c' external entry points have been completely rewritten ! to be more useful and have more sensible names. We now have, for ! example, versions that work exactly like `sprintf()' but return a ! `malloc()'ed string. ! * code in `print.c' that handles `stdout', `stderr' rewritten. ! * places that print to `stderr' directly replaced with ! `stderr_out()'. ! * new convenience functions `write_fmt_string()', ! `write_fmt_string_lisp()', `stderr_out_lisp()', `write_string()'. ! Changes to Allocation, Objects, and the Lisp Interpreter ! ======================================================== ! * automatically use "managed lcrecord" code when allocating. any ! lcrecord can be put on a free list with `free_lcrecord()'. ! * `record_unwind_protect()' returns the old spec depth. ! * `unbind_to()' now takes only one arg. use `unbind_to_1()' if you ! want the 2-arg version, with GC protection of second arg. ! * new funs to easily inhibit GC. (`{begin,end}_gc_forbidden()') use ! them in places where gc is currently being inhibited in a more ugly ! fashion. also, we disable GC in certain strategic places where ! string data is often passed in, e.g. `dfc' functions, `print' ! functions. ! * `make_buffer()' -> `wrap_buffer()' for consistency with other ! objects; same for `make_frame()' ->` wrap_frame()' and ! `make_console()' -> `wrap_console()'. ! * better documentation in condition-case. ! * new convenience funs `record_unwind_protect_freeing()' and ! `record_unwind_protect_freeing_dynarr()' for conveniently setting ! up an unwind-protect to `xfree()' or `Dynarr_free()' a pointer. ! s/m files: ! ========== ! * removal of unused `DATA_END', `TEXT_END', `SYSTEM_PURESIZE_EXTRA', ! `HAVE_ALLOCA' (automatically determined) ! * removal of `vfork' references (we no longer use `vfork') ! `make-docfile': ! =============== ! * clean up headers a bit. ! * allow `.obj' to mean equivalent `.c', just like for `.o'. ! * allow specification of a "response file" (a command-line argument ! beginning with @, specifying a file containing further command-line ! arguments) - a standard mswin idiom to avoid potential command-line ! limits and to simplify makefiles. use this in `xemacs.mak'. ! debug support ! ============= ! * (`cmdloop.el') new var breakpoint-on-error, which breaks into the C ! debugger when an unhandled error occurs noninteractively. useful ! when debugging errors coming out of complicated make scripts, e.g. ! package compilation, since you can set this through an env var. ! ! * (`startup.el') new env var `XEMACSDEBUG', specifying a Lisp form ! executed early in the startup process; meant to be used for turning ! on debug flags such as `breakpoint-on-error' or ! `stack-trace-on-error', to track down noninteractive errors. ! ! * (`cmdloop.el') removed non-working code in `command-error' to ! display a backtrace on `debug-on-error'. use ! `stack-trace-on-error' instead to get this. ! ! * (`process.c') new var `debug-process-io' displays data sent to and ! received from a process. ! ! * (`alloc.c') staticpros have name stored with them for easier ! debugging. ! ! * (`emacs.c') code that handles fatal errors consolidated and ! rewritten. much more robust and correctly handles all fatal exits ! on mswin (e.g. aborts, not previously handled right). ! `startup.el' ! ============ ! * move init routines from `before-init-hook' or `after-init-hook'; ! just call them directly (`init-menubar-at-startup', ! `init-mule-at-startup'). ! * help message fixed up (divided into sections), existing problem ! causing incomplete output fixed, undocumented options documented. ! `frame.el' ! ========== ! ! * delete old commented-out code.  ! File: internals.info, Node: Ben's TODO list, Next: Ben's README, Prev: General internal changes, Up: The Great Mule Merge of March 2002 ! 25.14.11 Ben's TODO list (probably obsolete) ! -------------------------------------------- ! These notes substantially overlap those in *Note Ben's README::. They ! should probably be combined. ! April 11, 2002 ! ============== ! Priority: ! 1. Finish checking in current mule ws. ! 2. Start working on bugs reported by others and noticed by me: ! * problems cutting and pasting binary data, e.g. from ! byte-compiler instructions ! * test suite failures ! * process i/o problems w.r.t. eol: |uniq (e.g.) leaves ^M's ! at end of line; running "bash" as shell-file-name doesn't ! work because it doesn't like the extra ^M's. ! March 20, 2002 ! ============== ! bugs: ! * TTY-mode problem. When you start up in TTY mode, XEmacs goes ! through the loadup process and appears to be working - you see the ! startup screen pulsing through the different screens, and it ! appears to be listening (hitting a key stops the screen motion), ! but it's frozen - the screen won't get off the startup, key ! commands don't cause anything to happen. STATUS: In progress. ! * Memory ballooning in some cases. Not yet understood. ! * other test suite failures? ! * need to review the handling of sounds. seems that not everything ! is documented, not everything is consistently used where it's ! supposed to, some sounds are ugly, etc. add sounds to `completer' ! as well. ! * redo with-trapping-errors so that the backtrace is stored away and ! only outputted when an error actually occurs (i.e. in the ! condition-case handler). test. (use ding of various sorts as a ! helpful way of checking out what's going on.) ! * problems with process input: |uniq (for example) leaves ^M's at ! end of line. ! * carefully review looking up of fonts by charset, esp. wrt the last ! element of a font spec. ! * add package support to ignore certain files - *-util.el for ! languages. ! * review use of escape-quoted in auto_save_1() vs. the buffer's own ! coding system. ! * figure out how to get the total amount of data memory (i.e. ! everything but the code, or even including the code if can't ! distinguish) used by the process on each different OS, and use it ! in a new algorithm for triggering GC: trigger only when a certain ! % of the data size has been consed up; in addition, have a minimum. ! * fixed bugs??? ! * Occasional crash when freeing display structures. The ! problem seems to be this: A window has a "display line ! dynarr"; each display line has a "display block dynarr". ! Sometimes this display block dynarr is getting freed twice. ! It appears from looking at the code that sometimes a ! display line from somewhere in the dynarr gets added to the ! end - hence two pointers to the same display block dynarr. ! need to review this code. ! August 29, 2001 ! =============== ! This is the most current list of priorities in `ben-mule-21-5'. ! Updated often. ! high-priority: ! *[input]* ! * support for WM_IME_CHAR. IME input can work under -nuni if ! we use WM_IME_CHAR. probably we should always be using this, ! instead of snarfing input using WM_COMPOSITION. i'll check ! this out. ! * Russian C-x problem. see above. ! *[clean-up]* ! * make sure it compiles and runs under non-mule. remember that ! some code needs the unicode support, or at least a simple ! version of it. ! * make sure it compiles and runs under pdump. see below. ! * make sure it compiles and runs under cygwin. see below. ! * clean up mswindows-multibyte, TSTR_TO_C_STRING. expand dfc ! optimizations to work across chain. ! * eliminate last vestiges of codepage<->charset conversion and ! similar stuff. ! *[other]* ! * test the "file-coding is binary only on Unix, no-Mule" stuff. ! * test that things work correctly in -nuni if the system ! environment is set to e.g. japanese - i should get japanese ! menus, japanese file names, etc. same for russian, hebrew ... ! * cut and paste. see below. ! * misc issues with handling lang environments. see also August ! 25, "finally: working on the `C-x' in ...". ! * when switching lang env, needs to set keyboard layout. ! * user var to control whether, when moving into text of a ! particular language, we set the appropriate keyboard ! layout. we would need to have a lisp api for ! retrieving and setting the keyboard layout, set text ! properties to indicate the layout of text, and have a ! way of dealing with text with no property on it. (e.g. ! saved text has no text properties on it.) basically, ! we need to get a keyboard layout from a charset; getting ! a language would do. Perhaps we need a table that ! maps charsets to language environments. ! * test that the lang env is properly set at startup. ! test that switching the lang env properly sets the C ! locale (call `setlocale()', set `LANG', etc.) - a ! spawned subprogram should have the new locale in its ! environment. ! * look through everything below and see if anything is missed ! in this priority list, and if so add it. create a separate ! file for the priority list, so it can be updated as ! appropriate. ! mid-priority: ! * clean up the chain coding system. its list should specify decode ! order, not encode; i now think this way is more logical. it should ! check the endpoints to make sure they make sense. it should also ! allow for the specification of "reverse-direction coding systems": ! use the specified coding system, but invert the sense of decode and ! encode. ! * along with that, places that take an arbitrary coding system and ! expect the ends to be anything specific need to check this, and add ! the appropriate conversions from byte->char or char->byte. ! * get some support for arabic, thai, vietnamese, japanese jisx 0212: ! at least get the unicode information in place and make sure we have ! things tied together so that we can display them. worry about r2l ! some other time. ! * check the handling of `C-c'. can XEmacs itself be interrupted with ! `C-c'? is that impossible now that we are a window, not a console, ! app? at least we should work something out with `i' so that if it ! receives a `C-c' or `C-break', it interrupts XEmacs, too. check ! out how process groups work and if they apply only to console apps. ! also redo the way that XEmacs sends `C-c' to other apps. the ! business of injecting code should be last resort. we should try ! `C-c' first, and if that doesn't work, then the next time we try to ! interrupt the same process, use the injection method. !  ! File: internals.info, Node: Ben's README, Prev: Ben's TODO list, Up: The Great Mule Merge of March 2002 ! 25.14.12 Ben's README (probably obsolete) ! ----------------------------------------- ! These notes substantially overlap those in *Note Ben's TODO list::. ! They should probably be combined. ! This may be of some historical interest as a record of Ben at work. ! There may also be some useful suggestions as yet unimplemented. ! oct 27, 2001 ! ============ ! ------- proposal for better buffer-switching commands: ! implement what VC++ currently has. you have a single "switch" ! command like `CTRL-TAB', which as long as you hold the button ! down, brings successive buffers that are "next in line" into the current ! position, bumping the rest forward. once you release the key, ! the chain is broken, and further `CTRL-TAB's will start from the ! beginning again. this way, frequently used buffers naturally move ! toward the front of the chain, and you can switch back and forth between ! two buffers using `CTRL-TAB'. the only thing about `CTRL-TAB' is it's ! a bit awkward. the way to implement is to have modifier-up strokes ! fire off a hook, like modifier-up-hook. this is driven by event ! dispatch, so there are no synchronization issues. when `C-tab' is ! pressed, the binding function does something like set a one-shot handler ! on the modifier-up-hook (perhaps separate hooks for separate ! modifiers?). ! ! to do this, we'd also want to change the buffer tabs so that they ! maintain their own order. in particular, they start out synched to the ! regular order, but as you make changes, you don't want the tabs to ! change order. (in fact, they may already do this.) selecting a ! particular buffer from the buffer tabs DOES make the buffer go to the ! head of the line. the invariant is that if the tabs are displaying X ! items, those X items are the first X items in the standard buffer list, ! but may be in a different order. (it looks like the tabs may already ! implement all of this.) ! oct 26, 2001 ! ============ ! necessary testing/changes: ! * test all eol detection stuff under windows w/ and w/o mule, unix ! w/ and w/o mule. (test configure flag, command-line flag, menu ! option) may need a way of pretending to be unix under cygwin. ! * test under windows w/ and w/o mule, cygwin w/ and w/o mule, cygwin ! x windows w/ and w/o mule. ! * test undecided-dos/unix/mac. ! * check `ESC ESC' works as `isearch-quit' under TTY's. ! * test `coding-system-base' and all its uses (grep for them). ! * menu item to revert to most recent auto save. ! * consider renaming `build_string' -> `build_intstring' and ! `build_c_string' to `build_string'. (consistent with ! `build_msg_string' et al; many more `build_c_string' than ! `build_string') ! oct 20, 2001 ! ============ ! fixed problem causing crash due to invalid internal-format data, fixed ! an existing bug in `valid_char_p', and added checks to more quickly ! catch when invalid chars are generated. still need to investigate why ! `mswindows-multibyte' is being detected. ! ! i now see why - we only process 65536 bytes due to a constant ! `MAX_BYTES_PROCESSED_FOR_DETECTION'. instead, we should have no limit ! as long as we have a seekable stream. we also need to write ! `stderr_out_lisp()', used in the debug info routines i wrote. ! ! check once more about `DEBUG_XEMACS'. i think debugging info should ! be ON by default. make sure it is. check that nothing untoward will ! result in a production system, e.g. presumably `assert()'s should not ! really `abort()'. (!! Actually, this should be runtime settable! Use ! a variable for this, and it can be set using the same `XEMACSDEBUG' ! method. In fact, now that I think of it, I'm sure that debugging info ! should be on always, with runtime ways of turning on or off any funny ! behavior.) ! oct 19, 2001 ! ============ ! fixed various bugs preventing packages from being able to be built. ! still another bug, with `psgml/etc/cdtd/docbook', which contains some ! strange characters starting around char pos 110,000. It gets detected ! as `mswindows-multibyte' (wrong! why?) and then invalid internal-format ! data is generated. need to fix `mswindows-multibyte' (and possibly add ! something that signals an error as well; need to work on this ! error-signalling mechanism) and figure out why it's getting detected as ! such. what i should do is add a debug var that outputs blow-by-blow ! info of the detection process. ! ! oct 9, 2001 ! =========== ! ! the stuff with `global-window-system-map' doesn't appear to work. in ! any case it needs better documentation. [DONE] ! ! `M-home', `M-end' do work, but cause cl-macs to get loaded. why? ! ! oct 8, 2001 ! =========== ! ! finished the coding system changes and they finally work! ! ! need to implement undecided-unix/dos/mac. they should be easy to ! do; it should be enough to specify an eol-type but not do-eol, but ! check this. ! ! consider making the standard naming be foo-lf/crlf/cr, with ! unix/dos/mac as aliases. ! ! print methods for coding systems should include some of the generic ! properties. (also then fix print_..._within_print_method). [DONE] ! ! in a little while, go back and delete the ! `text-file-wrapper-coding-system' code. (it'll be in CVS if necessary ! to get at it.) [DONE] ! ! need to verify at some point that non-text-file coding systems work ! properly when specified. when gzip is working, this would be a good ! test case. (and consider creating base64 as well!) ! ! remove extra crap from `coding-system-category' that checks for ! chain coding systems. [DONE] ! ! perhaps make a primitive that gets at `coding-system-canonical'. ! [DONE] ! ! need to test cygwin, compiling the mule packages, get unix-eol stuff ! working. frank from germany says he doesn't see a lisp backtrace when ! he gets an error during temacs? verify that this actually gets ! outputted. ! ! consider putting the current language on the modeline, mousable so ! it can be switched. also consider making the coding system be mousable ! and the line number (pick a line) and the percentage (pick a ! percentage). ! ! oct 6, 2001 ! =========== ! ! added code so that `debug_print()' will output a newline to the ! mswindows debugging output, not just the console. need to test. [DONE] ! ! working on problem where all files are being detected as binary. the ! problem may be that the undecided coding system is getting wrapped with ! an auto-eol coding system, which it shouldn't be - but even in this ! situation, we should get the right results! check the ! canonicalize-after-coding methods. also, ! `determine_real_coding_system' appears to be getting called even when ! we're not detecting encoding. also, undecided needs a print method to ! show its params, and chain needs to be updated to show ! `canonicalize_after_coding'. check others as well. [DONE] ! ! oct 5, 2001 ! =========== ! ! finished up coding system changes, testing. ! ! errors byte-compiling files in `iso-2022-7-bit'. perhaps it's not ! correctly detecting the encoding? ! ! noticed a problem in the dfc macros: we call ! `get_coding_system_for_text_file' with `eol_wrap == 1', to allow for ! auto-detection of the eol type; but this defeats the check and ! short-circuit for unicode. ! ! still need to implement calling `determine_real_coding_system()' for ! non-seekable streams. to implement correctly, we need to do our own ! buffering. [DONE, BUT WITHOUT BUFFERING] ! ! oct 4, 2001 ! =========== ! ! implemented most stuff below. ! ! need to finish up changes to `make_coding_system_1'. (i changed the ! way internal coding systems were handled; i need to create subsidiaries ! for all types of coding systems, not just text ones.) there's a nasty ! `xfree()' crash i was hitting; perhaps it'll go away once all stuff has ! been rewritten. ! ! check under cygwin to make sure that when an error occurs during ! loadup, a backtrace is output. ! ! as soon as andy releases his new setup, we should put it onto various ! standard windows software repositories. ! ! oct 3, 2001 ! =========== ! ! added `global-tty-map' and `global-window-system-map'. add some stuff ! to the maps, e.g. `C-x ESC' for repeat vs. `C-x ESC ESC' on TTY's, and ! of course `ESC ESC' on window systems vs. `ESC ESC ESC' on TTY's. [TEST] ! ! was working on integrating the two `help-for-tutorial' versions ! (mule, non-mule). [DONE, but test under non-Mule] ! ! was working on the file-coding changes. need to think more about ! `text-file-wrapper'. conclusion i think is that ! `get_coding_system_for_text_file' should wrap using a special coding ! system type called a `text-file-wrapper', which inherits from chain, ! and implements `canonicalize-after-decoding' to just return the ! unwrapped coding system. We need to implement inheritance of coding ! systems, which will certainly come in extremely useful when coding ! systems get implemented in Lisp, which should happen at some point. ! (see existing docs about this.) essentially, we have a way of ! declaring that we inherit from some system, and the appropriate data ! structures get created, perhaps just an extra inheritance pointer. but ! when we create the coding system, the extra data needs to be a stretchy ! array of offsets, pointing to the type-specific data for the coding ! system type and all its parents. that means that in the methods ! structure for a coding system (which perhaps should be expanded beyond ! method, it's just a "class structure") is the index in these arrays of ! offsets. `CODING_SYSTEM_DATA()' can take any of the coding system ! classes (rename type to class!) that make up this class. similarly, a ! coding system class inherits its methods from the class above unless ! specifying its own method, and can call the superclass method at any ! point by either just invoking its name, or conceivably by some macro ! like ! ! `CALL_SUPER (method, (args))' ! ! similar mods would have to be made to coding stream structures. ! ! perhaps for the immediate we can just sort of fake things like we ! currently do with undecided calling some stuff from chain. ! ! oct 2, 2001 ! =========== ! ! need to implement support for iso-8859-15, i.e. iso-8859-1 + euro ! symbol. figure out how to fall back to iso-8859-1 as necessary. ! ! leave the current bindings the way they are for the moment, but bump ! off `M-home' and `M-end' (hardly used), and substitute my buffer ! movement stuff there. [DONE, but test] ! ! there's something to be said for combining block of 6 and paragraph, ! esp. if we make the definition of "paragraph" be so that it skips by 6 ! when within code. hmm. ! ! eliminate `advertised-undo' crap, and similar hacks. [DONE] ! ! think about obsolete stuff to be eliminated. think about ! eliminating or dimming obsolete items from `hyper-apropos' and ! something similar in completion buffers. ! sep 30, 2001 ! ============ ! synched up the tutorials with FSF 21.0.105. was rewriting them to favor ! the cursor keys over the older `C-p', etc. keys. ! Got thinking about key bindings again. ! 1. I think that `M-up/down' and `M-C-up/down' should be reversed. I ! use scroll-up/down much more often than motion by paragraph. ! 2. Should we eliminate move by block (of 6) and subsitute it for ! paragraph? This would have the advantage that I could make ! bindings for buffer change (forward/back buffer, perhaps ! `M-C-up/down'. with shift, `M-C-S-up/down' only goes within the ! same type (C files, etc.). alternatively, just bump off ! `beginning-of-defun' from `C-M-home', since it's on `C-M-a' ! already. ! need someone to go over the other tutorials (five new ones, from FSF ! 21.0.105) and fix them up to correspond to the english one. ! shouldn't shift-motion work with `C-a' and such as well as arrows? ! sep 29, 2001 ! ============ ! `charcount_to_bytecount' can also be made to scream - as can ! `scan_buffer', `buffer_mule_signal_inserted_region', others? we should ! start profiling though before going too far down this line. ! ! Debug code that causes no slowdown should in general remain in the ! executable even in the release version because it may be useful (e.g. ! for people to see the event output). so `DEBUG_XEMACS' should be ! rethought. things like use of `msvcrtd.dll' should be controlled by ! error_checking on. maybe `DEBUG_XEMACS' controls general debug code ! (e.g. use of `msvcrtd.dll', asserts abort, error checking), and the ! actual debugging code should remain always, or be conditonalized on ! something else (e.g. `DEBUGGING_FUNS_PRESENT'). ! ! doc strings in dumped files are displayed with an extra blank line ! between each line. presumably this is recent? i assume either the ! change to detect-coding-region or the double-wrapping mentioned below. ! ! error with `coding-system-property' on `iso-2022-jp-dos'. problem ! is that that coding system is wrapped, so its type shows up as `chain', ! not `iso-2022'. this is a general problem, and i think the way to fix ! it is to in essence do late canonicalization - similar in spirit to ! what was done long ago, `canonicalize_when_code', except that the new ! coding system (the wrapper) is created only once, either when the ! original cs is created or when first needed. this way, operations on ! the coding system work like expected, and you get the same results as ! currently when decoding/encoding. the only thing tricky is handling ! `canonicalize-after-coding' and the ever-tricky double-wrapping problem ! mentioned below. i think the proper solution is to move the ! autodetection of eol into the main autodetect type. it can be asked to ! autodetect eol, coding, or both. for just coding, it does like it ! currently does. for just eol, it does similar to what it currently does ! but runs the detection code that `convert-eol' currently does, and ! selects the appropriate `convert-eol' system. when it does both eol ! and coding, it does something on the order of creating two more ! autodetect coding systems, one for eol only and one for coding only, and ! chains them together. when each has detected the appropriate value, the ! results are combined. this automatically eliminates the double-wrapping ! problem, removes the need for complicated `canonicalize-after-coding' ! stuff in chain, and fixes the problem of autodetect not having a ! seekable stream because hidden inside of a chain. (we presume that in ! the both-eol-and-coding case, the various autodetect coding streams can ! communicate with each other appropriately.) ! ! also, we should solve the problem of internal coding systems floating ! around and clogging up the list simply by having an "internal" property ! on cs's and an internal param to `coding-system-list' (optional; if not ! given, you don't get the internal ones). [DONE] ! ! we should try to reduce the size of the from-unicode tables (the ! dominant memory hog in the tables). one obvious thing is to not store ! a whole emchar as the mapped-to value, but a short that encodes the ! octets. [DONE] ! sep 28, 2001 ! ============ ! need to merge up to latest in trunk. ! add unicode charsets for all non-translatable unicode chars; probably ! want to extend the concept of charsets to allow for dimension 3 and ! dimension 4 charsets. for the moment we should stick with just ! dimension 3 charsets; otherwise we run past the current maximum of 4 ! bytes per emchar. (most code would work automatically since it uses` ! MAX_EMCHAR_LEN'; the trickiness is in certain code that has intimate ! knowledge of the representation. e.g. `bufpos_to_bytind()' has to ! multiply or divide by 1, 2, 3, or 4, and has special ways of handling ! each number. with 5 or 6 bytes per char, we'd have to change that code ! in various ways.) 96x96x96 = 884,000 or so, so with two 96x96x96 ! charsets, we could tackle all Unicode values representable by UTF-16 ! and then some - and only these codepoints will ever have assigned ! chars, as far as we know. ! ! need an easy way of showing the current language environment. some ! menus need to have the current one checked or whatever. [DONE] ! ! implement unicode surrogates. ! ! implement `buffer-file-coding-system-when-loaded' - make sure ! `find-file', `revert-file', etc. set the coding system [DONE] ! ! verify all the menu stuff [DONE] ! ! implemented the entirely-ascii check in buffers. not sure how much ! gain it'll get us as we already have a known range inside of which is ! constant time, and with pure-ascii files the known range spans the whole ! buffer. improved the comment about how `bufpos-to-bytind' and ! vice-versa work. [DONE] ! ! fix double-wrapping of `convert-eol': when undecided converts itself ! to something with a non-autodetect eol, it needs to tell the adjacent ! `convert-eol' to reduce itself to nothing. ! ! need menu item for find file with specified encoding. [DONE] ! ! renamed coding systems mswindows-### to windows-### to follow the ! standard in rfc1345. [DONE] ! ! implemented `coding-system-subsidiary-parent' [DONE] `HAVE_MULE' -> ! `MULE' in files in `nt/' so that depend checking works [DONE] ! ! need to take the smarter `search-all-files-in-dir' stuff from my ! sample init file and put it on the grep menu [DONE] ! ! added item for revert w/specified encoding; mostly works, but needs ! fixes. in particular, you get the correct results, but ! `buffer-file-coding-system' does not reflect things right. also, there ! are too many entries. need to split into submenus. there is already ! split code out there; see if it's generalized and if not make it so. ! it should only split when there's more than a specified number, and ! when splitting, split into groups of a specified size, not into a ! specified number of groups. [DONE] ! too many entries in the langenv menus; need to split. [DONE] ! sep 27, 2001 ! ============ ! NOTE: `M-x grep' for make-string causes crash now. something ! definitely to do with string changes. check very carefully the diffs ! and put in those sledgehammer checks. [DONE] ! fix font-lock bug i introduced. [DONE] ! added optimization to strings (keeps track of # of bytes of ascii at ! the beginning of a string). perhaps should also keep an all-ascii flag ! to deal with really large (> 2 MB) strings. rewrite code to count ! ascii-begin to use the 4-or-8-at-a-time stuff in ! `bytecount_to_charcount'. ! Error: `M-q' is causing Invalid Regexp error on the above paragraph. ! It's not in working. I assume it's a side effect of the string stuff. ! VERIFY! Write sledgehammer checks for strings. [DONE] ! revamped the locale/init stuff so that it tries much harder to get ! things right. should test a bit more. in particular, test out ! Describe Language on the various created environments and make sure ! everything looks right. ! should change the menus: move the submenus on `Edit->Mule' directly ! under `Edit'. add a menu entry on `File' to say "Reload with specified ! encoding ->". [DONE] ! Also `Find File' with specified encoding -> Also entry to change the ! EOL settings for Unix, and implement it. ! `decode-coding-region' isn't working because it needs to insert a ! binary (char->byte) converter. [DONE] ! chain should be rearranged to be in decoding order; similar for ! source/sink-type, other things? ! the detector should check for a magic cookie even without a seekable ! input. (currently its input is not seekable, because it's hidden ! within a chain. #### See what we can do about this.) ! provide a way to display various settings, e.g. the current category ! mappings and priority (see mule-diag; get this working so it's in the ! path); also a way to print out the likeliness results from a detection, ! perhaps a debug flag. ! problem with `env', which causes path issues due to `env' in ! packages. move env code to process, sync with fsf 21.0.105, check that ! the autoloads in `env' don't cause problems. [DONE] ! 8-bit iso2022 detection appears broken; or at least, mule-canna.c is ! not so detected. ! sep 25, 2001 ! ============ ! something else to do is review the font selection and fix it so that ! (e.g.) JISX-0212 can be displayed. ! also, text in widgets needs to be drawn by us so that the correct ! fonts will be displayed even in multi-lingual text. ! sep 24, 2001 ! ============ ! the detection system is now properly abstracted. the detectors have ! been rewritten to include multiple levels of abstraction. now we just ! need detectors for ascii, binary, and latin-x, as well as more ! sophisticated detectors in general and further review of the general ! algorithm for doing detection. (#### Is this written up anywhere?) ! after that, consider adding error-checking to decoding (VERY IMPORTANT) ! and verifying the binary correctness of things under unix no-mule. ! sep 23, 2001 ! ============ ! began to fix the detection system - adding multiple levels of likelihood ! and properly abstracting the detectors. the system is in place except ! for the abstraction of the detector-specific data out of the struct ! detection_state. we should get things working first before tackling ! that (which should not be too hard). i'm rewriting algorithms here ! rather than just converting code, so it's harder. mostly done with ! everything, but i need to review all detectors except iso2022 and make ! them properly follow the new way. also write a no-conversion detector. ! also need to look into the `recode' package and see how (if?) they ! handle detection, and maybe copy some of the algorithms. also look at ! recent FSF 21.0 and see if their algorithms have improved. ! sep 22, 2001 ! ============ ! * fixed gc bugs from yesterday. ! * fixed truename bug. ! * close/finalize stuff works. ! * eliminated notyet stuff in syswindows.h. ! * eliminated special code in tstr_to_c_string. ! * fixed pdump problems. (many of them, mostly latent bugs, ugh) ! * fixed cygwin `sscanf' problems in ! `parse-unicode-translation-table'. (NOT a `sscanf' bug, but subtly ! different behavior w.r.t. whitespace in the format string, ! combined with a debugger that sucks ROCKS!! and consistently ! outputs garbage for variable values.) ! main stuff to test is the handling of EOF recognition vs. binary ! (i.e. check what the default settings are under Unix). then we may have ! something that WORKS on all platforms!!! (Also need to test Windows ! non-Mule) ! sep 21, 2001 ! ============ ! finished redoing the close/finalize stuff in the lstream code. but i ! encountered again the nasty bug mentioned on sep 15 that disappeared on ! its own then. the problem seems to be that the finalize method of some ! of the lstreams is calling `Lstream_delete()', which calls ! `free_managed_lcrecord()', which is a no-no when we're inside of ! garbage-collection and the object passed to `free_managed_lcrecord()' ! is unmarked, and about to be released by the gc mechanism - the free ! lists will end up with `xfree()'d objects on them, which is very bad. ! we need to modify `free_managed_lcrecord()' to check if we're in gc and ! the object is unmarked, and ignore it rather than move it to the free ! list. [DONE] ! ! (#### What we really need to do is do what Java and C# do w.r.t. ! their finalize methods: For objects with finalizers, when they're about ! to be freed, leave them marked, run the finalizer, and set another bit ! on them indicating that the finalizer has run. Next GC cycle, the ! objects will again come up for freeing, and this time the sweeper ! notices that the finalize method has already been called, and frees ! them for good (provided that a finalize method didn't do something to ! make the object alive again).) ! sep 20, 2001 ! ============ ! redid the lstream code so there is only one coding stream. combined the ! various doubled coding stream methods into one; i'm a little bit unsure ! of this last part, though, as the results of combining the two together ! seem unclean. got it to compile, but it crashes in loadup. need to go ! through and rehash the close vs. finalize stuff, as the problem was ! stuff getting freed too quickly, before the canonicalize-after-decoding ! was run. should eliminate entirely `CODING_STATE_END' and use a ! different method (close coding stream). rewrite to use these two. make ! sure they're called in the right places. `Lstream_close' on a stream ! should *NOT* do finalizing. finalize only on delete. [DONE] ! ! in general i'd like to see the flags eliminated and converted to ! bit-fields. also, rewriting the methods to take advantage of rejecting ! should make it possible to eliminate much of the state in the various ! methods, esp. including the flags. need to test this is working, ! though - reduce the buffer size down very low and try files with only ! CRLF's in them, with one offset by a byte from the other, and see if we ! correctly handle rejection. ! still have the problem with incorrectly truenaming files. ! sep 19, 2001 ! ============ ! bug reported: crash while closing lstreams. ! the lstream/coding system close code needs revamping. we need to ! document that order of closing lstreams is very important, and make ! sure we're consistent. furthermore, chain and undecided lstreams need ! to close their underneath lstreams when they receive the EOF signal ! (there may be data in the underneath streams waiting to come out), not ! when they themselves are closed. [DONE] ! ! (if only we had proper inheritance. i think in any case we should ! simulate it for the chain coding stream - write things in such a way ! that undecided can use the chain coding stream and not have to duplicate ! anything itself.) ! ! in general we need to carefully think through the closing process to ! make sure everything always works correctly and in the right order. ! also check very carefully to make sure there are no dangling pointers ! to deleted objects floating around. ! ! move the docs for the lstream functions to the functions themselves, ! not the header files. document more carefully what exactly ! `Lstream_delete()' means and how it's used, what the connections are ! between `Lstream_close('), `Lstream_delete()', `Lstream_flush()', ! `lstream_finalize', etc. [DONE] ! ! additional error-checking: consider deadbeefing the memory in objects ! stored in lcrecord free lists; furthermore, consider whether lifo or ! fifo is correct; under error-checking, we should perhaps be doing fifo, ! and setting a minimum number of objects on the lists that's quite large ! so that it's highly likely that any erroneous accesses to freed objects ! will go into such deadbeefed memory and cause crashes. also, at the ! earliest available opportunity, go through all freed memory and check ! for any consistency failures (overwrites of the deadbeef), crashing if ! so. perhaps we could have some sort of id for each block, to easier ! trace where the offending block came from. (all of these ideas are ! present in the debug system malloc from VC++, plus more stuff.) there's ! similar code i wrote sitting somewhere (in `free-hook.c'? doesn't ! appear so. we need to delete the blocking stuff out of there!). also ! look into using the debug system malloc from VC++, which has lots of ! cool stuff in it. we even have the sources. that means compiling under ! pdump, which would be a good idea anyway. set it as the default. (but ! then, we need to remove the requirement that Xpm be a DLL, which is ! extremely annoying. look into this.) ! ! test the windows code page coding systems recently created. ! problems reading my mail files - 1personal appears to hang, others ! come up with lots of ^M's. investigate. ! test the enum functions i just wrote, and finish them. ! still pdump problems. ! sep 18, 2001 ! ============ ! critical-quit broken sometime after aug 25. ! * fixed critical quit. ! * fixed process problems. ! * print routines work. (no routine for ccl, though) ! * can read and write unicode files, and they can still be read by ! some other program ! * defaults should come up correctly - mswindows-multibyte is general. ! still need to test matej's stuff. seems ok with multibyte stuff but ! needs more testing. ! sep 17, 2001 ! ============ + !!!!! something broken with processes !!!!! cannot send mail anymore. + must investigate. ! sep 17, 2001 ! ============ ! on mon/wed nights, stop *BEFORE* 11pm. Otherwise i just start getting ! woozy and can't concentrate. ! just finished getting assorted fixups to the main branch committed, ! so it will compile under C++ (Andy committed some code that broke C++ ! builds). cup'd the code into the fixtypes workspace, updated the tags ! appropriately. i've created the appropriate log message, sitting in ! fixtypes.txt in /src/xemacs; perhaps it should go into a README. now i ! just have to build on everything (it's currently building), verify it's ! ok, run patcher-mail, commit, send. ! my mule ws is also very close. need to: ! * test the new print routines. ! * test it can read and write unicode files, and they can still be ! read by some other program. ! * try to see if unicode can be auto-detected properly. ! * test it can read and write multibyte files in a few different ! formats. currently can't recognize them, but if you set the cs ! right, it should work. ! * examine the test files sent by matej and see if we can handle them. ! sep 15, 2001 ! ============ ! more eol fixing. this stuff is utter crap. ! currently we wrap coding systems with `convert-eol-autodetect' when ! we create them in `make_coding_system_1'. i had a feeling that this ! would be a problem, and indeed it is - when autodetecting with ! `undecided', for example, we end up with multiple layers of eol ! conversion. to avoid this, we need to do the eol wrapping *ONLY* when ! we actually retrieve a coding system in places such as ! `insert-file-contents'. these places are `insert-file-contents', load, ! process input, `call-process-internal', ! `encode/decode/detect-coding-region', database input, ... ! ! (later) it's fixed, and things basically work. NOTE: for some ! reason, adding code to wrap coding systems with `convert-eol-lf' when ! `eol-type == lf' results in crashing during garbage collection in some ! pretty obscure place - an lstream is free when it shouldn't be. this ! is a bad sign. i guess something might be getting initialized too ! early? ! ! we still need to fix the canonicalization-after-decoding code to ! avoid problems with coding systems like `internal-7' showing up. ! basically, when `eol==lf' is detected, nil should be returned, and the ! callers should handle it appropriately, eliding when necessary. chain ! needs to recognize when it's got only one (or even 0) items in the ! chain, and elide out the chain. ! sep 11, 2001: the day that will live in infamy ! ============================================== ! rewrite of sep 9 entry about formats: ! when calling `make-coding-system', the name can be a cons of ! `(format1 . format2)', specifying that it decodes `format1->format2' ! and encodes the other way. if only one name is given, that is assumed ! to be `format1', and the other is either `external' or `internal' ! depending on the end type. normally the user when decoding gives the ! decoding order in formats, but can leave off the last one, `internal', ! which is assumed. a multichain might look like gzip|multibyte|unicode, ! using the coding systems named `gzip', `(unicode . multibyte)' and ! `unicode'. the way this actually works is by searching for ! gzip->multibyte; if not found, look for gzip->external or ! gzip->internal. (In general we automatically do conversion between ! internal and external as necessary: thus gzip|crlf does the expected, ! and maps to gzip->external, external->internal, crlf->internal, which ! when fully specified would be ! gzip|external:external|internal:crlf|internal - see below.) To ! forcibly fit together two converters that have explicitly specified and ! incompatible names (say you have unicode->multibyte and ! iso8859-1->ebcdic and you know that the multibyte and iso8859-1 in this ! case are compatible), you can force-cast using :, like this: ! ebcdic|iso8859-1:multibyte|unicode. (again, if you force-cast between ! internal and external formats, the conversion happens automatically.) ! sep 10, 2001 ! ============ ! moved the autodetection stuff (both codesys and eol) into particular ! coding systems - `undecided' and `convert-eol' (type == `autodetect'). ! needs lots of work. still need to search through the rest of the code ! and find any remaining auto-detect code and move it into the undecided ! coding system. need to modify make-coding-system so that it spits out ! auto-detecting versions of all text-file coding systems unless we say ! not to. need eliminate entirely the EOF flag from both the stream info ! and the coding system; have only the original-eof flag. in ! coding_system_from_mask, need to check that the returned value is not of ! type `undecided', falling back to no-conversion if so. also need to ! make sure we wrap everything appropriate for text-files - i removed the ! wrapping on set-coding-category-list or whatever (need to check all ! those files to make sure all wrapping is removed). need to review ! carefully the new code in `undecided' to make sure it works are ! preserves the same logic as previously. need to review the closing and ! rewinding behavior of chain and undecided (same - should really ! consolidate into helper routines, so that any coding system can embed a ! chain in it) - make sure the dynarr's are getting their data flushed ! out as necessary, rewound/closed in the right order, no missing steps, ! etc. ! also split out mule stuff into `mule-coding.c'. work done on ! `configure'/`xemacs.mak'/`Makefile's not done yet. work on ! `emacs.c'/`symsinit.h' to interface with the new init functions not ! done yet. ! ! also put in a few declarations of the way i think the abstracted ! detection stuff ought to go. DON'T WORK ON THIS MORE UNTIL THE REST IS ! DEALT WITH AND WE HAVE A WORKING XEMACS AGAIN WITH ALL EOL ISSUES ! NAILED. ! ! really need a version of `cvs-mods' that reports only the current ! directory. WRITE THIS! use it to implement a better `cvs-checkin'. ! ! sep 9, 2001 ! =========== ! ! implemented a gzip coding system. unfortunately, doesn't quite work ! right because it doesn't handle the gzip headers - it just reads and ! writes raw zlib data. there's no function in the library to skip past ! the header, but we do have some code out of the library that we can ! snarf that implements header parsing. we need to snarf that, store it, ! and output it again at the beginning when encoding. in the process, we ! should create a "get next byte" macro that bails out when there are no ! more. using this, we set up a nice way of doing most stuff statelessly ! - if we have to bail, we reject everything back to the sync point. ! also need to fix up the autodetection of zlib in configure.in. ! ! BIG problems with eol. finished up everything i thought i would ! need to get eol stuff working, but no - when you have ! mswindows-unicode, with its eol set to autodetect, the detection ! routines themselves do the autodetect (first), and fail (they report CR ! on CRLF because of the NULL byte between the CR and the LF) since ! they're not looking at ascii data. with a chain it's similarly bad. ! for mswindows-multibyte, for example, which is a chain ! unicode->unicode-to-multibyte, autodetection happens inside of the ! chain, both when unicode and unicode-to-multibyte are active. we could ! twiddle around with the eol flags to try to deal with this, but it's ! gonna be a big mess, which is exactly what we're trying to avoid. what ! we basically want is to entirely rip out all EOL settings from either ! the coding system or the stream (yes, there are two! one might saw ! autodetect, and then the stream contains the actual detected value). ! instead, we simply create an eol-autodetect coding system - or rather, ! it's part of the convert-eol coding system. convert-eol, type = ! autodetect, does autodetection the first time it gets data sent to it to ! decode, and thereafter sets a stream parameter indicating the actual eol ! type for this stream. this means that all autodetect coding systems, as ! created by `make-coding-system', really are chains with a convert-eol ! at the beginning. only subsidiary xxx-unix has no wrapping at all. ! this should allow eof detection of gzip, unicode, etc. for that ! matter, general autodetection should be entirely encapsulated inside of ! the `autodetect' coding system, with no eol-autodetection - the chain ! becomes convert-eol (autodetect) -> autodetect or perhaps backwards. ! the generic autodetect similarly has a coding-system in its stream ! methods, and needs somehow or other to insert the detected ! coding-system into the chain. either it contains a chain inside of it ! (perhaps it *IS* a chain), or there's some magic involving ! canonicalization-type switcherooing in the middle of a decode. either ! way, once everything is good and done and we want to save the coding ! system so it can be used later, we need to do another sort of ! canonicalization - converting auto-detect-type coding systems into the ! detected systems. again, a coding-system method, with some magic ! currently so that subsidiaries get properly used rather than something ! that's new but equivalent to subsidiaries. (#### perhaps we could use a ! hash table to avoid recreating coding systems when not necessary. but ! that would require that coding systems be immutable from external, and ! i'm not sure that's the case.) ! ! i really think, after all, that i should reverse the naming of ! everything in chain and source-sink-type - they should be ! decoding-centric. later on, if/when we come up with the proper way to ! make it totally symmetrical, we'll be fine whether before then we were ! encoding or decoding centric. ! ! sep 9, 2001 ! =========== ! ! investigated eol parameter. ! ! implemented handling in `make-coding-system' of `eol-cr' and ! `eol-crlf'. fixed calls everywhere to `Fget_coding_system' / ! `Ffind_coding_system' to reject non-char->byte coding systems. ! still need to handle "query eol type using coding-system-property" ! so it magically returns the right type by parsing the chain. ! no work done on formats, as mentioned below. we should consider ! using : instead of || to indicate casting. ! early sep 9, 2001 ! ================= ! renamed some codesys properties: `list' in chain -> chain; `subtype' in ! unicode -> type. everything compiles again and sort of works; some CRLF ! problems that may resolve themselves when i finish the convert-eol ! stuff. the stuff to create subsidiaries has been rewritten to use ! chains; but i still need to investigate how the EOL type parameter is ! used. also, still need to implement this: when a coding system is ! created, and its eol type is not autodetect or lf, a chain needs to be ! created and returned. i think that what needs to happen is that the ! eol type can only be set to autodetect or lf; later on this should be ! changed to simply be either autodetect or not (but that would require ! ripping out the eol converting stuff in the various coding systems), ! and eventually we will do the work on the detection mechanism so it can ! do chain detection; then we won't need an eol autodetect setting at ! all. i think there's a way to query the eol type of a coding system; ! this should check to see if the coding system is a chain and there's a ! convert-eol at the front; if so, the eol type comes from the type of ! the convert-eol. ! ! also check out everywhere that `Fget_coding_system' or ! `Ffind_coding_system' is called, and see whether anything but a ! char->byte system can be tolerated. create a new function for all the ! places that only want char->byte, something like ! `get_coding_system_char_to_byte_only'. ! ! think about specifying formats in make-coding-system. perhaps the ! name can be a cons of (format1, format2), specifying that it encodes ! format1->format2 and decodes the other way. if only one name is given, ! that is assumed to be format2, and the other is either `byte' or `char' ! depending on the end type. normally the user when decoding gives the ! decoding order in formats, but can leave off the last one, `char', ! which is assumed. perhaps we should say `internal' instead of `char' ! and `external' instead of byte. a multichain might look like ! gzip|multibyte|unicode, using the coding systems named `gzip', ! `(unicode . multibyte)' and `unicode'. we would have to allow ! something where one format is given only as generic byte/char or ! internal/external to fit with any of the same byte/char type. when ! forcibly fitting together two converters that have explicitly specified ! and incompatible names (say you have unicode->multibyte and ! iso8859-1->ebcdic and you know that the multibyte and iso8859-1 in this ! case are compatible), you can force-cast using ||, like this: ! ebcdic|iso8859-1||multibyte|unicode. this will also force ! external->internal translation as necessary: ! unicode|multibyte||crlf|internal does unicode->multibyte, ! external->internal, crlf->internal. perhaps you'd need to put in the ! internal translation, like this: ! unicode|multibyte|internal||crlf|internal, which means ! unicode->multibyte, external->internal (multibyte is compatible with ! external); force-cast to crlf format and convert crlf->internal. ! ! even later: Sep 8, 2001 ! ======================= ! ! chain doesn't need to set character mode, that happens automatically ! when the coding systems are created. fixed chain to return correct ! source/sink type for itself and to check the compatibility of ! source/sink types in its chain. fixed decode/encode-coding-region to ! check the source and sink types of the coding system performing the ! conversion and insert appropriate byte->char/char->byte converters (aka ! "binary" coding system). fixed set-coding-category-system to only ! accept the traditional encode-char-to-byte types of coding systems. ! ! still need to extend chain to specify the parameters mentioned below, ! esp. "reverse". also need to extend the print mechanism for chain so it ! prints out the chain. probably this should be general: have a new ! method to return all properties, and output those properties. you ! could also implement a read syntax for coding systems this way. ! ! still need to implement `convert-eol' and finish up the rest of the ! eol stuff mentioned below. ! ! later September 7, 2001 (more like Sep 8) ! ========================================= ! ! moved many `Lisp_Coding_System *' params to `Lisp_Object'. In general ! this is the way to go, and if we ever implement a copying GC, we will ! never want to be passing direct pointers around. With no ! error-checking, we lose no cycles using `Lisp_Object's in place of ! pointers - the `Lisp_Object' itself is nothing but a pointer, and so ! all the casts and "dereferences" boil down to nothing. ! ! Clarified and cleaned up the "character mode" on streams, and ! documented who (caller or object itself) has the right to be setting ! character mode on a stream, depending on whether it's a read or write ! stream. changed `conversion_end_type' method and `enum ! source_sink_type' to return encoding-centric values, rather than ! decoding-centric. for the moment, we're going to be entirely ! encoding-centric in everything; we can rethink later. fixed coding ! systems so that the decode and encode methods are guaranteed to receive ! only full characters, if that's the source type of the data, as per ! conversion_end_type. ! ! still need to fix the chain method so that it correctly sets the ! character mode on all the lstreams in it and checks the source/sink ! types to be compatible. also fix `decode-coding-string' and friends to ! put the appropriate byte->character (i.e. `no-conversion') coding ! systems on the ends as necessary so that the final ends are both ! character. also add to chain a parameter giving the ability to switch ! the direction of conversion of any particular item in the chain (i.e. ! swap encoding and decoding). i think what we really want to do is ! allow for arbitrary parameters to be put onto a particular coding ! system in the chain, of which the only one so far is ! swap-encode-decode. don't need too much codage here for that, but make ! the design extendable. ! September 7, 2001 ! ================= ! just added a return value from the decode and encode methods of a coding ! system, so that some of the data can get rejected. fixed the calling ! routines to handle this. need to investigate when and whether the ! coding lstream is set to character mode, so that the decode/encode ! methods only get whole characters. if not, we should do so, according ! to the source type of these methods. also need to implement the ! convert_eol coding system, and fix the subsidiary coding systems (and ! in general, any coding system where the eol type is specified and is ! not LF) to be chains involving convert_eol. ! ! after everything is working, need to remove eol handling from ! encode/decode methods and eventually consider rewriting (simplifying) ! them given the reject ability. ! September 5, 2001 ! ================= ! * need to organize this. get everything below into the TODO list. ! CVS the TODO list frequently so i can delete old stuff. prioritize ! it!!!!!!!!! ! * move `README.ben-mule...' to `STATUS.ben-mule...'; use `README' ! for intro, overview of what's new, what's broken, how to use the ! features, etc. ! * need a global and local `coding-category-precedence' list, which ! get merged. ! * finished the BOM support. also finished something not listed ! below, expansion to the auto-generator of Unicode-encapsulation to ! support bracketing code with `#if ... #endif', for Cygwin and MINGW ! problems, e.g. This is tested; appears to work. ! * need to add more multibyte coding systems now that we have various ! properties to specify them. need to add DEFUN's for mac-code-page ! and ebcdic-code-page for completeness. need to rethink the whole ! way that the priority list works. it will continue to be total ! junk until multiple levels of likeliness get implemented. ! * need to finish up the stuff about the various defaults. [need to ! investigate more generally where all the different default values ! are that control encoding. (there are six places or so.) need to ! list them in `make-coding-system' docs and put pointers elsewhere. ! [[[[#### what interface to specify that this default should be ! unicode? a "Unicode" language environment seems too drastic, as ! the language environment controls much more.]]]] even skipping the ! Unicode stuff here, we need to survey and list the variables that ! control coding page behavior and determine how they need to be set ! for various possible scenarios: ! * total binary: no detection at all. ! * raw-text only: wants only autodetection of line endings, ! nothing else. ! * "standard Windows environment": tries for Unicode, falls ! back on code page encoding. ! * some sort of East European environment, and Russian. ! * some sort of standard Japanese Windows environment. ! * standard Chinese Windows environments (traditional and ! simplified) ! * various Unix environments (European, Japanese, Russian, ! etc.) ! * Unicode support in all of these when it's reasonable ! These really require multiple likelihood levels to be fully ! implementable. We should see what can be done ("gracefully fall back") ! with single likelihood level. need lots of testing. ! * need to fix the truename problem. ! * lots of testing: need to test all of the stuff above and below ! that's recently been implemented. ! September 4, 2001 ! ================= ! mostly everything compiles. currently there is a crash in ! `parse-unicode-translation-table', and Cygwin/Mule won't run. it may ! well be a bug in the `sscanf()' in Cygwin. ! ! working on today: ! ! * adding BOM support for Unicode coding systems. mostly there, but ! need to finish adding BOM support to the detection routines. then ! test. ! ! * adding properties to `unicode-to-multibyte' to specify the coding ! system in various flexible ways, e.g. directly specified code page ! or ansi or oem code page of specified locale, current locale, ! user-default or system-default locale. need to test. ! ! * creating a `multibyte' coding system, with the same parameters as ! unicode-to-multibyte and which resolves at coding-system-creation ! time to the appropriate chain. creating the underlying mechanism ! to allow such under-the-scenes switcheroo. need to test. ! ! * set default-value of `buffer-file-coding-system' to ! mswindows-multibyte, as Matej said it should be. need to test. ! need to investigate more generally where all the different default ! values are that control encoding. (there are six places or so.) ! need to list them in make-coding-system docs and put pointers ! elsewhere. #### what interface to specify that this default should ! be unicode? a "Unicode" language environment seems too drastic, as ! the language environment controls much more. ! ! * thinking about adding multiple levels of certainty to the detection ! schemes, instead of just a mask. eventually, we need to totally ! abstract things, but that can easier be done in many steps. (we ! need multiple levels of likelihood to more reasonably support a ! Windows environment with code-page type files. currently, in order ! to get them detected, we have to put them first, because they can ! look like lots of other things; but then, other encodings don't get ! detected. with multiple levels of likelihood, we still put the ! code-page categories first, but they will return low levels of ! likelihood. Lower-down encodings may be able to return higher ! levels of likelihood, and will get taken preferentially.) ! ! * making it so you cannot disable file-coding, but you get an ! equivalent default on Unix non-Mule systems where all defaults are ! `binary'. need to test!!!!!!!!! ! ! Matej (mostly, + some others) notes the following problems, and here ! are possible solutions: ! ! * he wants the defaults to work right. [figure out what those ! defaults are. i presume they are auto-detection of data in current ! code page and in unicode, and new files have current code page set ! as their output encoding.] ! ! * too easy to lose data with incorrect encodings. [need to set up an ! error system for encoding/decoding. extremely important but a ! little tricky to implement so let's deal with other issues now.] ! ! * EOL isn't always detected correctly. [#### ?? need examples] ! ! * truename isn't working: `c:\t.txt' and `c:\tmp.txt' have the same ! truename. [should be easy to fix] ! ! * unicode files lose the BOM mark. [working on this] ! ! * command-line utilities use OEM. [actually it seems more ! complicated. it seems they use the codepage of the console. we ! may be able to set that, e.g. to UTF8, before we invoke a command. ! need to investigate.] ! ! * no way to handle unicode characters not recognized as charsets. [we ! need to create something like 8 private 2-dimensional charsets to ! handle all BMP Unicode chars. Obviously this is a stopgap ! solution. Switching to Unicode internal will ultimately make life ! far easier and remove the BMP limitation. but for now it will ! work. we translate all characters where we have charsets into ! chars in those charsets, and the remainder in a unicode charset. ! that way we can save them out again and guarantee no data loss with ! unicode. this creates font problems, though ...] ! ! * problems with xemacs font handling. [xemacs font handling is not ! sophisticated enough. it goes on a charset granularity basis and ! only looks for a font whose name contains the corresponding windows ! charset in it. with unicode this fails in various ways. for one ! the granularity needs to be single character, so that those unicode ! charsets mentioned above work; and it needs to query the font to ! see what unicode ranges it supports, rather than just looking at ! the charset ending.] ! ! August 28, 2001 ! =============== ! ! working on getting everything to compile again: Cygwin, non-MULE, ! pdump. not there yet. ! ! `mswindows-multibyte' is now defined using chain, and works. ! removed most vestiges of the `mswindows-multibyte' coding system type. ! ! file-coding is on by default; should default to binary only on Unix. ! Need to test. (Needs to compile first :-) ! ! August 26, 2001 ! =============== ! ! I've fixed the issue of inputting non-ASCII text under -nuni, and done ! some of the work on the Russian problem - we now compute the ! other possibilities. We still need to fix the key-lookup code, though, ! and that code is unfortunately a bit ugly. the best way, it seems, is ! to expand the command-builder structure so you can specify different ! interpretations for keys. (if we do find an alternative binding, though, ! we need to mess with both the command builder and this-command-keys, as ! does the function-key stuff. probably need to abstract that munging ! code.) ! ! high-priority: ! ! *[currently doing]* ! * support for `WM_IME_CHAR'. IME input can work under `-nuni' ! if we use `WM_IME_CHAR'. probably we should always be using ! this, instead of snarfing input using `WM_COMPOSITION'. i'll ! check this out. ! ! * Russian problem. see above. ! ! *[clean-up]* ! * make sure it compiles and runs under non-mule. remember that ! some code needs the unicode support, or at least a simple ! version of it. ! ! * make sure it compiles and runs under pdump. see below. ! ! * clean up `mswindows-multibyte', `TSTR_TO_C_STRING'. see ! below. [DONE] ! ! * eliminate last vestiges of codepage<->charset conversion and ! similar stuff. ! ! *[other]* ! * cut and paste. see below. ! ! * misc issues with handling lang environments. see also August ! 25, "finally: working on the C-x in ...". ! * when switching lang env, needs to set keyboard layout. ! ! * user var to control whether, when moving into text of a ! particular language, we set the appropriate keyboard ! layout. we would need to have a lisp api for ! retrieving and setting the keyboard layout, set text ! properties to indicate the layout of text, and have a ! way of dealing with text with no property on it. (e.g. ! saved text has no text properties on it.) basically, ! we need to get a keyboard layout from a charset; getting ! a language would do. Perhaps we need a table that ! maps charsets to language environments. ! ! * test that the lang env is properly set at startup. ! test that switching the lang env properly sets the C ! locale (call setlocale(), set LANG, etc.) - a spawned ! subprogram should have the new locale in its ! environment. ! ! * look through everything below and see if anything is missed ! in this priority list, and if so add it. create a separate ! file for the priority list, so it can be updated as ! appropriate. ! ! mid-priority: ! ! * clean up the chain coding system. its list should specify decode ! order, not encode; i now think this way is more logical. it should ! check the endpoints to make sure they make sense. it should also ! allow for the specification of "reverse-direction coding systems": ! use the specified coding system, but invert the sense of decode and ! encode. ! ! * along with that, places that take an arbitrary coding system and ! expect the ends to be anything specific need to check this, and add ! the appropriate conversions from byte->char or char->byte. ! ! * get some support for arabic, thai, vietnamese, japanese jisx 0212: ! at least get the unicode information in place and make sure we have ! things tied together so that we can display them. worry about r2l ! some other time. ! ! August 25, 2001 ! =============== ! ! There is actually more non-Unicode-ized stuff, but it's basically ! inconsequential. (See previous note.) You can check using the file ! nmkun.txt (#### RENAME), which is just a list of all the routines that ! have been split. (It was generated from the output of `nmake ! unicode-encapsulate', after removing everything from the output but the ! function names.) Use something like ! ! fgrep -f ../nmkun.txt -w [a-hj-z]*.[ch] |m ! ! in the source directory, which does a word match and skips ! `intl-unicode-win32.[ch]' and `intl-win32.[ch]', which have a whole lot ! of references to these, unavoidably. It effectively detects what needs ! to be changed because changed versions either begin `qxe...' or end ! with A or W, and in each case there's no whole-word match. ! ! The nasty bug has been fixed below. The `-nuni' option now works - ! all specially-written code to handle the encapsulation has been tested ! by some operation (fonts by loadup and checking the output of ! `(list-fonts "")'; devmode by printing; dragdrop tests other stuff). ! ! NOTE: for `-nuni' (Win 95), areas need work: ! ! * cut and paste. we should be able to receive Unicode text if it's ! there, and we should be able to receive it even in Win 95 or ! `-nuni'. we should just check in all circumstances. also, under ! 95, when we put some text in the clipboard, it may or may not also ! be automatically enumerated as unicode. we need to test this out ! and/or just go ahead and manually do the unicode enumeration. ! ! * receiving keyboard input. we get only a single byte, but we should ! be able to correlate the language of the keyboard layout to a ! particular code page, so we can then decode it correctly. ! ! * `mswindows-multibyte'. still implemented as its own thing. should ! be done as a chain of (encoding) unicode | unicode-to-multibyte. ! need to turn this on, get it working, and look into optimizations ! in the dfc stuff. (#### perhaps there's a general way to do these ! optimizations??? something like having a method on a coding ! system that can specify whether a pure-ASCII string gets rendered ! as pure-ASCII bytes and vice-versa.) ! ! ALSO: ! ! * we have special macros `TSTR_TO_C_STRING' and such because formerly ! the `DFC' macros didn't know about external stuff that was Unicode ! encoded and would call `strlen()' on them. this is fixed, so now ! we should undo the special macros, make em normal, removal the ! comments about this, and make sure it works. [DONE] ! ! * finally: working on the `C-x' in Russian key layout problem. in ! the process will probably end up doing work on cleaning up the ! handling of keyboard layouts, integrating or deleting the FSF ! stuff, adding code to change the keyboard layout as we move in and ! out of text in different languages (implemented as a ! post-command-hook; we need something like ! internal-post-command-hook if not already there, for internal ! stuff that doesn't want to get mixed up with the regular ! post-command-hook; similar for pre-command-hook). also, when ! langenv changes, ways to set the keyboard layout appropriately. ! ! * i think the stuff above is higher priority than the other stuff ! mentioned below. what i'm aiming for is to be able to input and ! work with multiple languages without weird glitches, both under 95 ! and NT. the problems above are all basic impediments to such work. ! we assume for the moment that the user can make use of the existing ! file i/o conversion stuff, and put that lower in priority, after ! the basic input is working. ! ! * i should get my modem connected and write up what's going on and ! send it to the lists; also cvs commit my workspaces and get more ! testers. ! ! August 24, 2001: ! ! All code has been Unicode-ized except for some stuff in console-msw.c ! that deals with console output. Much of the Unicode-encapsulation ! stuff, particularly the hand-written stuff, really needs testing. I ! added a new command-line option, `-nuni', to force use of all ANSI ! calls - `XE_UNICODEP' evaluates to false in this case. ! ! There is a nasty bug that appeared recently, probably when the event ! code got Unicode-ized - bad interactions with OS sticky modifiers. ! Hold the shift key down and release it, then instead of affecting the ! next char only, it gets permanently stuck on (until you do a regular ! shift+char stroke). This needs to be debugged. ! ! Other things on agenda: ! ! * go through and prioritize what's listed below. ! ! * make sure the pdump code can compile and work. for the moment we ! just don't try to dump any Unicode tables and load them up each ! time. this is certainly fast but ... ! ! * there's the problem that XEmacs can't be run in a directory with ! non-ASCII/Latin-1 chars in it, since it will be doing Unicode ! processing before we've had a chance to load the tables. In fact, ! even finding the tables in such a situation is problematic using ! the normal commands. my idea is to eventually load the stuff ! extremely extremely early, at the same time as the pdump data gets ! loaded. in fact, the unicode table data (stored in an efficient ! binary format) can even be stuck into the pdump file (which would ! mean as a resource to the executable, for windows). we'd need to ! extend pdump a bit: to allow for attaching extra data to the pdump ! file. (something like `pdump_attach_extra_data (addr, length)' ! returns a number of some sort, an index into the file, which you ! can then retrieve with `pdump_load_extra_data()', which returns an ! addr (`mmap()'ed or loaded), and later you ! `pdump_unload_extra_data()' when finished. we'd probably also need ! `pdump_attach_extra_data_append()', which appends data to the data ! just written out with `pdump_attach_extra_data()'. this way, ! multiple tables in memory can be written out into one contiguous ! table. (we'd use the tar-like trick of allowing new blocks to be ! written without going back to change the old blocks - we just rely ! on the end of file/end of memory.) this same mechanism could be ! extracted out of pdump and used to handle the non-pdump situation ! (or alternatively, we could just dump either the memory image of ! the tables themselves or the compressed binary version). in the ! case of extra unicode tables not known about at compile time that ! get loaded before dumping, we either just dump them into the image ! (pdump and all) or extract them into the compressed binary format, ! free the original tables, and treat them like all other tables. ! ! * `C-x b' when using a Russian keyboard layout. XEmacs currently ! tries to interpret `C+cyrillic char', which causes an error. We ! want `C-x b' to still work even when the keyboard normally ! generates Cyrillic. What we should do is expand the keyboard ! event structure so that it contains not only the actual char, but ! what the char would have been in various other keyboard layouts, ! and in contexts where only certain keystrokes make sense (creating ! control chars, and looking up in keymaps), we proceed in order, ! processing each of them until we get something. order should be ! something like: current keyboard layout; layout of the current ! language environment; layout of the user's default language; ! layout of the system default language; layout of US English. ! ! * reading and writing Unicode files. multiple problems: ! ! * EOL's aren't handled right. for the moment, just fix the ! Unicode coding systems; later on, create EOL-only coding ! systems: ! ! 1. they would be character->character and operate next ! to the internal data; this means that coding systems ! need to be able to handle ends of lines that are ! either CR, LF, or CRLF. usually this isn't a ! problem, as they are just characters like any other ! and get encoded appropriately. however, coding ! systems that are line-oriented need to recognize any ! of the three as line endings. ! ! 2. we'd also have to complete the stuff that handles ! coding systems where either end can be byte or char ! (four possibilities total; use a single enum such as ! `ENCODES_CHAR_TO_BYTE', `ENCODES_BYTE_TO_BYTE', ! etc.). ! ! 3. we'd need ways of specifying the chaining of coding ! systems. e.g. when reading a coding system, a user ! can specify more than one with a | symbol between ! them. when a context calls for a coding system and ! a chain is needed, the `chain' coding system is ! useful; but we should really expand the contexts ! where a list of coding systems can be given, and whenever ! possible try to inline the chain instead of using a ! surrounding `chain' coding system. ! ! 4. the `chain' needs some work so that it passes all ! sorts of lstream commands down to the chain inside ! it - it should be entirely transparent and the fact ! that there's actually a surrounding coding system ! should be invisible. more general coding system ! methods might need to be created. ! ! 5. important: we need a way of specifying how detecting ! works when we have more than one coding system. we ! might need more than a single priority list. need ! to think about this. ! ! * Unicode files beginning with the BOM are not recognized as ! such. we need to fix this; but to make things sensible, we ! really need to add the idea of different levels of ! confidence regarding what's detected. otherwise, Unicode ! says "yes this is me" but others higher up do too. in the ! process we should probably finish abstracting the detection ! system and fix up some stupidities in it. ! ! * When writing a file, we need error detection; otherwise ! somebody will create a Unicode file without realizing the ! coding system of the buffer is Raw, and then lose all the ! non-ASCII/Latin-1 text when it's written out. We need two ! levels ! ! 1. first, a "safe-charset" level that checks before any ! actual encoding to see if all characters in the ! document can safely be represented using the given ! coding system. FSF has a "safe-charset" property of ! coding systems, but it's stupid because this ! information can be automatically derived from the ! coding system, at least the vast majority of the time. ! What we need is some sort of ! alternative-coding-system-precedence-list, ! langenv-specific, where everything on it can be ! checked for safe charsets and then the user given a ! list of possibilities. When the user does "save ! with specified encoding", they should see the same ! precedence list. Again like with other precedence lists, ! there's also a global one, and presumably all coding ! systems not on other list get appended to the end ! (and perhaps not checked at all when doing ! safe-checking?). safe-checking should work ! something like this: compile a list of all charsets ! used in the buffer, along with a count of chars ! used. that way, "slightly unsafe" charsets can perhaps ! be presented at the end, which will lose only a few ! characters and are perhaps what the users were ! looking for. ! ! 2. when actually writing out, we need error checking in ! case an individual char in a charset can't be ! written even though the charsets are safe. again, ! the user gets the choice of other reasonable coding ! systems. ! ! 3. same thing (error checking, list of alternatives, ! etc.) needs to happen when reading! all of this ! will be a lot of work! ! Announcement, August 20, 2001: ! ============================== ! I'm looking for testers. There is a complete and fast implementation ! in C of Unicode conversion, translations for almost all of the ! standardly-defined charsets that load up automatically and ! instantaneously at runtime, coding systems supporting the common ! external representations of Unicode [utf-16, ucs-4, utf-8, ! little-endian versions of utf-16 and ucs-4; utf-7 is sitting there with ! abort[]s where the coding routines should go, just waiting for somebody ! to implement], and a nice set of primitives for translating ! characters<->codepoints and setting the priority lists used to control ! codepoint->char lookup. ! ! It's so far hooked into one place: the Windows IME. Currently I can ! select the Japanese IME from the thing on my tray pad in the lower ! right corner of the screen, and type Japanese into XEmacs, and you get ! Japanese in XEmacs - regardless of whether you set either your current ! or global system locale to Japanese,and regardless of whether you set ! your XEmacs lang env as Japanese. This should work for many other ! languages, too - Cyrillic, Chinese either Traditional or Simplified, ! and many others, but YMMV. There may be some lurking bugs (hardly ! surprising for something so raw). ! ! To get at this, checkout using `ben-mule-21-5', NOT the simpler ! *`mule-21-5'. For example ! ! cvs -d :pserver:xemacs@cvs.xemacs.org:/usr/CVSroot checkout -r ! ben-mule-21-5 xemacs ! ! or you get the idea. the `-r ben-mule-21-5' is important. ! ! I keep track of my progress in a file called README.ben-mule-21-5 in ! the root directory of the source tree. ! ! WARNING: Pdump might not work. Will be fixed rsn. ! ! August 20, 2001 ! =============== ! ! * still need to sort out demand loading, binary format, etc. figure ! out what the goals are and how we're going to achieve them. for ! the moment let's just say that running XEmacs in a directory with ! Japanese or other weird characters in the name is likely to cause ! problems under MS Windows, but once XEmacs is initialized (and ! before processing init files), all Unicode support is there. ! ! * wrote the size computation routines, although not yet tested. ! ! * lots more abstraction of coding systems; almost done. ! ! * UNICODE WORKS!!!!! ! ! August 19, 2001 ! =============== ! ! Still needed on the Unicode support: ! ! * demand loading: load the Unicode table data the first time a ! conversion needs to be done. ! ! * maybe: table size computation: figure out how big the in-memory ! tables actually are. ! ! * maybe: create a space-efficient binary format for the data, and a ! way to dump out an existing charset's data into this binary format. ! it should allow for many such groups of data to be appended ! together in one file, such that you can just append the new data ! onto the end and not have to go back and modify anything ! previously. (like how tar archives work, and how the UFS? for ! CD-R's and CD-RW's works.) ! ! * maybe: figure out how to be able to access the Unicode tables at ! `init_intl()' time, before we know how to get at data-directory; ! that way we can handle the need for unicode conversions that come ! up very early, for example if XEmacs is run from a directory ! containing Japanese in it. Presumably we'd want to generalize the ! stuff in `pdump.c' that deals with the dumper file, so that it can ! handle other files - putting the file either in the directory of ! the executable or in a resource, maybe actually attached to the ! pdump file itself - or maybe we just dump the data into the actual ! executable. With pdump we could extend pdump to allow for data ! that's in the pdump file but not actually mapped at startup, ! separate from the data that does get mapped - and then at runtime ! the pointer gets restored not with a real pointer but an offset ! into the file; another pdump call and we get some way to access ! the data. (tricky because it might be in a resource, not a file. ! we might have to just tell pdump to mmap or whatever the data in, ! and then tell pdump to release it.) ! ! * fix multibyte to use unicode. at first, just reverse ! `mswindows-multibyte-to-unicode' to be `unicode-to-multibyte'; ! later implement something in chain to allow for reversal, for ! declaring the ends of the coding systems, etc. ! ! * actually make sure that the IME stuff is working!!! ! ! Other things before announcing: ! ! * change so that the Unicode tables are not pdumped. This means we ! need to free any table data out there. Make sure that pdump ! compiles and try to finish the pretty-much-already-done stuff ! already with `XD_STRUCT_ARRAY' and dynamic size computation; just ! need to see what's going on with `LO_LINK'. ! ! August 14, 2001 ! =============== ! ! To do a diff between this workspace and the mainline, use the most ! recent sync tags, currently: ! ! cvs diff -r main-branch-ben-mule-21-5-aug-11-2001-sync -r ben-mule-21-5-post-aug-11-2001-sync ! ! Unicode support: ! ! Unicode support is important for supporting many languages under ! Windows, such as Cyrillic, without resorting to translation tables for ! particular Windows-specific code pages. Internally, all characters in ! Windows can be represented in two encodings: code pages and Unicode. ! With Unicode support, we can seamlessly support all Windows characters. ! Currently, the test in the drive to support Unicode is if IME input ! works properly, since it is being converted from Unicode. ! ! Unicode support also requires that the various Windows API's be ! "Unicode-encapsulated", so that they automatically call the ANSI or ! Unicode version of the API call appropriately and handle the size ! differences in structures. What this means is: ! ! * first, note that Windows already provides a sort of encapsulation ! of all API's that deal with text. All such API's are underlyingly ! provided in two versions, with an A or W suffix (ANSI or "wide" ! i.e. Unicode), and the compile-time constant UNICODE controls which ! is selected by the unsuffixed API. Same thing happens with ! structures. Unfortunately, this is compile-time only, not ! run-time, so not sufficient. (Creating the necessary run-time ! encoding is not conceptually difficult, but very time-consuming to ! write. It adds no significant overhead, and the only reason it's ! not standard in Windows is conscious marketing attempts by ! Microsoft to cripple Windows 95. FUCK MICROSOFT! They even ! describe in a KnowledgeBase article exactly how to create such an ! API [although we don't exactly follow their procedure], and point ! out its usefulness; the procedure is also described more generally ! in Nadine Kano's book on Win32 internationalization - written SIX ! YEARS AGO! Obviously Microsoft has such an API available ! internally.) ! ! * what we do is provide an encapsulation of each standard Windows API ! call that is split into A and W versions. current theory is to ! avoid all preprocessor games; so we name the function with a prefix ! - "qxe" currently - and require callers to use the prefixed name. ! Callers need to explicitly use the W version of all structures, and ! convert text themselves using `Qmswindows_tstr'. the qxe ! encapsulated version will automatically call the appropriate A or W ! version depending on whether we're running on 9x or NT, and copy ! data between W and A versions of the structures as necessary. ! ! * We require the caller to handle the actual translation of text to ! avoid possible overflow when dealing with fixed-size Windows ! structures. There are no such problems when copying data between ! the A and W versions because ANSI text is never larger than its ! equivalent Unicode representation. ! ! * We allow for incremental creation of the encapsulated routines by ! using the coding system `Qmswindows_tstr_notyet'. This is an ! alias for `Qmswindows_multibyte', i.e. it always converts to ANSI; ! but it indicates that it will be changed to `Qmswindows_tstr' when ! we have a qxe version of the API call that the data is being ! passed to and change the code to use the new function. ! ! Besides creating the encapsulation, the following needs to be done ! for Unicode support: ! ! * No actual translation tables are fed into XEmacs. We need to ! provide glue code to read the tables in `etc/unicode'. See ! `etc/unicode/README' for the interface to implement. ! ! * Fix pdump. The translation tables for Unicode characters function ! as unions of structures with different numbers of indirection ! levels, in order to be efficient. pdump doesn't yet support such ! unions. `charset.h' has a general description of how the ! translation tables work, and the pdump code has constants added ! for the new required data types, and descriptions of how these ! should work. ! ! * ultimately, there's no end to additional work (composition, bidi ! reordering, glyph shaping/ordering, etc.), but the above is enough ! to get basic translation working. ! ! Merging this workspace into the trunk requires some work. ChangeLogs ! have not yet been created. Also, there is a lot of additional code in ! this workspace other than just Windows and Unicode stuff. Some of the ! changes have been somewhat disruptive to the code base, in particular: ! ! * the code that handles the details of processing multilingual text ! has been consolidated to make it easier to extend it. it has been ! yanked out of various files (`buffer.h', `mule-charset.h', ! `lisp.h', `insdel.c', `fns.c', `file-coding.c', etc.) and put into ! `text.c' and `text.h'. `mule-charset.h' has also been renamed ! `charset.h'. all long comments concerning the representations and ! their processing have been consolidated into `text.c'. ! ! * `nt/config.h' has been eliminated and everything in it merged into ! `config.h.in' and `s/windowsnt.h'. see `config.h.in' for more ! info. ! ! * `s/windowsnt.h' has been completely rewritten, and `s/cygwin32.h' ! and `s/mingw32.h' have been largely rewritten. tons of dead ! weight has been removed, and stuff common to more than one file ! has been isolated into `s/win32-common.h' and `s/win32-native.h', ! similar to what's already done for usg variants. ! * large amounts of code throughout the code base have been Mule-ized, ! not just Windows code. ! * `file-coding.c/.h' have been largely rewritten (although still ! mostly syncable); see below. ! June 26, 2001 ! ============= ! ben-mule-21-5 ! this contains all the mule work i've been doing. this includes ! mostly work done to get mule working under ms windows, but in the ! process i've [of course] fixed a whole lot of other things as well, ! mostly mule issues. the specifics: ! ! * it compiles and runs under windows and should basically work. the ! stuff remaining to do is (a) improved unicode support (see below) ! and (b) smarter handling of keyboard layouts. in particular, it ! should (1) set the right keyboard layout when you change your ! language environment; (2) optionally (a user var) set the ! appropriate keyboard layout as you move the cursor into text in a ! particular language. ! ! * i added a bunch of code to better support OS locales. it tries to ! notice your locale at startup and set the language environment ! accordingly (this more or less works), and call setlocale() and set ! LANG when you change the language environment (may or may not ! work). ! ! * major rewriting of file-coding. it's mostly abstracted into coding ! systems that are defined by methods (similar to devices and ! specifiers), with the ultimate aim being to allow non-i18n coding ! systems such as gzip. there is a "chain" coding system that allows ! multiple coding systems to be chained together. (it doesn't yet ! have the concept that either end of a coding system can be bytes or ! chars; this needs to be added.) ! ! * unicode support. very raw. a few days ago i wrote a complete and ! efficient implementation of unicode translation. it should be very ! fast, and fairly memory-efficient in its tables. it allows for ! charset priority lists, which should be language-environment ! specific (but i haven't yet written the glue code). it works in ! preliminary testing, but obviously needs more testing and work. ! as of yet there is no translation data added for the standard ! charsets. the tables are in etc/unicode, and all we need is a bit ! of glue code to process them. see etc/unicode/README for the ! interface to implement. ! ! * support for unicode in windows is partly there. this will work ! even on windows 95. the basic model is implemented but it needs ! finishing up. ! ! * there is a preliminary implementation of windows ime support ! courtesy of ikeyama. ! ! * if you want to get cyrillic working under windows (it appears to ! "work" but the wrong chars currently appear), the best way is to ! add unicode support for iso-8859-5 and use it in redisplay-msw.c. ! we are already passing unicode codepoints to the text-draw routine ! (ExtTextOutW). (ExtTextOutW and GetTextExtentPoint32W are ! implemented on both 95 and NT.) ! ! * i fixed the iso2022 handling so it will correctly read in files ! containing unknown charsets, creating a "temporary" charset which ! can later be overwritten by the real charset when it's defined. ! this allows iso2022 elisp files with literals in strange languages ! to compile correctly under mule. i also added a hack that will ! correctly read in and write out the emacs-specific "composition" ! escape sequences, i.e. `ESC 0' through `ESC 4'. this means that ! my workspace correctly compiles the new file `devanagari.el' that ! i added (see below). ! ! * i copied the remaining language-specific files from fsf. i made ! some minor changes in certain cases but for the most part the stuff ! was just copied and may not work. ! ! * i fixed `post-read-conversion' in coding systems to follow fsf ! conventions. (i also support our convention, for the moment. a ! kludge, of course.) ! * `make-coding-system' accepts (but ignores) the additional ! properties present in the fsf version, for compatibility. !  ! File: internals.info, Node: Consoles; Devices; Frames; Windows, Next: The Redisplay Mechanism, Prev: Multilingual Support, Up: Top ! 26 Consoles; Devices; Frames; Windows ! ************************************* ! * Menu: ! ! * Introduction to Consoles; Devices; Frames; Windows:: ! * Point:: ! * Window Hierarchy:: ! * The Window Object:: ! * Modules for the Basic Displayable Lisp Objects::  ! File: internals.info, Node: Introduction to Consoles; Devices; Frames; Windows, Next: Point, Prev: Consoles; Devices; Frames; Windows, Up: Consoles; Devices; Frames; Windows ! 26.1 Introduction to Consoles; Devices; Frames; Windows ! ======================================================= ! A window-system window that you see on the screen is called a "frame" ! in Emacs terminology. Each frame is subdivided into one or more ! non-overlapping panes, called (confusingly) "windows". Each window ! displays the text of a buffer in it. (See above on Buffers.) Note that ! buffers and windows are independent entities: Two or more windows can ! be displaying the same buffer (potentially in different locations), and ! a buffer can be displayed in no windows. ! A single display screen that contains one or more frames is called a ! "display". Under most circumstances, there is only one display. ! However, more than one display can exist, for example if you have a ! "multi-headed" console, i.e. one with a single keyboard but multiple ! displays. (Typically in such a situation, the various displays act like ! one large display, in that the mouse is only in one of them at a time, ! and moving the mouse off of one moves it into another.) In some cases, ! the different displays will have different characteristics, e.g. one ! color and one mono. ! XEmacs can display frames on multiple displays. It can even deal ! simultaneously with frames on multiple keyboards (called "consoles" in ! XEmacs terminology). Here is one case where this might be useful: You ! are using XEmacs on your workstation at work, and leave it running. ! Then you go home and dial in on a TTY line, and you can use the ! already-running XEmacs process to display another frame on your local ! TTY. ! Thus, there is a hierarchy console -> display -> frame -> window. ! There is a separate Lisp object type for each of these four concepts. ! Furthermore, there is logically a "selected console", "selected ! display", "selected frame", and "selected window". Each of these ! objects is distinguished in various ways, such as being the default ! object for various functions that act on objects of that type. Note ! that every containing object remembers the "selected" object among the ! objects that it contains: e.g. not only is there a selected window, but ! every frame remembers the last window in it that was selected, and ! changing the selected frame causes the remembered window within it to ! become the selected window. Similar relationships apply for consoles ! to devices and devices to frames.  ! File: internals.info, Node: Point, Next: Window Hierarchy, Prev: Introduction to Consoles; Devices; Frames; Windows, Up: Consoles; Devices; Frames; Windows ! 26.2 Point ! ========== ! Recall that every buffer has a current insertion position, called ! "point". Now, two or more windows may be displaying the same buffer, ! and the text cursor in the two windows (i.e. `point') can be in two ! different places. You may ask, how can that be, since each buffer has ! only one value of `point'? The answer is that each window also has a ! value of `point' that is squirreled away in it. There is only one ! selected window, and the value of "point" in that buffer corresponds to ! that window. When the selected window is changed from one window to ! another displaying the same buffer, the old value of `point' is stored ! into the old window's "point" and the value of `point' from the new ! window is retrieved and made the value of `point' in the buffer. This ! means that `window-point' for the selected window is potentially ! inaccurate, and if you want to retrieve the correct value of `point' ! for a window, you must special-case on the selected window and retrieve ! the buffer's point instead. This is related to why ! `save-window-excursion' does not save the selected window's value of ! `point'. !  ! File: internals.info, Node: Window Hierarchy, Next: The Window Object, Prev: Point, Up: Consoles; Devices; Frames; Windows ! 26.3 Window Hierarchy ! ===================== ! If a frame contains multiple windows (panes), they are always created ! by splitting an existing window along the horizontal or vertical axis. ! Terminology is a bit confusing here: to "split a window horizontally" ! means to create two side-by-side windows, i.e. to make a _vertical_ cut ! in a window. Likewise, to "split a window vertically" means to create ! two windows, one above the other, by making a _horizontal_ cut. ! If you split a window and then split again along the same axis, you ! will end up with a number of panes all arranged along the same axis. ! The precise way in which the splits were made should not be important, ! and this is reflected internally. Internally, all windows are arranged ! in a tree, consisting of two types of windows, "combination" windows ! (which have children, and are covered completely by those children) and ! "leaf" windows, which have no children and are visible. Every ! combination window has two or more children, all arranged along the same ! axis. There are (logically) two subtypes of windows, depending on ! whether their children are horizontally or vertically arrayed. There is ! always one root window, which is either a leaf window (if the frame ! contains only one window) or a combination window (if the frame contains ! more than one window). In the latter case, the root window will have ! two or more children, either horizontally or vertically arrayed, and ! each of those children will be either a leaf window or another ! combination window. ! Here are some rules: ! 1. Horizontal combination windows can never have children that are ! horizontal combination windows; same for vertical. ! 2. Only leaf windows can be split (obviously) and this splitting does ! one of two things: (a) turns the leaf window into a combination ! window and creates two new leaf children, or (b) turns the leaf ! window into one of the two new leaves and creates the other leaf. ! Rule (1) dictates which of these two outcomes happens. ! 3. Every combination window must have at least two children. ! 4. Leaf windows can never become combination windows. They can be ! deleted, however. If this results in a violation of (3), the ! parent combination window also gets deleted. ! 5. All functions that accept windows must be prepared to accept ! combination windows, and do something sane (e.g. signal an error ! if so). Combination windows _do_ escape to the Lisp level. ! 6. All windows have three fields governing their contents: these are ! "hchild" (a list of horizontally-arrayed children), "vchild" (a ! list of vertically-arrayed children), and "buffer" (the buffer ! contained in a leaf window). Exactly one of these will be ! non-`nil'. Remember that "horizontally-arrayed" means ! "side-by-side" and "vertically-arrayed" means "one above the ! other". ! 7. Leaf windows also have markers in their `start' (the first buffer ! position displayed in the window) and `pointm' (the window's ! stashed value of `point'--see above) fields, while combination ! windows have `nil' in these fields. ! 8. The list of children for a window is threaded through the `next' ! and `prev' fields of each child window. ! 9. *Deleted windows can be undeleted*. This happens as a result of ! restoring a window configuration, and is unlike frames, displays, ! and consoles, which, once deleted, can never be restored. ! Deleting a window does nothing except set a special `dead' bit to ! 1 and clear out the `next', `prev', `hchild', and `vchild' fields, ! for GC purposes. ! 10. Most frames actually have two top-level windows--one for the ! minibuffer and one (the "root") for everything else. The modeline ! (if present) separates these two. The `next' field of the root ! points to the minibuffer, and the `prev' field of the minibuffer ! points to the root. The other `next' and `prev' fields are `nil', ! and the frame points to both of these windows. Minibuffer-less ! frames have no minibuffer window, and the `next' and `prev' of the ! root window are `nil'. Minibuffer-only frames have no root ! window, and the `next' of the minibuffer window is `nil' but the ! `prev' points to itself. (#### This is an artifact that should be ! fixed.) !  ! File: internals.info, Node: The Window Object, Next: Modules for the Basic Displayable Lisp Objects, Prev: Window Hierarchy, Up: Consoles; Devices; Frames; Windows ! 26.4 The Window Object ! ====================== ! Windows have the following accessible fields: ! `frame' ! The frame that this window is on. ! `mini_p' ! Non-`nil' if this window is a minibuffer window. ! `buffer' ! The buffer that the window is displaying. This may change often ! during the life of the window. ! `dedicated' ! Non-`nil' if this window is dedicated to its buffer. ! `pointm' ! This is the value of point in the current buffer when this window ! is selected; when it is not selected, it retains its previous ! value. ! `start' ! The position in the buffer that is the first character to be ! displayed in the window. ! `force_start' ! If this flag is non-`nil', it says that the window has been ! scrolled explicitly by the Lisp program. This affects what the ! next redisplay does if point is off the screen: instead of ! scrolling the window to show the text around point, it moves point ! to a location that is on the screen. ! `last_modified' ! The `modified' field of the window's buffer, as of the last time a ! redisplay completed in this window. ! `last_point' ! The buffer's value of point, as of the last time a redisplay ! completed in this window. ! `left' ! This is the left-hand edge of the window, measured in columns. ! (The leftmost column on the screen is column 0.) ! `top' ! This is the top edge of the window, measured in lines. (The top ! line on the screen is line 0.) ! `height' ! The height of the window, measured in lines. ! `width' ! The width of the window, measured in columns. ! `next' ! This is the window that is the next in the chain of siblings. It ! is `nil' in a window that is the rightmost or bottommost of a ! group of siblings. ! `prev' ! This is the window that is the previous in the chain of siblings. ! It is `nil' in a window that is the leftmost or topmost of a group ! of siblings. ! `parent' ! Internally, XEmacs arranges windows in a tree; each group of ! siblings has a parent window whose area includes all the siblings. ! This field points to a window's parent. ! Parent windows do not display buffers, and play little role in ! display except to shape their child windows. Emacs Lisp programs ! usually have no access to the parent windows; they operate on the ! windows at the leaves of the tree, which actually display buffers. ! `hscroll' ! This is the number of columns that the display in the window is ! scrolled horizontally to the left. Normally, this is 0. ! `use_time' ! This is the last time that the window was selected. The function ! `get-lru-window' uses this field. ! `display_table' ! The window's display table, or `nil' if none is specified for it. ! `update_mode_line' ! Non-`nil' means this window's mode line needs to be updated. ! `base_line_number' ! The line number of a certain position in the buffer, or `nil'. ! This is used for displaying the line number of point in the mode ! line. ! `base_line_pos' ! The position in the buffer for which the line number is known, or ! `nil' meaning none is known. ! `region_showing' ! If the region (or part of it) is highlighted in this window, this ! field holds the mark position that made one end of that region. ! Otherwise, this field is `nil'. !  ! File: internals.info, Node: Modules for the Basic Displayable Lisp Objects, Prev: The Window Object, Up: Consoles; Devices; Frames; Windows ! 26.5 Modules for the Basic Displayable Lisp Objects ! =================================================== ! `console-msw.c' ! `console-msw.h' ! `console-stream.c' ! `console-stream.h' ! `console-tty.c' ! `console-tty.h' ! `console-x.c' ! `console-x.h' ! `console.c' ! `console.h' ! These modules implement the "console" Lisp object type. A console ! contains multiple display devices, but only one keyboard and mouse. ! Most of the time, a console will contain exactly one device. ! *This model may no longer suffice.* The X Window System (at least) ! now supports a variety of input devices, including touchscreens and ! tablets, as well as the traditional keyboard and mouse, and may even be ! able to support multiple instances of a single type of input device ! (especially pointing devices) on a single console. ! Consoles are the top of a lisp object inclusion hierarchy. Consoles ! contain devices, which contain frames, which contain windows. ! `device-msw.c' ! `device-tty.c' ! `device-x.c' ! `device.c' ! `device.h' ! These modules implement the "device" Lisp object type. This ! abstracts a particular screen or connection on which frames are ! displayed. As with Lisp objects, event interfaces, and other ! subsystems, the device code is separated into a generic component that ! contains a standardized interface (in the form of a set of methods) onto ! particular device types. ! The device subsystem defines all the methods and provides method ! services for not only device operations but also for the frame, window, ! menubar, scrollbar, toolbar, and other displayable-object subsystems. ! The reason for this is that all of these subsystems have the same ! subtypes (X, TTY, NeXTstep, Microsoft Windows, etc.) as devices do. ! *This abstraction is probably broken* (as of late 2004), at least ! for X consoles, with the advent of the *Xft* library. Xft is a ! complete break from the traditional approach to text rendering in the ! X11 environment, since fonts are composed of glyphs rendered by ! _client-side_ code. These glyphs are then transmitted to the server as ! sets of trapezoids, and displayed by the *XRender* extension (where ! available; the X11 core protocol can also be used, but this is slow). ! The XRender extension is especially attractive because it allows modern ! image composition techniques to be used to render antialiased fonts. ! By contrast, the traditional approach renders fonts on the server ! side as a collection of bitmaps. It is also possible use a _font ! server_ that knows how to render antialiased fonts, but for some reason ! this approach has never caught on. ! The problem that this creates for XEmacs is that the traditional (and ! still popular) widget sets, the various Athena variants and the Motif ! widget set, are based on the server-side rendering model. Thus, even if ! XEmacs-specific widgets (such as the basic text window, the Lucid ! menubar, and the recently added tab control) can be adapted to render ! text via Xft, older widgets (such as buttons and labels) and "modern" ! widgets derived from traditional widgets (the progress gauge) still ! expect their font resources to be converted to server-side fonts. Then ! text is rendered by calls to the core protocol via Xlib, rather than by ! calls to the XRender protocol via Xft. ! It's even possible to imagine a situation where a widget is composed ! of components which draw their own text (_predefined widgets_) as well ! as new components which can draw using more modern methods. Handling ! this will either require reworking the Emacs face mechanism to provide a ! way to determine whether this widget can use that font, or ways to give ! each of several different widgets, even different components of a given ! widget, a different face property. This is already an issue, as widgets ! generally derive their font from the gui-element face, but this might ! not be appropriate for widgets embedded in a buffer. ! There seem to be two overall ways to go. ! 1. Add face information to the Lucid widget library, and extend the ! coverage of that library to device types that aren't supported by ! it yet (MS Windows, and maybe TTY). ! 2. Create a lighter-weight interface, perhaps an extension of the ! device interface, that allows widgets to access face information ! from the device it is implemented on. ! `frame-msw.c' ! `frame-tty.c' ! `frame-x.c' ! `frame.c' ! `frame.h' ! Each device contains one or more frames in which objects (e.g. text) ! are displayed. A frame corresponds to a window in the window system; ! usually this is a top-level window but it could potentially be one of a ! number of overlapping child windows within a top-level window, using the ! MDI (Multiple Document Interface) protocol in Microsoft Windows or a ! similar scheme. ! The `frame-*' files implement the "frame" Lisp object type and ! provide the generic and device-type-specific operations on frames (e.g. ! raising, lowering, resizing, moving, etc.). ! `window.c' ! `window.h' ! Each frame consists of one or more non-overlapping "windows" (better ! known as "panes" in standard window-system terminology) in which a ! buffer's text can be displayed. Windows can also have scrollbars ! displayed around their edges. ! `window.c' and `window.h' implement the "window" Lisp object type ! and provide code to manage windows. Since windows have no associated ! resources in the window system (the window system knows only about the ! frame; no child windows or anything are used for XEmacs windows), there ! is no device-type-specific code here; all of that code is part of the ! redisplay mechanism or the code for particular object types such as ! scrollbars.  ! File: internals.info, Node: The Redisplay Mechanism, Next: Extents, Prev: Consoles; Devices; Frames; Windows, Up: Top ! 27 The Redisplay Mechanism ! ************************** ! The redisplay mechanism is one of the most complicated sections of ! XEmacs, especially from a conceptual standpoint. This is doubly so ! because, unlike for the basic aspects of the Lisp interpreter, the ! computer science theories of how to efficiently handle redisplay are not ! well-developed. ! When working with the redisplay mechanism, remember the Golden Rules ! of Redisplay: ! 1. It Is Better To Be Correct Than Fast. ! 2. Thou Shalt Not Run Elisp From Within Redisplay. ! 3. It Is Better To Be Fast Than Not To Be. ! * Menu: ! * Critical Redisplay Sections:: ! * Line Start Cache:: ! * Redisplay Piece by Piece:: ! * Modules for the Redisplay Mechanism:: ! * Modules for other Display-Related Lisp Objects:: !  ! File: internals.info, Node: Critical Redisplay Sections, Next: Line Start Cache, Prev: The Redisplay Mechanism, Up: The Redisplay Mechanism ! 27.1 Critical Redisplay Sections ! ================================ ! *The following paragraphs are way out-of-date and inaccurate.* ! Within this section, we are defenseless and assume that the ! following cannot happen: ! 1. garbage collection ! 2. Lisp code evaluation ! 3. frame size changes ! We ensure (3) by calling `hold_frame_size_changes()', which will ! cause any pending frame size changes to get put on hold till after the ! end of the critical section. (1) follows automatically if (2) is met. ! #### Unfortunately, there are some places where Lisp code can be called ! within this section. We need to remove them. ! If `Fsignal()' is called during this critical section, we will ! `abort()'. ! If garbage collection is called during this critical section, we ! simply return. #### We should abort instead. ! #### If a frame-size change does occur we should probably actually ! be preempting redisplay. ! *Begin up-to-date stuff* ! 27.1.1 Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT ! ------------------------------------------------------------------------- ! These are now fixed as of November 10, 2004. ! Crash - reentrant `regenerate_window()' ! --------------------------------------- ! Here is a crash I (ben) just got - November 9, 2004: It can sort of be ! reproduced by creating a bunch of frames, opening a bunch of large ! files (which may be fontlocking for awhile). and immediately start ! Alt-TAB-ing back and forth quickly and constantly scrolling up and down ! using the scrolling dial on your mouse. ! Fatal error: assertion failed, file c:\xemacs\build\src\redisplay.c, line 5532, ! !dy->locked ! C backtrace: ! assert_failed(const char * 0x012a4ff0 `string', int 5532, const char * 0x0127bea4 `string') line 3839 ! Dynarr_verify_mod_1(void * 0x023ad2b0, const char * 0x012a4ff0 `string', int 5532) line 1306 + 36 bytes ! regenerate_window(window * 0x02f2ca88, long 40372, long 40372, int 2) line 5532 + 25 bytes ! update_line_start_cache(window * 0x02f2ca88, long 40372, long 40401, long 40372, int 0) line 8543 + 19 bytes ! point_in_line_start_cache(window * 0x02f2ca88, long 40372, int 0) line 7850 + 23 bytes ! start_end_of_last_line(window * 0x02f2ca88, long 40372, int 1, int 1) line 8121 + 15 bytes ! end_of_last_line_may_error(window * 0x02f2ca88, long 40372) line 8203 + 17 bytes ! pixel_to_glyph_translation(frame * 0x02f2c900, int 291, int 317, int * 0x0082bb04, int * 0x0082bb00, int * 0x0082bafc, int * 0x0082baf8, window * * 0x0082bae8, long * 0x0082baf4, long * 0x0082baf0, long * 0x0082baec, long * 0x0082bb10, long * 0x0082bb0c) line 9336 + 32 bytes ! mswindows_handle_mousewheel_event(long 49465600, int 0, int -240, tagPOINTS {...}) line 360 + 82 bytes ! mswindows_wnd_proc(HWND__ * 0x00260a42, unsigned int 522, unsigned int 4279238656, long 29885130) line 3561 + 36 bytes ! intercepted_wnd_proc(HWND__ * 0x00260a42, unsigned int 522, unsigned int 4279238656, long 29885130) line 2376 ! USER32! 77e11ef0() ! USER32! 77e1204c() ! USER32! 77e121af() ! mswindows_drain_windows_queue(int 0) line 1330 + 9 bytes ! emacs_mswindows_drain_queue() line 1339 + 7 bytes ! event_stream_drain_queue() line 1785 ! event_stream_quit_p() line 1893 ! check_quit() line 938 ! check_what_happened() line 459 ! internal_equal(long 22180468, long 22180468, int 0) line 2823 + 14 bytes ! update_image_instance(long 83498640, long 22180468) line 2121 + 18 bytes ! image_instantiate(long 21418616, long 20663624, long 54932896, long 22180468, long 3) line 3403 + 13 bytes ! va_call_trapping_problems_1(void * 0x0082cf94) line 5220 + 221 bytes ! call_trapping_problems_2(long 83160440) line 4867 + 13 bytes ! call_with_condition_handler(long (long, long, long)* 0x010cc4c0 flagged_a_squirmer(long, long, long), long 83160440, long (long)* 0x010cc440 call_trapping_problems_2(long), long 83160440) line 2129 + 7 bytes ! call_trapping_problems_1(long 83160440) line 4874 + 23 bytes ! internal_catch(long 21399864, long (long)* 0x010cc490 call_trapping_problems_1(long), long 83160440, int * volatile 0x0082ce4c, long * volatile 0x0082ce54) line 1527 + 7 bytes ! call_trapping_problems(long 20908160, const char * 0x00000000, int 98315, call_trapping_problems_result * 0x00000000, long (void *)* 0x010cca30 va_call_trapping_problems_1(void *), void * 0x0082cf94) line 5147 + 32 bytes ! call_with_suspended_errors(long (void)* 0x011448c0 image_instantiate(long, long, long, long, long), long 20663624, long 20908160, _error_behavior_struct_ {...}, int 5) line 5314 + 26 bytes ! specifier_instance_from_inst_list(long 21418616, long 20663624, long 54932896, long 21673760, _error_behavior_struct_ {...}, int 1, long 3) line 2501 + 54 bytes ! specifier_instance(long 21418616, long 20663624, long 54932896, _error_behavior_struct_ {...}, int 1, int 0, long 3) line 2614 + 64 bytes ! glyph_image_instance(long 22692176, long 54932896, _error_behavior_struct_ {...}, int 1) line 3955 + 31 bytes ! add_glyph_rune(position_redisplay_data_type * 0x0082d52c, glyph_block * 0x0082d454, int 0, int 0, glyph_cachel * 0x04f4e518) line 1972 + 26 bytes ! create_text_block(window * 0x034635a0, display_line * 0x033bfb28, long 29860, prop_block_dynarr * * 0x0082d7b8, int 2) line 2827 + 30 bytes ! generate_display_line(window * 0x034635a0, display_line * 0x033bfb28, int 1, long 29860, prop_block_dynarr * * 0x0082d7b8, int 2) line 979 + 38 bytes ! regenerate_window(window * 0x034635a0, long 29860, long 25012, int 2) line 5607 + 30 bytes ! update_line_start_cache(window * 0x034635a0, long 25012, long 28767, long 25012, int 0) line 8614 + 19 bytes ! point_in_line_start_cache(window * 0x034635a0, long 25012, int 0) line 7850 + 23 bytes ! start_end_of_last_line(window * 0x034635a0, long 25012, int 1, int 0) line 8121 + 15 bytes ! end_of_last_line(window * 0x034635a0, long 25012) line 8197 + 17 bytes ! Fwindow_end(long 54932896, long 20926544) line 1848 + 13 bytes ! Ffuncall(int 3, long * 0x0082dbb8) line 3841 + 93 bytes ! execute_optimized_program(const unsigned char * 0x032ceee8, int 7, long * 0x03289f40) line 823 + 16 bytes ! funcall_compiled_function(long 52991916, int 1, long * 0x0082dfb0) line 3454 + 85 bytes ! Ffuncall(int 2, long * 0x0082dfac) line 3880 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02f667d8, int 6, long * 0x01558748) line 823 + 16 bytes ! funcall_compiled_function(long 22579576, int 3, long * 0x0082e3ac) line 3454 + 85 bytes ! Ffuncall(int 4, long * 0x0082e3a8) line 3880 + 17 bytes ! execute_optimized_program(const unsigned char * 0x03209c98, int 5, long * 0x03288c68) line 823 + 16 bytes ! funcall_compiled_function(long 51656320, int 1, long * 0x0082e7a4) line 3454 + 85 bytes ! Ffuncall(int 2, long * 0x0082e7a0) line 3880 + 17 bytes ! execute_optimized_program(const unsigned char * 0x0082e9ec, int 4, long * 0x03224990) line 823 + 16 bytes ! Fbyte_code(long 37927380, long 52578688, long 9) line 2564 + 70 bytes ! Feval(long 51505420) line 3601 + 187 bytes ! internal_catch(long 51959412, long (long)* 0x010c6f40 Feval(long), long 51505420, int * volatile 0x00000000, long * volatile 0x00000000) line 1527 + 7 bytes ! execute_rare_opcode(long * 0x0082eee8, const unsigned char * 0x03248365, Opcode Bcatch) line 1380 + 24 bytes ! execute_optimized_program(const unsigned char * 0x03248340, int 2, long * 0x02f3c0a0) line 715 + 17 bytes ! funcall_compiled_function(long 51656276, int 0, long * 0x0082f444) line 3454 + 85 bytes ! Ffuncall(int 1, long * 0x0082f440) line 3880 + 17 bytes ! run_hook_with_args_in_buffer(buffer * 0x04ee9060, int 1, long * 0x0082f440, run_hooks_condition RUN_HOOKS_TO_COMPLETION) line 4361 + 13 bytes ! run_hook_with_args(int 1, long * 0x0082f440, run_hooks_condition RUN_HOOKS_TO_COMPLETION) line 4374 + 23 bytes ! run_hook(long 51959028) line 4443 + 13 bytes ! safe_run_hook_trapping_problems_1(void * 0x013c73c0) line 5517 + 9 bytes ! call_trapping_problems_2(long 83157920) line 4867 + 13 bytes ! call_with_condition_handler(long (long, long, long)* 0x010cc4c0 flagged_a_squirmer(long, long, long), long 83157920, long (long)* 0x010cc440 call_trapping_problems_2(long), long 83157920) line 2129 + 7 bytes ! call_trapping_problems_1(long 83157920) line 4874 + 23 bytes ! internal_catch(long 21399864, long (long)* 0x010cc490 call_trapping_problems_1(long), long 83157920, int * volatile 0x0082f700, long * volatile 0x0082f708) line 1527 + 7 bytes ! call_trapping_problems(long 20925944, const char * 0x00000000, int 131235, call_trapping_problems_result * 0x0082f830, long (void *)* 0x010cd990 safe_run_hook_trapping_problems_1(void *), void * 0x013c73c0) line 5147 + 32 bytes ! safe_run_hook_trapping_problems(long 20741312, long 20739008, int 160) line 5543 + 36 bytes ! run_pre_idle_hook() line 2084 + 24 bytes ! redisplay() line 7224 ! Fnext_event(long 37363732, long 20928056) line 2263 ! Fcommand_loop_1() line 600 + 15 bytes ! command_loop_1(long 20928056) line 512 ! condition_case_1(long 20925944, long (long)* 0x01096a80 command_loop_1(long), long 20928056, long (long, long)* 0x01096630 cmd_error(long, long), long 20928056) line 1918 + 7 bytes ! command_loop_3() line 262 + 35 bytes ! command_loop_2(long 20928056) line 277 ! internal_catch(long 20683712, long (long)* 0x010967a0 command_loop_2(long), long 20928056, int * volatile 0x00000000, long * volatile 0x00000000) line 1527 + 7 bytes ! initial_command_loop(long 20928056) line 313 + 28 bytes ! xemacs_21_5_b18_i586_pc_win32(int 1, unsigned short * * 0x0082fed0, unsigned short * * 0x00000000, int 0) line 2551 ! main(int 1, char * * 0x00e52610, char * * 0x00e52bb0) line 2992 ! mainCRTStartup() line 338 + 17 bytes ! KERNEL32! 7c59893d() ! Lisp backtrace: ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! window-end(#" 0x5e4a> t) ! # (unwind-protect ...) ! # bind (buffer we-are-screwed check-text-props window) ! lazy-lock-fontify-window(#" 0x5e4a>) ! # bind (walk-windows-current walk-windows-start arg which-devices which-frames ! minibuf function) ! walk-windows(lazy-lock-fontify-window no-minibuf #) ! # (unwind-protect ...) ! # bind (ssf65112 tick frame) ! lazy-lock-maybe-fontify-frame(#) ! # bind (frame starting-frame) ! byte-code("..." [starting-frame frame selected-frame frame-visible-p frame-min ! ibuffer-only-p next-frame visible-nomini throw lazy-lock-frame-loop-done t lazy- ! lock-maybe-fontify-frame] 4) ! # (catch lazy-lock-frame-loop-done ...) ! lazy-lock-pre-idle-fontify-windows() ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! (next-event "[internal]") ! # (condition-case ... . error) ! # (catch top-level ...) ! Another Lisp trace of a similar situation (C stack trace not available): ! ........................................................................ ! Fatal error: assertion failed, file c:\xemacs\build\src\redisplay.c, line 5532, ! !dy->locked ! Lisp backtrace follows: ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! scrollbar-page-down((#)) ! (dispatch-event "[internal]") ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! window-end(# t) ! # (unwind-protect ...) ! # bind (buffer we-are-screwed check-text-props window) ! lazy-lock-fontify-window(#) ! # bind (walk-windows-current walk-windows-start arg which-devices which-frames ! minibuf function) ! walk-windows(lazy-lock-fontify-window no-minibuf #) ! # (unwind-protect ...) ! # bind (ssf65112 tick frame) ! lazy-lock-maybe-fontify-frame(#) ! # bind (frame starting-frame) ! byte-code("..." [starting-frame frame selected-frame frame-visible-p frame-min ! ibuffer-only-p next-frame visible-nomini throw lazy-lock-frame-loop-done t lazy- ! lock-maybe-fontify-frame] 4) ! # (catch lazy-lock-frame-loop-done ...) ! lazy-lock-pre-idle-fontify-windows() ! # (unwind-protect ...) ! # (catch # ...) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! # (unwind-protect ...) ! # (unwind-protect ...) ! # bind (inhibit-quit) ! (next-event "[internal]") ! # (condition-case ... . error) ! # (catch top-level ...) ! Crash - reentrant `generate_displayable_area()' ! ----------------------------------------------- ! Original code said [Tricky tricky tricky. ! `generate_displayable_area()' can (could) be called reentrantly, and ! redisplay is not prepared to handle this:]. ! assert_failed(const char * 0x0129c8c8 `string', int 5328, const char ! * 0x01274068 `string') line 3620 Dynarr_verify_mod_1(void * 0x0250f228, ! const char * 0x0129c8c8 `string', int 5328) line 1256 + 36 bytes ! generate_displayable_area(window * 0x02480028, long 38776292, int 0, ! int 0, int 265, int 169, display_line_dynarr * 0x0250f228, long 0, int ! 2) line 5328 + 25 bytes output_gutter(frame * 0x0228ad90, gutter_pos ! TOP_GUTTER, int 1) line 409 + 69 bytes redraw_exposed_gutter(frame * ! 0x0228ad90, gutter_pos TOP_GUTTER, int 8, int 23, int 249, int 127) ! line 687 + 15 bytes redraw_exposed_gutters(frame * 0x0228ad90, int 8, ! int 23, int 249, int 127) line 703 + 29 bytes ! mswindows_redraw_exposed_area(frame * 0x0228ad90, int 8, int 23, int ! 249, int 127) line 862 + 25 bytes mswindows_handle_paint(frame * ! 0x0228ad90) line 2176 + 25 bytes mswindows_wnd_proc(HWND__ * ! 0x001003e2, unsigned int 15, unsigned int 0, long 0) line 3233 + 45 ! bytes intercepted_wnd_proc(HWND__ * 0x001003e2, unsigned int 15, ! unsigned int 0, long 0) line 2488 USER32! 77e3a244() USER32! 77e14730() ! USER32! 77e1558a() NTDLL! KiUserCallbackDispatcher@12 + 19 bytes ! USER32! 77e14680() USER32! 77e1a792() qxeIsDialogMessage(HWND__ * ! 0x001003e2, tagMSG * 0x0082a93c {msg=0x0000000f wp=0x00000000 ! lp=0x00000000}) line 2298 + 14 bytes mswindows_is_dialog_msg(tagMSG * ! 0x0082a93c {msg=0x0000000f wp=0x00000000 lp=0x00000000}) line 165 + 13 ! bytes mswindows_drain_windows_queue(int 0) line 1282 + 9 bytes ! emacs_mswindows_drain_queue() line 1326 + 7 bytes ! event_stream_drain_queue() line 1887 event_stream_quit_p() line 1992 ! check_quit() line 993 unbind_to_hairy(int 35) line 5963 unbind_to_1(int ! 35, long 20888208) line 5945 + 200 bytes ! specifier_instance_from_inst_list(long 21379344, long 38135616, long ! 36220304, long 20888208, _error_behavior_struct_ {...}, int 1, long 3) ! line 2522 + 16 bytes specifier_instance(long 21379344, long 38135616, ! long 36220304, _error_behavior_struct_ {...}, int 1, int 0, long 3) ! line 2625 + 65 bytes specifier_instance_no_quit(long 21379344, long ! 38135616, long 36220304, _error_behavior_struct_ {...}, int 0, long 1) ! line 2658 + 31 bytes face_property_matching_instance(long 22612340, ! long 20860632, long 22530956, long 36220304, _error_behavior_struct_ ! {...}, int 0, long 1) line 565 + 48 bytes ! ensure_face_cachel_contains_charset(face_cachel * 0x0082b014, long ! 36220304, long 22530956) line 1104 + 35 bytes ! update_face_cachel_data(face_cachel * 0x0082b014, long 36220304, long ! 22612340) line 1304 + 19 bytes query_string_geometry(long 21110576, ! long 22612340, int * 0x00000000, int * 0x0082b5b4, int * 0x00000000, ! long 38852960) line 2370 + 23 bytes ! mswindows_widget_query_string_geometry(long 21110576, long 22612340, ! int * 0x0082b5b8, int * 0x0082b5b4, long 38852960) line 2914 + 25 bytes ! widget_query_string_geometry(long 21110576, long 22612340, int * ! 0x0082b5b8, int * 0x0082b5b4, long 38852960) line 514 + 32 bytes ! edit_field_query_geometry(long 38857648, int * 0x0082b7b4, int * ! 0x0082b7b8, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long ! 38852960) line 920 + 390 bytes widget_query_geometry(long 38857648, int ! * 0x0082b7b4, int * 0x0082b7b8, image_instance_geometry ! IMAGE_DESIRED_GEOMETRY, long 38852960) line 567 + 26 bytes ! image_instance_query_geometry(long 38857648, int * 0x0082b7b4, int * ! 0x0082b7b8, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long ! 38852960) line 2015 + 26 bytes glyph_query_geometry(long 38853384, int ! * 0x0082b7b4, int * 0x0082b7b8, image_instance_geometry ! IMAGE_DESIRED_GEOMETRY, long 38852960) line 4197 + 25 bytes ! layout_query_geometry(long 38852960, int * 0x0082b9cc, int * ! 0x0082b9d0, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long ! 38404624) line 1351 + 25 bytes widget_query_geometry(long 38852960, int ! * 0x0082b9cc, int * 0x0082b9d0, image_instance_geometry ! IMAGE_DESIRED_GEOMETRY, long 38404624) line 567 + 26 bytes ! image_instance_query_geometry(long 38852960, int * 0x0082b9cc, int * ! 0x0082b9d0, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long ! 38404624) line 2015 + 26 bytes glyph_query_geometry(long 38537976, int ! * 0x0082b9cc, int * 0x0082b9d0, image_instance_geometry ! IMAGE_DESIRED_GEOMETRY, long 38404624) line 4197 + 25 bytes ! layout_layout(long 38404624, int 265, int 156, int -2, int -2, long ! 38273064) line 1468 + 23 bytes widget_layout(long 38404624, int 265, ! int 156, int -2, int -2, long 38273064) line 626 + 30 bytes ! image_instance_layout(long 38404624, int 265, int 156, int -2, int -2, ! long 38273064) line 2102 + 51 bytes glyph_ascent(long 38404624, long ! 38273064) line 4009 + 21 bytes update_glyph_cachel_data(window * ! 0x02480028, long 36201168, glyph_cachel * 0x0248c3d8) line 4272 + 13 ! bytes get_glyph_cachel_index(window * 0x02480028, long 36201168) line ! 4306 + 17 bytes add_glyph_rune(position_redisplay_data_type * ! 0x0082bf2c, glyph_block * 0x024bd028, int 0, int 0, glyph_cachel * ! 0x00000000) line 1800 + 15 bytes ! add_glyph_runes(position_redisplay_data_type * 0x0082bf2c, int 0) line ! 2085 + 31 bytes create_string_text_block(window * 0x02480028, long ! 38776292, display_line * 0x02514500, long 0, prop_block_dynarr * * ! 0x0082c13c, int 2) line 4907 + 14 bytes ! generate_string_display_line(window * 0x02480028, long 38776292, ! display_line * 0x02514500, long 0, prop_block_dynarr * * 0x0082c13c, ! int 2) line 5293 + 29 bytes generate_displayable_area(window * ! 0x02480028, long 38776292, int 0, int 0, int 265, int 169, ! display_line_dynarr * 0x0250f228, long 0, int 2) line 5372 + 29 bytes ! output_gutter(frame * 0x0228ad90, gutter_pos TOP_GUTTER, int 0) line ! 409 + 69 bytes update_frame_gutters(frame * 0x0228ad90) line 639 + 15 ! bytes redisplay_frame(frame * 0x0228ad90, int 1) line 6792 + 9 bytes ! redisplay_device(device * 0x0171df00, int 1) line 6911 + 11 bytes ! redisplay_without_hooks() line 6957 + 11 bytes ! redisplay_no_pre_idle_hook() line 7029 redisplay() line 7011 ! mswindows_wnd_proc(HWND__ * 0x001003e2, unsigned int 5, unsigned int 0, ! long 10223881) line 3424 intercepted_wnd_proc(HWND__ * 0x001003e2, ! unsigned int 5, unsigned int 0, long 10223881) line 2488 USER32! ! 77e3a244() USER32! 77e16362() USER32! 77e14c1a() USER32! 77e1dd30() ! mswindows_wnd_proc(HWND__ * 0x001003e2, unsigned int 71, unsigned int ! 0, long 8578308) line 3926 + 21 bytes intercepted_wnd_proc(HWND__ * ! 0x001003e2, unsigned int 71, unsigned int 0, long 8578308) line 2488 ! USER32! 77e3a244() USER32! 77e14730() USER32! 77e174b4() NTDLL! ! KiUserCallbackDispatcher@12 + 19 bytes mswindows_set_frame_size(frame * ! 0x0228ad90, int 265, int 156) line 355 internal_set_frame_size(frame * ! 0x0228ad90, int 265, int 156, int 0) line 2754 + 24 bytes ! Fset_frame_displayable_pixel_size(long 36220304, long 531, long 313, ! long 20888208) line 3004 + 32 bytes Ffuncall(int 4, long * 0x0082e778) ! line 3844 + 168 bytes execute_optimized_program(const unsigned char * ! 0x02286e48, int 40, long * 0x01529b80) line 609 + 16 bytes ! funcall_compiled_function(long 22433308, int 0, long * 0x0082ec08) line ! 3452 + 85 bytes Ffuncall(int 1, long * 0x0082ec04) line 3883 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02286d40, int 6, long ! * 0x01548ddc) line 609 + 16 bytes funcall_compiled_function(long ! 22505864, int 11, long * 0x0082f00c) line 3452 + 85 bytes Ffuncall(int ! 12, long * 0x0082f008) line 3883 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02503e38, int 47, ! long * 0x0152dc48) line 609 + 16 bytes funcall_compiled_function(long ! 22436784, int 0, long * 0x0082f534) line 3452 + 85 bytes Ffuncall(int ! 1, long * 0x0082f530) line 3883 + 17 bytes apply1(long 22436784, long ! 20888208) line 4458 + 11 bytes Fcall_interactively(long 20742816, long ! 20888208, long 20888208) line 460 + 13 bytes Ffuncall(int 2, long * ! 0x0082f8ec) line 3844 + 127 bytes call1(long 20854392, long 20742816) ! line 4489 + 11 bytes execute_command_event(command_builder * ! 0x01798f98, long 24439276) line 4198 + 69 bytes Fdispatch_event(long ! 24439276) line 4569 + 13 bytes Fcommand_loop_1() line 569 + 9 bytes ! command_loop_1(long 20888208) line 489 condition_case_1(long 20886024, ! long (long)* 0x010955a0 command_loop_1(long), long 20888208, long ! (long, long)* 0x01095150 cmd_error(long, long), long 20888208) line ! 1917 + 7 bytes command_loop_3() line 251 + 35 bytes command_loop_2(long ! 20888208) line 264 internal_catch(long 20650992, long (long)* ! 0x010952c0 command_loop_2(long), long 20888208, int * volatile ! 0x00000000, long * volatile 0x00000000) line 1527 + 7 bytes ! initial_command_loop(long 20888208) line 300 + 28 bytes ! xemacs_21_5_b10_i586_pc_win32(int 1, char * * 0x00e52620, char * * ! 0x00e52bb0, int 0) line 2356 main(int 1, char * * 0x00e52620, char * * ! 0x00e52bb0) line 2733 mainCRTStartup() line 338 + 17 bytes KERNEL32! ! 77ea847c() !  ! File: internals.info, Node: Line Start Cache, Next: Redisplay Piece by Piece, Prev: Critical Redisplay Sections, Up: The Redisplay Mechanism ! 27.2 Line Start Cache ! ===================== ! The traditional scrolling code in Emacs breaks in a variable height ! world. It depends on the key assumption that the number of lines that ! can be displayed at any given time is fixed. This led to a complete ! separation of the scrolling code from the redisplay code. In order to ! fully support variable height lines, the scrolling code must actually be ! tightly integrated with redisplay. Only redisplay can determine how ! many lines will be displayed on a screen for any given starting point. ! What is ideally wanted is a complete list of the starting buffer ! position for every possible display line of a buffer along with the ! height of that display line. Maintaining such a full list would be very ! expensive. We settle for having it include information for all areas ! which we happen to generate anyhow (i.e. the region currently being ! displayed) and for those areas we need to work with. ! In order to ensure that the cache accurately represents what ! redisplay would actually show, it is necessary to invalidate it in many ! situations. If the buffer changes, the starting positions may no longer ! be correct. If a face or an extent has changed then the line heights ! may have altered. These events happen frequently enough that the cache ! can end up being constantly disabled. With this potentially constant ! invalidation when is the cache ever useful? ! Even if the cache is invalidated before every single usage, it is ! necessary. Scrolling often requires knowledge about display lines which ! are actually above or below the visible region. The cache provides a ! convenient light-weight method of storing this information for multiple ! display regions. This knowledge is necessary for the scrolling code to ! always obey the First Golden Rule of Redisplay. ! If the cache already contains all of the information that the ! scrolling routines happen to need so that it doesn't have to go ! generate it, then we are able to obey the Third Golden Rule of ! Redisplay. The first thing we do to help out the cache is to always ! add the displayed region. This region had to be generated anyway, so ! the cache ends up getting the information basically for free. In those ! cases where a user is simply scrolling around viewing a buffer there is ! a high probability that this is sufficient to always provide the needed ! information. The second thing we can do is be smart about invalidating ! the cache. ! TODO--Be smart about invalidating the cache. Potential places: ! * Insertions at end-of-line which don't cause line-wraps do not ! alter the starting positions of any display lines. These types of ! buffer modifications should not invalidate the cache. This is ! actually a large optimization for redisplay speed as well. ! * Buffer modifications frequently only affect the display of lines ! at and below where they occur. In these situations we should only ! invalidate the part of the cache starting at where the ! modification occurs. ! In case you're wondering, the Second Golden Rule of Redisplay is not ! applicable. !  ! File: internals.info, Node: Redisplay Piece by Piece, Next: Modules for the Redisplay Mechanism, Prev: Line Start Cache, Up: The Redisplay Mechanism ! 27.3 Redisplay Piece by Piece ! ============================= ! ! As you can begin to see redisplay is complex and also not well ! documented. Chuck no longer works on XEmacs so this section is my take ! on the workings of redisplay. ! ! Redisplay happens in three phases: ! ! 1. Determine desired display in area that needs redisplay. ! Implemented by `redisplay.c' ! ! 2. Compare desired display with current display Implemented by ! `redisplay-output.c' ! ! 3. Output changes Implemented by `redisplay-output.c', ! `redisplay-x.c', `redisplay-msw.c' and `redisplay-tty.c' ! ! Steps 1 and 2 are device-independent and relatively complex. Step 3 ! is mostly device-dependent. ! ! Determining the desired display ! ! Display attributes are stored in `display_line' structures. Each ! `display_line' consists of a set of `display_block''s and each ! `display_block' contains a number of `rune''s. Generally dynarr's of ! `display_line''s are held by each window representing the current ! display and the desired display. ! ! The `display_line' structures are tightly tied to buffers which ! presents a problem for redisplay as this connection is bogus for the ! modeline. Hence the `display_line' generation routines are duplicated ! for generating the modeline. This means that the modeline display code ! has many bugs that the standard redisplay code does not. ! ! The guts of `display_line' generation are in `create_text_block', ! which creates a single display line for the desired locale. This ! incrementally parses the characters on the current line and generates ! redisplay structures for each. ! ! Gutter redisplay is different. Because the data to display is stored ! in a string we cannot use `create_text_block'. Instead we use ! `create_text_string_block' which performs the same function as ! `create_text_block' but for strings. Many of the complexities of ! `create_text_block' to do with cursor handling and selective display ! have been removed. ! !  ! File: internals.info, Node: Modules for the Redisplay Mechanism, Next: Modules for other Display-Related Lisp Objects, Prev: Redisplay Piece by Piece, Up: The Redisplay Mechanism ! ! 27.4 Modules for the Redisplay Mechanism ! ======================================== ! ! `redisplay-output.c' ! `redisplay-msw.c' ! `redisplay-tty.c' ! `redisplay-x.c' ! `redisplay.c' ! `redisplay.h' ! ! These files provide the redisplay mechanism. As with many other ! subsystems in XEmacs, there is a clean separation between the general ! and device-specific support. ! ! `redisplay.c' contains the bulk of the redisplay engine. These ! functions update the redisplay structures (which describe how the screen ! is to appear) to reflect any changes made to the state of any ! displayable objects (buffer, frame, window, etc.) since the last time ! that redisplay was called. These functions are highly optimized to ! avoid doing more work than necessary (since redisplay is called ! extremely often and is potentially a huge time sink), and depend heavily ! on notifications from the objects themselves that changes have occurred, ! so that redisplay doesn't explicitly have to check each possible object. ! The redisplay mechanism also contains a great deal of caching to further ! speed things up; some of this caching is contained within the various ! displayable objects. ! ! `redisplay-output.c' goes through the redisplay structures and ! converts them into calls to device-specific methods to actually output ! the screen changes. ! ! `redisplay-x.c' and `redisplay-tty.c' are two implementations of ! these redisplay output methods, for X frames and TTY frames, ! respectively. ! ! `indent.c' ! ! This module contains various functions and Lisp primitives for ! converting between buffer positions and screen positions. These ! functions call the redisplay mechanism to do most of the work, and then ! examine the redisplay structures to get the necessary information. This ! module needs work. ! ! `termcap.c' ! `terminfo.c' ! `tparam.c' ! ! These files contain functions for working with the termcap ! (BSD-style) and terminfo (System V style) databases of terminal ! capabilities and escape sequences, used when XEmacs is displaying in a ! TTY. ! ! `cm.c' ! `cm.h' ! ! These files provide some miscellaneous TTY-output functions and ! should probably be merged into `redisplay-tty.c'. ! !  ! File: internals.info, Node: Modules for other Display-Related Lisp Objects, Prev: Modules for the Redisplay Mechanism, Up: The Redisplay Mechanism ! ! 27.5 Modules for other Display-Related Lisp Objects ! =================================================== ! ! `faces.c' ! `faces.h' ! ! `bitmaps.h' ! `glyphs-eimage.c' ! `glyphs-msw.c' ! `glyphs-msw.h' ! `glyphs-widget.c' ! `glyphs-x.c' ! `glyphs-x.h' ! `glyphs.c' ! `glyphs.h' ! ! `objects-msw.c' ! `objects-msw.h' ! `objects-tty.c' ! `objects-tty.h' ! `objects-x.c' ! `objects-x.h' ! `objects.c' ! `objects.h' ! ! `menubar-msw.c' ! `menubar-msw.h' ! `menubar-x.c' ! `menubar.c' ! `menubar.h' ! ! `scrollbar-msw.c' ! `scrollbar-msw.h' ! `scrollbar-x.c' ! `scrollbar-x.h' ! `scrollbar.c' ! `scrollbar.h' ! ! `toolbar-msw.c' ! `toolbar-x.c' ! `toolbar.c' ! `toolbar.h' ! ! `font-lock.c' ! ! This file provides C support for syntax highlighting--i.e. ! highlighting different syntactic constructs of a source file in ! different colors, for easy reading. The C support is provided so that ! this is fast. ! ! `dgif_lib.c' ! `gif_err.c' ! `gif_lib.h' ! `gifalloc.c' ! ! These modules decode GIF-format image files, for use with glyphs. ! These files were removed due to Unisys patent infringement concerns. ! !  ! File: internals.info, Node: Extents, Next: Faces, Prev: The Redisplay Mechanism, Up: Top ! ! 28 Extents ! ********** ! ! * Menu: ! ! * Introduction to Extents:: Extents are ranges over text, with properties. ! * Extent Ordering:: How extents are ordered internally. ! * Format of the Extent Info:: The extent information in a buffer or string. ! * Zero-Length Extents:: A weird special case. ! * Mathematics of Extent Ordering:: A rigorous foundation. ! * Extent Fragments:: Cached information useful for redisplay. ! !  ! File: internals.info, Node: Introduction to Extents, Next: Extent Ordering, Prev: Extents, Up: Extents ! ! 28.1 Introduction to Extents ! ============================ ! ! Extents are regions over a buffer, with a start and an end position ! denoting the region of the buffer included in the extent. In addition, ! either end can be closed or open, meaning that the endpoint is or is ! not logically included in the extent. Insertion of a character at a ! closed endpoint causes the character to go inside the extent; insertion ! at an open endpoint causes the character to go outside. ! ! Extent endpoints are stored using memory indices (see `insdel.c'), ! to minimize the amount of adjusting that needs to be done when ! characters are inserted or deleted. ! ! (Formerly, extent endpoints at the gap could be either before or ! after the gap, depending on the open/closedness of the endpoint. The ! intent of this was to make it so that insertions would automatically go ! inside or out of extents as necessary with no further work needing to ! be done. It didn't work out that way, however, and just ended up ! complexifying and buggifying all the rest of the code.) ! !  ! File: internals.info, Node: Extent Ordering, Next: Format of the Extent Info, Prev: Introduction to Extents, Up: Extents ! ! 28.2 Extent Ordering ! ==================== ! ! Extents are compared using memory indices. There are two orderings for ! extents and both orders are kept current at all times. The normal or ! "display" order is as follows: ! ! Extent A is ``less than'' extent B, ! that is, earlier in the display order, ! if: A-start < B-start, ! or if: A-start = B-start, and A-end > B-end ! ! So if two extents begin at the same position, the larger of them is ! the earlier one in the display order (`EXTENT_LESS' is true). ! ! For the e-order, the same thing holds: ! ! Extent A is ``less than'' extent B in e-order, ! that is, later in the buffer, ! if: A-end < B-end, ! or if: A-end = B-end, and A-start > B-start ! ! So if two extents end at the same position, the smaller of them is ! the earlier one in the e-order (`EXTENT_E_LESS' is true). ! ! The display order and the e-order are complementary orders: any ! theorem about the display order also applies to the e-order if you swap ! all occurrences of "display order" and "e-order", "less than" and ! "greater than", and "extent start" and "extent end". ! !  ! File: internals.info, Node: Format of the Extent Info, Next: Zero-Length Extents, Prev: Extent Ordering, Up: Extents ! ! 28.3 Format of the Extent Info ! ============================== ! ! An extent-info structure consists of a list of the buffer or string's ! extents and a "stack of extents" that lists all of the extents over a ! particular position. The stack-of-extents info is used for ! optimization purposes--it basically caches some info that might be ! expensive to compute. Certain otherwise hard computations are easy ! given the stack of extents over a particular position, and if the stack ! of extents over a nearby position is known (because it was calculated ! at some prior point in time), it's easy to move the stack of extents to ! the proper position. ! ! Given that the stack of extents is an optimization, and given that ! it requires memory, a string's stack of extents is wiped out each time ! a garbage collection occurs. Therefore, any time you retrieve the ! stack of extents, it might not be there. If you need it to be there, ! use the `_force' version. ! ! Similarly, a string may or may not have an extent_info structure. ! (Generally it won't if there haven't been any extents added to the ! string.) So use the `_force' version if you need the extent_info ! structure to be there. ! ! A list of extents is maintained as a double gap array. One gap array ! is ordered by start index (the "display order") and the other is ! ordered by end index (the "e-order"). Note that positions in an extent ! list should logically be conceived of as referring _to_ a particular ! extent (as is the norm in programs) rather than sitting between two ! extents. Note also that callers of these functions should not be aware ! of the fact that the extent list is implemented as an array, except for ! the fact that positions are integers (this should be generalized to ! handle integers and linked list equally well). ! ! A gap array is the same structure used by buffer text: an array of ! elements with a "gap" somewhere in the middle. Insertion and deletion ! happens by moving the gap to the insertion/deletion point, and then ! expanding/contracting as necessary. Gap arrays have a number of useful ! properties: ! ! 1. They are space efficient, as there is no need for next/previous ! pointers. ! ! 2. If the items in them are sorted, locating an item is fast - O(log ! N). ! ! 3. Insertion and deletion is very fast (constant time, essentially) ! if the gap is near (which favors localized operations, as will ! usually be the case). Even if not, it requires only a block move ! of memory, which is generally a highly optimized operation on ! modern processors. ! ! 4. Code to manipulate them is relatively simple to write. ! ! An alternative would be balanced binary trees, which have guaranteed ! O(log N) time for all operations (although the constant factors are not ! as good, and repeated localized operations will be slower than for a ! gap array). Such code is quite tricky to write, however. ! !  ! File: internals.info, Node: Zero-Length Extents, Next: Mathematics of Extent Ordering, Prev: Format of the Extent Info, Up: Extents ! ! 28.4 Zero-Length Extents ! ======================== ! ! Extents can be zero-length, and will end up that way if their endpoints ! are explicitly set that way or if their detachable property is `nil' ! and all the text in the extent is deleted. (The exception is open-open ! zero-length extents, which are barred from existing because there is no ! sensible way to define their properties. Deletion of the text in an ! open-open extent causes it to be converted into a closed-open extent.) ! Zero-length extents are primarily used to represent annotations, and ! behave as follows: ! ! 1. Insertion at the position of a zero-length extent expands the ! extent if both endpoints are closed; goes after the extent if it ! is closed-open; and goes before the extent if it is open-closed. ! ! 2. Deletion of a character on a side of a zero-length extent whose ! corresponding endpoint is closed causes the extent to be detached ! if it is detachable; if the extent is not detachable or the ! corresponding endpoint is open, the extent remains in the buffer, ! moving as necessary. ! ! Note that closed-open, non-detachable zero-length extents behave ! exactly like markers and that open-closed, non-detachable zero-length ! extents behave like the "point-type" marker in Mule. ! !  ! File: internals.info, Node: Mathematics of Extent Ordering, Next: Extent Fragments, Prev: Zero-Length Extents, Up: Extents ! ! 28.5 Mathematics of Extent Ordering ! =================================== ! ! The extents in a buffer are ordered by "display order" because that is ! that order that the redisplay mechanism needs to process them in. The ! e-order is an auxiliary ordering used to facilitate operations over ! extents. The operations that can be performed on the ordered list of ! extents in a buffer are ! ! 1. Locate where an extent would go if inserted into the list. ! ! 2. Insert an extent into the list. ! ! 3. Remove an extent from the list. ! ! 4. Map over all the extents that overlap a range. ! ! (4) requires being able to determine the first and last extents that ! overlap a range. ! ! NOTE: "overlap" is used as follows: ! ! * two ranges overlap if they have at least one point in common. ! Whether the endpoints are open or closed makes a difference here. ! ! * a point overlaps a range if the point is contained within the ! range; this is equivalent to treating a point P as the range [P, ! P]. ! ! * In the case of an _extent_ overlapping a point or range, the extent ! is normally treated as having closed endpoints. This applies ! consistently in the discussion of stacks of extents and such below. ! Note that this definition of overlap is not necessarily consistent ! with the extents that `map-extents' maps over, since `map-extents' ! sometimes pays attention to whether the endpoints of an extents ! are open or closed. But for our purposes, it greatly simplifies ! things to treat all extents as having closed endpoints. ! ! First, define >, <, <=, etc. as applied to extents to mean ! comparison according to the display order. Comparison between an ! extent E and an index I means comparison between E and the range [I, I]. ! ! Also define e>, e<, e<=, etc. to mean comparison according to the ! e-order. ! ! For any range R, define R(0) to be the starting index of the range ! and R(1) to be the ending index of the range. ! ! For any extent E, define E(next) to be the extent directly following ! E, and E(prev) to be the extent directly preceding E. Assume E(next) ! and E(prev) can be determined from E in constant time. (This is ! because we store the extent list as a doubly linked list.) ! ! Similarly, define E(e-next) and E(e-prev) to be the extents directly ! following and preceding E in the e-order. ! ! Now: ! ! Let R be a range. Let F be the first extent overlapping R. Let L ! be the last extent overlapping R. ! ! Theorem 1: R(1) lies between L and L(next), i.e. L <= R(1) < L(next). ! ! This follows easily from the definition of display order. The basic ! reason that this theorem applies is that the display order sorts by ! increasing starting index. ! ! Therefore, we can determine L just by looking at where we would ! insert R(1) into the list, and if we know F and are moving forward over ! extents, we can easily determine when we've hit L by comparing the ! extent we're at to R(1). ! ! Theorem 2: F(e-prev) e< [1, R(0)] e<= F. ! ! This is the analog of Theorem 1, and applies because the e-order ! sorts by increasing ending index. ! ! Therefore, F can be found in the same amount of time as operation ! (1), i.e. the time that it takes to locate where an extent would go if ! inserted into the e-order list. This is O(log N), since we are using ! gap arrays to manage extents. ! ! Define a "stack of extents" (or "SOE") as the set of extents ! (ordered in display order and e-order, just like for normal extent ! lists) that overlap an index I. ! ! Now: ! ! Let I be an index, let S be the stack of extents on I and let F be ! the first extent in S. ! ! Theorem 3: The first extent in S is the first extent that overlaps ! any range [I, J]. ! ! Proof: Any extent that overlaps [I, J] but does not include I must ! have a start index > I, and thus be greater than any extent in S. ! ! Therefore, finding the first extent that overlaps a range R is the ! same as finding the first extent that overlaps R(0). ! ! Theorem 4: Let I2 be an index such that I2 > I, and let F2 be the ! first extent that overlaps I2. Then, either F2 is in S or F2 is ! greater than any extent in S. ! ! Proof: If F2 does not include I then its start index is greater than ! I and thus it is greater than any extent in S, including F. Otherwise, ! F2 includes I and thus is in S, and thus F2 >= F. ! !  ! File: internals.info, Node: Extent Fragments, Prev: Mathematics of Extent Ordering, Up: Extents ! ! 28.6 Extent Fragments ! ===================== ! ! Imagine that the buffer is divided up into contiguous, non-overlapping ! "runs" of text such that no extent starts or ends within a run (extents ! that abut the run don't count). ! ! An extent fragment is a structure that holds data about the run that ! contains a particular buffer position (if the buffer position is at the ! junction of two runs, the run after the position is used)--the ! beginning and end of the run, a list of all of the extents in that run, ! the "merged face" that results from merging all of the faces ! corresponding to those extents, the begin and end glyphs at the ! beginning of the run, etc. This is the information that redisplay needs ! in order to display this run. ! ! Extent fragments have to be very quick to update to a new buffer ! position when moving linearly through the buffer. They rely on the ! stack-of-extents code, which does the heavy-duty algorithmic work of ! determining which extents overly a particular position. ! !  ! File: internals.info, Node: Faces, Next: Glyphs, Prev: Extents, Up: Top ! ! 29 Faces ! ******** ! ! Not yet documented. ! !  ! File: internals.info, Node: Glyphs, Next: Specifiers, Prev: Faces, Up: Top ! ! 30 Glyphs ! ********* ! ! Glyphs are graphical elements that can be displayed in XEmacs buffers or ! gutters. We use the term graphical element here in the broadest possible ! sense since glyphs can be as mundane as text or as arcane as a native ! tab widget. ! ! In XEmacs, glyphs represent the uninstantiated state of graphical ! elements, i.e. they hold all the information necessary to produce an ! image on-screen but the image need not exist at this stage, and multiple ! screen images can be instantiated from a single glyph. ! ! Glyphs are lazily instantiated by calling one of the glyph ! functions. This usually occurs within redisplay when `Fglyph_height' is ! called. Instantiation causes an image-instance to be created and ! cached. This cache is on a per-device basis for all glyphs except ! widget-glyphs, and on a per-window basis for widgets-glyphs. The ! caching is done by `image_instantiate' and is necessary because it is ! generally possible to display an image-instance in multiple domains. ! For instance if we create a Pixmap, we can actually display this on ! multiple windows - even though we only need a single Pixmap instance to ! do this. If caching wasn't done then it would be necessary to create ! image-instances for every displayable occurrence of a glyph - and every ! usage - and this would be extremely memory and cpu intensive. ! ! Widget-glyphs (a.k.a native widgets) are not cached in this way. ! This is because widget-glyph image-instances on screen are toolkit ! windows, and thus cannot be reused in multiple XEmacs domains. Thus ! widget-glyphs are cached on an XEmacs window basis. ! ! Any action on a glyph first consults the cache before actually ! instantiating a widget. ! ! 30.1 Glyph Instantiation ! ======================== ! ! Glyph instantiation is a hairy topic and requires some explanation. The ! guts of glyph instantiation is contained within `image_instantiate'. A ! glyph contains an image which is a specifier. When a glyph function - ! for instance `Fglyph_height' - asks for a property of the glyph that ! can only be determined from its instantiated state, then the glyph ! image is instantiated and an image instance created. The instantiation ! process is governed by the specifier code and goes through a series of ! steps: ! ! * Validation. Instantiation of image instances happens dynamically - ! often within the guts of redisplay. Thus it is often not feasible ! to catch instantiator errors at instantiation time. Instead the ! instantiator is validated at the time it is added to the image ! specifier. This function is defined by `image_validate' and at a ! simple level validates keyword value pairs. ! ! * Duplication. The specifier code by default takes a copy of the ! instantiator. This is reasonable for most specifiers but in the ! case of widget-glyphs can be problematic, since some of the ! properties in the instantiator - for instance callbacks - could ! cause infinite recursion in the copying process. Thus the image ! code defines a function - `image_copy_instantiator' - which will ! selectively copy values. This is controlled by the way that a ! keyword is defined either using `IIFORMAT_VALID_KEYWORD' or ! `IIFORMAT_VALID_NONCOPY_KEYWORD'. Note that the image caching and ! redisplay code relies on instantiator copying to ensure that ! current and new instantiators are actually different rather than ! referring to the same thing. ! ! * Normalization. Once the instantiator has been copied it must be ! converted into a form that is viable at instantiation time. This ! can involve no changes at all, but typically involves things like ! converting file names to the actual data. This function is defined ! by `image_going_to_add' and `normalize_image_instantiator'. ! ! * Instantiation. When an image instance is actually required for ! display it is instantiated using `image_instantiate'. This ! involves calling instantiate methods that are specific to the type ! of image being instantiated. ! ! The final instantiation phase also involves a number of steps. In ! order to understand these we need to describe a number of concepts. ! ! An image is instantiated in a "domain", where a domain can be any ! one of a device, frame, window or image-instance. The domain gives the ! image-instance context and identity and properties that affect the ! appearance of the image-instance may be different for the same glyph ! instantiated in different domains. An example is the face used to ! display the image-instance. ! ! Although an image is instantiated in a particular domain the ! instantiation domain is not necessarily the domain in which the ! image-instance is cached. For example a pixmap can be instantiated in a ! window be actually be cached on a per-device basis. The domain in which ! the image-instance is actually cached is called the "governing-domain". ! A governing-domain is currently either a device or a window. ! Widget-glyphs and text-glyphs have a window as a governing-domain, all ! other image-instances have a device as the governing-domain. The ! governing domain for an image-instance is determined using the ! governing_domain image-instance method. ! ! 30.2 Widget-Glyphs ! ================== ! ! 30.3 Widget-Glyphs in the MS-Windows Environment ! ================================================ ! ! To Do ! ! 30.4 Widget-Glyphs in the X Environment ! ======================================= ! ! Widget-glyphs under X make heavy use of lwlib (*note Lucid Widget ! Library::) for manipulating the native toolkit objects. This is ! primarily so that different toolkits can be supported for ! widget-glyphs, just as they are supported for features such as menubars ! etc. ! ! Lwlib is extremely poorly documented and quite hairy so here is my ! understanding of what goes on. ! ! Lwlib maintains a set of widget_instances which mirror the ! hierarchical state of Xt widgets. I think this is so that widgets can ! be updated and manipulated generically by the lwlib library. For ! instance update_one_widget_instance can cope with multiple types of ! widget and multiple types of toolkit. Each element in the widget ! hierarchy is updated from its corresponding widget_instance by walking ! the widget_instance tree recursively. ! ! This has desirable properties such as lw_modify_all_widgets which is ! called from `glyphs-x.c' and updates all the properties of a widget ! without having to know what the widget is or what toolkit it is from. ! Unfortunately this also has hairy properties such as making the lwlib ! code quite complex. And of course lwlib has to know at some level what ! the widget is and how to set its properties. ! !  ! File: internals.info, Node: Specifiers, Next: Menus, Prev: Glyphs, Up: Top ! ! 31 Specifiers ! ************* ! ! Not yet documented. ! ! Specifiers are documented in depth in the Lisp Reference manual. ! *Note Specifiers: (lispref)Specifiers. The code in `specifier.c' is ! pretty straightforward. ! !  ! File: internals.info, Node: Menus, Next: Events and the Event Loop, Prev: Specifiers, Up: Top ! ! 32 Menus ! ******** ! ! A menu is set by setting the value of the variable `current-menubar' ! (which may be buffer-local) and then calling `set-menubar-dirty-flag' ! to signal a change. This will cause the menu to be redrawn at the next ! redisplay. The format of the data in `current-menubar' is described in ! `menubar.c'. ! ! Internally the data in current-menubar is parsed into a tree of ! `widget_value's' (defined in `lwlib.h'); this is accomplished by the ! recursive function `menu_item_descriptor_to_widget_value()', called by ! `compute_menubar_data()'. Such a tree is deallocated using ! `free_widget_value()'. ! ! `update_screen_menubars()' is one of the external entry points. ! This checks to see, for each screen, if that screen's menubar needs to ! be updated. This is the case if ! ! 1. `set-menubar-dirty-flag' was called since the last redisplay. ! (This function sets the C variable menubar_has_changed.) ! ! 2. The buffer displayed in the screen has changed. ! ! 3. The screen has no menubar currently displayed. ! ! `set_screen_menubar()' is called for each such screen. This ! function calls `compute_menubar_data()' to create the tree of ! widget_value's, then calls `lw_create_widget()', ! `lw_modify_all_widgets()', and/or `lw_destroy_all_widgets()' to create ! the X-Toolkit widget associated with the menu. ! ! `update_psheets()', the other external entry point, actually changes ! the menus being displayed. It uses the widgets fixed by ! `update_screen_menubars()' and calls various X functions to ensure that ! the menus are displayed properly. ! ! The menubar widget is set up so that `pre_activate_callback()' is ! called when the menu is first selected (i.e. mouse button goes down), ! and `menubar_selection_callback()' is called when an item is selected. ! `pre_activate_callback()' calls the function in activate-menubar-hook, ! which can change the menubar (this is described in `menubar.c'). If ! the menubar is changed, `set_screen_menubars()' is called. ! `menubar_selection_callback()' enqueues a menu event, putting in it a ! function to call (either `eval' or `call-interactively') and its ! argument, which is the callback function or form given in the menu's ! description. ! !  ! File: internals.info, Node: Events and the Event Loop, Next: Asynchronous Events; Quit Checking, Prev: Menus, Up: Top ! ! 33 Events and the Event Loop ! **************************** ! ! * Menu: ! ! * Introduction to Events:: ! * Main Loop:: ! * Specifics of the Event Gathering Mechanism:: ! * Specifics About the Emacs Event:: ! * Event Queues:: ! * Event Stream Callback Routines:: ! * Other Event Loop Functions:: ! * Stream Pairs:: ! * Converting Events:: ! * Dispatching Events; The Command Builder:: ! * Focus Handling:: ! * Editor-Level Control Flow Modules:: ! !  ! File: internals.info, Node: Introduction to Events, Next: Main Loop, Prev: Events and the Event Loop, Up: Events and the Event Loop ! ! 33.1 Introduction to Events ! =========================== ! ! An event is an object that encapsulates information about an ! interesting occurrence in the operating system. Events are generated ! either by user action, direct (e.g. typing on the keyboard or moving ! the mouse) or indirect (moving another window, thereby generating an ! expose event on an Emacs frame), or as a result of some other typically ! asynchronous action happening, such as output from a subprocess being ! ready or a timer expiring. Events come into the system in an ! asynchronous fashion (typically through a callback being called) and ! are converted into a synchronous event queue (first-in, first-out) in a ! process that we will call "collection". ! ! Note that each application has its own event queue. (It is ! immaterial whether the collection process directly puts the events in ! the proper application's queue, or puts them into a single system ! queue, which is later split up.) ! ! The most basic level of event collection is done by the operating ! system or window system. Typically, XEmacs does its own event ! collection as well. Often there are multiple layers of collection in ! XEmacs, with events from various sources being collected into a queue, ! which is then combined with other sources to go into another queue ! (i.e. a second level of collection), with perhaps another level on top ! of this, etc. ! ! XEmacs has its own types of events (called "Emacs events"), which ! provides an abstract layer on top of the system-dependent nature of the ! most basic events that are received. Part of the complex nature of the ! XEmacs event collection process involves converting from the ! operating-system events into the proper Emacs events--there may not be ! a one-to-one correspondence. ! ! Emacs events are documented in `events.h'; I'll discuss them later. ! !  ! File: internals.info, Node: Main Loop, Next: Specifics of the Event Gathering Mechanism, Prev: Introduction to Events, Up: Events and the Event Loop ! ! 33.2 Main Loop ! ============== ! ! The "command loop" is the top-level loop that the editor is always ! running. It loops endlessly, calling `next-event' to retrieve an event ! and `dispatch-event' to execute it. `dispatch-event' does the ! appropriate thing with non-user events (process, timeout, magic, eval, ! mouse motion); this involves calling a Lisp handler function, redrawing ! a newly-exposed part of a frame, reading subprocess output, etc. For ! user events, `dispatch-event' looks up the event in relevant keymaps or ! menubars; when a full key sequence or menubar selection is reached, the ! appropriate function is executed. `dispatch-event' may have to keep ! state across calls; this is done in the "command-builder" structure ! associated with each console (remember, there's usually only one ! console), and the engine that looks up keystrokes and constructs full ! key sequences is called the "command builder". This is documented ! elsewhere. ! ! The guts of the command loop are in `command_loop_1()'. This ! function doesn't catch errors, though--that's the job of ! `command_loop_2()', which is a condition-case (i.e. error-trapping) ! wrapper around `command_loop_1()'. `command_loop_1()' never returns, ! but may get thrown out of. ! ! When an error occurs, `cmd_error()' is called, which usually invokes ! the Lisp error handler in `command-error'; however, a default error ! handler is provided if `command-error' is `nil' (e.g. during startup). ! The purpose of the error handler is simply to display the error message ! and do associated cleanup; it does not need to throw anywhere. When ! the error handler finishes, the condition-case in `command_loop_2()' ! will finish and `command_loop_2()' will reinvoke `command_loop_1()'. ! ! `command_loop_2()' is invoked from three places: from ! `initial_command_loop()' (called from `main()' at the end of internal ! initialization), from the Lisp function `recursive-edit', and from ! `call_command_loop()'. ! ! `call_command_loop()' is called when a macro is started and when the ! minibuffer is entered; normal termination of the macro or minibuffer ! causes a throw out of the recursive command loop. (To ! `execute-kbd-macro' for macros and `exit' for minibuffers. Note also ! that the low-level minibuffer-entering function, ! `read-minibuffer-internal', provides its own error handling and does ! not need `command_loop_2()''s error encapsulation; so it tells ! `call_command_loop()' to invoke `command_loop_1()' directly.) ! ! Note that both read-minibuffer-internal and recursive-edit set up a ! catch for `exit'; this is why `abort-recursive-edit', which throws to ! this catch, exits out of either one. ! ! `initial_command_loop()', called from `main()', sets up a catch for ! `top-level' when invoking `command_loop_2()', allowing functions to ! throw all the way to the top level if they really need to. Before ! invoking `command_loop_2()', `initial_command_loop()' calls ! `top_level_1()', which handles all of the startup stuff (creating the ! initial frame, handling the command-line options, loading the user's ! `.emacs' file, etc.). The function that actually does this is in Lisp ! and is pointed to by the variable `top-level'; normally this function is ! `normal-top-level'. `top_level_1()' is just an error-handling wrapper ! similar to `command_loop_2()'. Note also that `initial_command_loop()' ! sets up a catch for `top-level' when invoking `top_level_1()', just ! like when it invokes `command_loop_2()'. ! !  ! File: internals.info, Node: Specifics of the Event Gathering Mechanism, Next: Specifics About the Emacs Event, Prev: Main Loop, Up: Events and the Event Loop ! ! 33.3 Specifics of the Event Gathering Mechanism ! =============================================== ! ! Here is an approximate diagram of the collection processes at work in ! XEmacs, under TTY's (TTY's are simpler than X so we'll look at this ! first): ! ! ! asynch. asynch. asynch. asynch. [Collectors in ! kbd events kbd events process process the OS] ! | | output output ! | | | | ! | | | | SIGINT, [signal handlers ! | | | | SIGQUIT, in XEmacs] ! V V V V SIGWINCH, ! file file file file SIGALRM ! desc. desc. desc. desc. | ! (TTY) (TTY) (pipe) (pipe) | ! | | | | fake timeouts ! | | | | file | ! | | | | desc. | ! | | | | (pipe) | ! | | | | | | ! | | | | | | ! | | | | | | ! V V V V V V ! ------>-----------<----------------<---------------- ! | ! | ! | [collected using `select()' in `emacs_tty_next_event()' ! | and converted to the appropriate Emacs event] ! | ! | ! V (above this line is TTY-specific) ! Emacs ----------------------------------------------- ! event (below this line is the generic event mechanism) ! | ! | ! was there if not, call ! a SIGINT? `emacs_tty_next_event()' ! | | ! | | ! | | ! V V ! --->------<---- ! | ! | [collected in `event_stream_next_event()'; ! | SIGINT is converted using `maybe_read_quit_event()'] ! V ! Emacs ! event ! | ! \---->------>----- maybe_kbd_translate() ---->---\ ! | ! | ! | ! command event queue | ! if not from command ! (contains events that were event queue, call ! read earlier but not processed, `event_stream_next_event()' ! typically when waiting in a | ! sit-for, sleep-for, etc. for | ! a particular event to be received) | ! | | ! | | ! V V ! ---->------------------------------------<---- ! | ! | [collected in ! | `next_event_internal()'] ! | ! unread- unread- event from | ! command- command- keyboard else, call ! events event macro `next_event_internal()' ! | | | | ! | | | | ! | | | | ! V V V V ! --------->----------------------<------------ ! | ! | [collected in `next-event', which may loop ! | more than once if the event it gets is on ! | a dead frame, device, etc.] ! | ! | ! V ! feed into top-level event loop, ! which repeatedly calls `next-event' ! and then dispatches the event ! using `dispatch-event' ! ! Notice the separation between TTY-specific and generic event ! mechanism. When using the Xt-based event loop, the TTY-specific stuff ! is replaced but the rest stays the same. ! ! It's also important to realize that only one different kind of ! system-specific event loop can be operating at a time, and must be able ! to receive all kinds of events simultaneously. For the two existing ! event loops (implemented in `event-tty.c' and `event-Xt.c', ! respectively), the TTY event loop _only_ handles TTY consoles, while ! the Xt event loop handles _both_ TTY and X consoles. This situation is ! different from all of the output handlers, where you simply have one ! per console type. ! ! Here's the Xt Event Loop Diagram (notice that below a certain point, ! it's the same as the above diagram): ! ! asynch. asynch. asynch. asynch. [Collectors in ! kbd kbd process process the OS] ! events events output output ! | | | | ! | | | | asynch. asynch. [Collectors in the ! | | | | X X OS and X Window System] ! | | | | events events ! | | | | | | ! | | | | | | ! | | | | | | SIGINT, [signal handlers ! | | | | | | SIGQUIT, in XEmacs] ! | | | | | | SIGWINCH, ! | | | | | | SIGALRM ! | | | | | | | ! | | | | | | | ! | | | | | | | timeouts ! | | | | | | | | ! | | | | | | | | ! | | | | | | V | ! V V V V V V fake | ! file file file file file file file | ! desc. desc. desc. desc. desc. desc. desc. | ! (TTY) (TTY) (pipe) (pipe) (socket) (socket) (pipe) | ! | | | | | | | | ! | | | | | | | | ! | | | | | | | | ! V V V V V V V V ! --->----------------------------------------<---------<------ ! | | | ! | | |[collected using `select()' in ! | | | `_XtWaitForSomething()', called ! | | | from `XtAppProcessEvent()', called ! | | | in `emacs_Xt_next_event()'; ! | | | dispatched to various callbacks] ! | | | ! | | | ! emacs_Xt_ p_s_callback(), | [popup_selection_callback] ! event_handler() x_u_v_s_callback(),| [x_update_vertical_scrollbar_ ! | x_u_h_s_callback(),| callback] ! | search_callback() | [x_update_horizontal_scrollbar_ ! | | | callback] ! | | | ! | | | ! enqueue_Xt_ signal_special_ | ! dispatch_event() Xt_user_event() | ! [maybe multiple | | ! times, maybe 0 | | ! times] | | ! | enqueue_Xt_ | ! | dispatch_event() | ! | | | ! | | | ! V V | ! -->----------<-- | ! | | ! | | ! dispatch `Xt_what_callback()' ! event sets flags ! queue | ! | | ! | | ! | | ! | | ! ---->-----------<-------- ! | ! | ! | [collected and converted as appropriate in ! | `emacs_Xt_next_event()'] ! | ! | ! V (above this line is Xt-specific) ! Emacs ------------------------------------------------ ! event (below this line is the generic event mechanism) ! | ! | ! was there if not, call ! a SIGINT? `emacs_Xt_next_event()' ! | | ! | | ! | | ! V V ! --->-------<---- ! | ! | [collected in `event_stream_next_event()'; ! | SIGINT is converted using `maybe_read_quit_event()'] ! V ! Emacs ! event ! | ! \---->------>----- maybe_kbd_translate() -->-----\ ! | ! | ! | ! command event queue | ! if not from command ! (contains events that were event queue, call ! read earlier but not processed, `event_stream_next_event()' ! typically when waiting in a | ! sit-for, sleep-for, etc. for | ! a particular event to be received) | ! | | ! | | ! V V ! ---->----------------------------------<------ ! | ! | [collected in ! | `next_event_internal()'] ! | ! unread- unread- event from | ! command- command- keyboard else, call ! events event macro `next_event_internal()' ! | | | | ! | | | | ! | | | | ! V V V V ! --------->----------------------<------------ ! | ! | [collected in `next-event', which may loop ! | more than once if the event it gets is on ! | a dead frame, device, etc.] ! | ! | ! V ! feed into top-level event loop, ! which repeatedly calls `next-event' ! and then dispatches the event ! using `dispatch-event' !  ! File: internals.info, Node: Specifics About the Emacs Event, Next: Event Queues, Prev: Specifics of the Event Gathering Mechanism, Up: Events and the Event Loop ! 33.4 Specifics About the Emacs Event ! ==================================== !  ! File: internals.info, Node: Event Queues, Next: Event Stream Callback Routines, Prev: Specifics About the Emacs Event, Up: Events and the Event Loop ! 33.5 Event Queues ! ================= ! There are two event queues here - the command event queue (#### which ! should be called "deferred event queue" and is in my glyph ws) and the ! dispatch event queue. (MS Windows actually has an extra dispatch queue ! for non-user events and uses the generic one only for user events. This ! is because user and non-user events in Windows come through the same ! place - the window procedure - but under X, it's possible to ! selectively process events such that we take all the user events before ! the non-user ones. #### In fact, given the way we now drain the queue, ! we might need two separate queues, like under Windows. Need to think ! carefully exactly how this works, and should certainly generalize the ! two different queues. ! The dispatch queue (which used to occur duplicated inside of each ! event implementation) is used for events that have been read from the ! window-system event queue(s) and not yet process by ! `next_event_internal()'. It exists for two reasons: (1) because in many ! implementations, events often come from the window system by way of ! callbacks, and need to push the event to be returned onto a queue; (2) ! in order to handle QUIT in a guaranteed correct fashion without ! resorting to weird implementation-specific hacks that may or may not ! work well, we need to drain the window-system event queues and then look ! through to see if there's an event matching quit-char (usually ^G). the ! drained events need to go onto a queue. (There are other, similar cases ! where we need to drain the pending events so we can look ahead - for ! example, checking for pending expose events under X to avoid excessive ! server activity.) ! The command event queue is used *AFTER* an event has been read from ! `next_event_internal()', when it needs to be pushed back. This ! includes, for example, `accept-process-output', `sleep-for' and ! `wait_delaying_user_input()'. Eval events and the like, generated by ! `enqueue-eval-event', `enqueue_magic_eval_event()', etc. are also ! pushed onto this queue. Some events generated by callbacks are also ! pushed onto this queue, #### although maybe shouldn't be. ! The command queue takes precedence over the dispatch queue. ! #### It is worth investigating to see whether both queues are really ! needed, and how exactly they should be used. `enqueue-eval-event', for ! example, could certainly push onto the dispatch queue, and all ! callbacks maybe should. `wait_delaying_user_input()' seems to need ! both queues, since it can take events from the dispatch queue and push ! them onto the command queue; but it perhaps could be rewritten to avoid ! this. #### In general we need to review the handling of these two ! queues, figure out exactly what ought to be happening, and document it. !  ! File: internals.info, Node: Event Stream Callback Routines, Next: Other Event Loop Functions, Prev: Event Queues, Up: Events and the Event Loop ! 33.6 Event Stream Callback Routines ! =================================== ! There is one object called an event_stream. This object contains ! callback functions for doing the window-system-dependent operations ! that XEmacs requires. ! If XEmacs is compiled with support for X11 and the X Toolkit, then ! this event_stream structure will contain functions that can cope with ! input on XEmacs windows on multiple displays, as well as input from ! dumb tty frames. ! If it is desired to have XEmacs able to open frames on the displays ! of multiple heterogeneous machines, X11 and SunView, or X11 and NeXT, ! for example, then it will be necessary to construct an event_stream ! structure that can cope with the given types. Currently, the only ! implemented event_streams are for dumb-ttys, and for X11 plus dumb-ttys, ! and for mswindows. ! To implement this for one window system is relatively simple. To ! implement this for multiple window systems is trickier and may not be ! possible in all situations, but it's been done for X and TTY. ! Note that these callbacks are *NOT* console methods; that's because ! the routines are not specific to a particular console type but must be ! able to simultaneously cope with all allowable console types. ! The slots of the event_stream structure: ! `next_event_cb' ! A function which fills in an XEmacs_event structure with the next ! event available. If there is no event available, then this should ! block. ! IMPORTANT: timer events and especially process events *must not* be ! returned if there are events of other types available; otherwise ! you can end up with an infinite loop in `Fdiscard_input()'. ! `event_pending_cb' ! A function which says whether there are events to be read. If ! called with an argument of 0, then this should say whether calling ! the `next_event_cb' will block. If called with a non-zero ! argument, then this should say whether there are that many ! user-generated events pending (that is, keypresses, mouse-clicks, ! dialog-box selection events, etc.). (This is used for redisplay ! optimization, among other things.) The difference is that the ! former includes process events and timer events, but the latter ! doesn't. ! If this function is not sure whether there are events to be read, ! it *must* return 0. Otherwise various undesirable effects will ! occur, such as redisplay not occurring until the next event occurs. ! `handle_magic_event_cb' ! XEmacs calls this with an event structure which contains ! window-system dependent information that XEmacs doesn't need to ! know about, but which must happen in order. If the ! `next_event_cb' never returns an event of type "magic", this will ! never be used. ! `format_magic_event_cb' ! Called with a magic event; print a representation of the innards ! of the event to PSTREAM. ! `compare_magic_event_cb' ! Called with two magic events; return non-zero if the innards of ! the two are equal, zero otherwise. ! `hash_magic_event_cb' ! Called with a magic event; return a hash of the innards of the ! event. ! `add_timeout_cb' ! Called with an EMACS_TIME, the absolute time at which a wakeup ! event should be generated; and a void *, which is an arbitrary ! value that will be returned in the timeout event. The timeouts ! generated by this function should be one-shots: they fire once and ! then disappear. This callback should return an int id-number ! which uniquely identifies this wakeup. If an implementation ! doesn't have microseconds or millisecond granularity, it should ! round up to the closest value it can deal with. ! `remove_timeout_cb' ! Called with an int, the id number of a wakeup to discard. This id ! number must have been returned by the `add_timeout_cb'. If the ! given wakeup has already expired, this should do nothing. ! `select_process_cb' ! `unselect_process_cb' ! These callbacks tell the underlying implementation to add or ! remove a file descriptor from the list of fds which are polled for ! inferior-process input. When input becomes available on the given ! process connection, an event of type "process" should be generated. ! `select_console_cb' ! `unselect_console_cb' ! These callbacks tell the underlying implementation to add or ! remove a console from the list of consoles which are polled for ! user-input. ! `select_device_cb' ! `unselect_device_cb' ! These callbacks are used by Unixoid event loops (those that use ! `select()' and file descriptors and have a separate input fd per ! device). ! `create_io_streams_cb' ! `delete_io_streams_cb' ! These callbacks are called by process code to create the input and ! output lstreams which are used for subprocess I/O. ! `quitp_cb' ! A handler function called from the `QUIT' macro which should check ! whether the quit character has been typed. On systems with SIGIO, ! this will not be called unless the `sigio_happened' flag is true ! (it is set from the SIGIO handler). ! XEmacs has its own event structures, which are distinct from the ! event structures used by X or any other window system. It is the job ! of the event_stream layer to translate to this format. !  ! File: internals.info, Node: Other Event Loop Functions, Next: Stream Pairs, Prev: Event Stream Callback Routines, Up: Events and the Event Loop ! 33.7 Other Event Loop Functions ! =============================== ! `detect_input_pending()' and `input-pending-p' look for input by ! calling `event_stream->event_pending_p' and looking in ! `[V]unread-command-event' and the `command_event_queue' (they do not ! check for an executing keyboard macro, though). ! `discard-input' cancels any command events pending (and any keyboard ! macros currently executing), and puts the others onto the ! `command_event_queue'. There is a comment about a "race condition", ! which is not a good sign. ! `next-command-event' and `read-char' are higher-level interfaces to ! `next-event'. `next-command-event' gets the next "command" event (i.e. ! keypress, mouse event, menu selection, or scrollbar action), calling ! `dispatch-event' on any others. `read-char' calls `next-command-event' ! and uses `event_to_character()' to return the character equivalent. ! With the right kind of input method support, it is possible for ! (read-char) to return a Kanji character. !  ! File: internals.info, Node: Stream Pairs, Next: Converting Events, Prev: Other Event Loop Functions, Up: Events and the Event Loop ! 33.8 Stream Pairs ! ================= ! Since there are many possible processes/event loop combinations, the ! event code is responsible for creating an appropriate lstream type. The ! process implementation does not care about that implementation. ! The Create stream pair function is passed two void* values, which ! identify process-dependent 'handles'. The process implementation uses ! these handles to communicate with child processes. The function must be ! prepared to receive handle types of any process implementation. Since ! only one process implementation exists in a particular XEmacs ! configuration, preprocessing is a means of compiling in the support for ! the code which deals with particular handle types. ! For example, a unixoid type loop, which relies on file descriptors, ! may be asked to create a pair of streams by a unix-style process ! implementation. In this case, the handles passed are unix file ! descriptors, and the code may deal with these directly. Although, the ! same code may be used on Win32 system with X-Windows. In this case, ! Win32 process implementation passes handles of type HANDLE, and the ! `create_io_streams' function must call appropriate function to get file ! descriptors given HANDLEs, so that these descriptors may be passed to ! `XtAddInput'. ! The handle given may have special denying value, in which case the ! corresponding lstream should not be created. ! The return value of the function is a unique stream identifier. It ! is used by processes implementation, in its platform-independent part. ! There is the get_process_from_usid function, which returns process ! object given its USID. The event stream is responsible for converting ! its internal handle type into USID. ! Example is the TTY event stream. When a file descriptor signals ! input, the event loop must determine process to which the input is ! destined. Thus, the implementation uses process input stream file ! descriptor as USID, by simply casting the fd value to USID type. ! There are two special USID values. One, `USID_ERROR', indicates that ! the stream pair cannot be created. The second, `USID_DONTHASH', ! indicates that streams are created, but the event stream does not wish ! to be able to find the process by its USID. Specifically, if an event ! stream implementation never calls `get_process_from_usid', this value ! should always be returned, to prevent accumulating useless information ! on USID to process relationship. !  ! File: internals.info, Node: Converting Events, Next: Dispatching Events; The Command Builder, Prev: Stream Pairs, Up: Events and the Event Loop ! 33.9 Converting Events ! ====================== ! `character_to_event()', `event_to_character()', `event-to-character', ! and `character-to-event' convert between characters and keypress events ! corresponding to the characters. If the event was not a keypress, ! `event_to_character()' returns -1 and `event-to-character' returns ! `nil'. These functions convert between character representation and ! the split-up event representation (keysym plus mod keys). ! !  ! File: internals.info, Node: Dispatching Events; The Command Builder, Next: Focus Handling, Prev: Converting Events, Up: Events and the Event Loop ! 33.10 Dispatching Events; The Command Builder ! ============================================= ! Not yet documented.  ! File: internals.info, Node: Focus Handling, Next: Editor-Level Control Flow Modules, Prev: Dispatching Events; The Command Builder, Up: Events and the Event Loop ! 33.11 Focus Handling ! ==================== ! Ben's capsule lecture on focus: ! In GNU Emacs `select-frame' never changes the window-manager frame ! focus. All it does is change the "selected frame". This is similar to ! what happens when we call `select-device' or `select-console'. ! Whenever an event comes in (including a keyboard event), its frame is ! selected; therefore, evaluating `select-frame' in `*scratch*' won't ! cause any effects because the next received event (in the same frame) ! will cause a switch back to the frame displaying `*scratch*'. ! Whenever a focus-change event is received from the window manager, it ! generates a `switch-frame' event, which causes the Lisp function ! `handle-switch-frame' to get run. This basically just runs ! `select-frame' (see below, however). ! In GNU Emacs, if you want to have an operation run when a frame is ! selected, you supply an event binding for `switch-frame' (and then ! maybe call `handle-switch-frame', or something ...). ! In XEmacs, we *do* change the window-manager frame focus as a result ! of `select-frame', but not until the next time an event is received, so ! that a function that momentarily changes the selected frame won't cause ! WM focus flashing. (#### There's something not quite right here; this ! is causing the wrong-cursor-focus problems that you occasionally see. ! But the general idea is correct.) This approach is winning for people ! who use the explicit-focus model, but is trickier to implement. ! We also don't make the `switch-frame' event visible but instead have ! `select-frame-hook', which is a better approach. ! There is the problem of surrogate minibuffers, where when we enter ! the minibuffer, you essentially want to temporarily switch the WM focus ! to the frame with the minibuffer, and switch it back when you exit the ! minibuffer. ! ! GNU Emacs solves this with the crockish `redirect-frame-focus', ! which says "for keyboard events received from FRAME, act like they're ! coming from FOCUS-FRAME". I think what this means is that, when a ! keyboard event comes in and the event manager is about to select the ! event's frame, if that frame has its focus redirected, the redirected-to ! frame is selected instead. That way, if you're in a minibufferless ! frame and enter the minibuffer, then all Lisp functions that run see the ! selected frame as the minibuffer's frame rather than the minibufferless ! frame you came from, so that (e.g.) your typing actually appears in the ! minibuffer's frame and things behave sanely. ! ! There's also some weird logic that switches the redirected frame ! focus from one frame to another if Lisp code explicitly calls ! `select-frame' (but not if `handle-switch-frame' is called), and saves ! and restores the frame focus in window configurations, etc. etc. All ! of this logic is heavily `#if 0''d, with lots of comments saying "No, ! this approach doesn't seem to work, so I'm trying this ... is it ! reasonable? Well, I'm not sure ..." that are a red flag indicating ! crockishness. ! ! Because of our way of doing things, we can avoid all this crock. ! Keyboard events never cause a select-frame (who cares what frame they're ! associated with? They come from a console, only). We change the actual ! WM focus to a surrogate minibuffer frame, so we don't have to do any ! internal redirection. In order to get the focus back, I took the ! approach in `minibuf.el' of just checking to see if the frame we moved ! to is still the selected frame, and move back to the old one if so. ! Conceivably we might have to do the weird "tracking" that GNU Emacs does ! when `select-frame' is called, but I don't think so. If the selected ! frame moved from the minibuffer frame, then we just leave it there, ! figuring that someone knows what they're doing. Because we don't have ! any redirection recorded anywhere, it's safe to do this, and we don't ! end up with unwanted redirection.  ! File: internals.info, Node: Editor-Level Control Flow Modules, Prev: Focus Handling, Up: Events and the Event Loop ! 33.12 Editor-Level Control Flow Modules ! ======================================= ! `event-Xt.c' ! `event-msw.c' ! `event-stream.c' ! `event-tty.c' ! `events-mod.h' ! `gpmevent.c' ! `gpmevent.h' ! `events.c' ! `events.h' ! These implement the handling of events (user input and other system ! notifications). ! `events.c' and `events.h' define the "event" Lisp object type and ! primitives for manipulating it. ! `event-stream.c' implements the basic functions for working with ! event queues, dispatching an event by looking it up in relevant keymaps ! and such, and handling timeouts; this includes the primitives ! `next-event' and `dispatch-event', as well as related primitives such ! as `sit-for', `sleep-for', and `accept-process-output'. ! (`event-stream.c' is one of the hairiest and trickiest modules in ! XEmacs. Beware! You can easily mess things up here.) ! `event-Xt.c' and `event-tty.c' implement the low-level interfaces ! onto retrieving events from Xt (the X toolkit) and from TTY's (using ! `read()' and `select()'), respectively. The event interface enforces a ! clean separation between the specific code for interfacing with the ! operating system and the generic code for working with events, by ! defining an API of basic, low-level event methods; `event-Xt.c' and ! `event-tty.c' are two different implementations of this API. To add ! support for a new operating system (e.g. NeXTstep), one merely needs to ! provide another implementation of those API functions. ! Note that the choice of whether to use `event-Xt.c' or `event-tty.c' ! is made at compile time! Or at the very latest, it is made at startup ! time. `event-Xt.c' handles events for _both_ X and TTY frames; ! `event-tty.c' is only used when X support is not compiled into XEmacs. ! The reason for this is that there is only one event loop in XEmacs: ! thus, it needs to be able to receive events from all different kinds of ! frames. ! `keymap.c' ! `keymap.h' ! ! `keymap.c' and `keymap.h' define the "keymap" Lisp object type and ! associated methods and primitives. (Remember that keymaps are objects ! that associate event descriptions with functions to be called to ! "execute" those events; `dispatch-event' looks up events in the ! relevant keymaps.) ! `cmdloop.c' ! `cmdloop.c' contains functions that implement the actual editor ! command loop--i.e. the event loop that cyclically retrieves and ! dispatches events. This code is also rather tricky, just like ! `event-stream.c'. ! `macros.c' ! `macros.h' ! These two modules contain the basic code for defining keyboard ! macros. These functions don't actually do much; most of the code that ! handles keyboard macros is mixed in with the event-handling code in ! `event-stream.c'. ! `minibuf.c' ! This contains some miscellaneous code related to the minibuffer ! (most of the minibuffer code was moved into Lisp by Richard Mlynarik). ! This includes the primitives for completion (although filename ! completion is in `dired.c'), the lowest-level interface to the ! minibuffer (if the command loop were cleaned up, this too could be in ! Lisp), and code for dealing with the echo area (this, too, was mostly ! moved into Lisp, and the only code remaining is code to call out to ! Lisp or provide simple bootstrapping implementations early in temacs, ! before the echo-area Lisp code is loaded). !  ! File: internals.info, Node: Asynchronous Events; Quit Checking, Next: Lstreams, Prev: Events and the Event Loop, Up: Top ! 34 Asynchronous Events; Quit Checking ! ************************************* ! ! * Menu: ! ! * Signal Handling:: ! * Control-G (Quit) Checking:: ! * Profiling:: ! * Asynchronous Timeouts:: ! * Exiting::  ! File: internals.info, Node: Signal Handling, Next: Control-G (Quit) Checking, Prev: Asynchronous Events; Quit Checking, Up: Asynchronous Events; Quit Checking ! 34.1 Signal Handling ! ==================== !  ! File: internals.info, Node: Control-G (Quit) Checking, Next: Profiling, Prev: Signal Handling, Up: Asynchronous Events; Quit Checking ! 34.2 Control-G (Quit) Checking ! ============================== ! _Note_: The code to handle QUIT is divided between `lisp.h' and ! `signal.c'. There is also some special-case code in the async timer ! code in `event-stream.c' to notice when the poll-for-quit (and ! poll-for-sigchld) timers have gone off. ! Here's an overview of how this convoluted stuff works: ! 1. Scattered throughout the XEmacs core code are calls to the macro ! QUIT; This macro checks to see whether a `C-g' has recently been ! pressed and not yet handled, and if so, it handles the `C-g' by ! calling `signal_quit()', which invokes the standard `Fsignal()' ! code, with the error being `Qquit'. Lisp code can establish ! handlers for this (using `condition-case'), but normally there is ! no handler, and so execution is thrown back to the innermost ! enclosing event loop. (One of the things that happens when ! entering an event loop is that a `condition-case' is established ! that catches *all* calls to `signal', including this one.) ! 2. How does the QUIT macro check to see whether `C-g' has been ! pressed; obviously this needs to be extremely fast. Now for some ! history. In early Lemacs as inherited from the FSF going back 15 ! years or more, there was a great fondness for using SIGIO (which ! is sent whenever there is I/O available on a given socket, tty, ! etc.). In fact, in GNU Emacs, perhaps even today, all reading of ! events from the X server occurs inside the SIGIO handler! This is ! crazy, but not completely relevant. What is relevant is that ! similar stuff happened inside the SIGIO handler for `C-g': it ! searched through all the pending (i.e. not yet delivered to XEmacs ! yet) X events for one that matched `C-g'. When it saw a match, it ! set Vquit_flag to Qt. On TTY's, `C-g' is actually mapped to be the ! interrupt character (i.e. it generates SIGINT), and XEmacs's ! handler for this signal sets Vquit_flag to Qt. Then, sometime ! later after the signal handlers finished and a QUIT macro was ! called, the macro noticed the setting of `Vquit_flag' and used ! this as an indication to call `signal_quit()'. What ! `signal_quit()' actually does is set `Vquit_flag' to Qnil (so that ! we won't get repeated interruptions from a single `C-g' press) and ! then calls the equivalent of (signal 'quit nil). ! 3. Another complication is introduced in that Vquit_flag is actually ! exported to Lisp as `quit-flag'. This allows users some level of ! control over whether and when `C-g' is processed as quit, esp. in ! combination with `inhibit-quit'. This is another Lisp variable, ! and if set to non-nil, it inhibits `signal_quit()' from getting ! called, meaning that the `C-g' gets essentially ignored. But not ! completely: Because the resetting of `quit-flag' happens only in ! `signal_quit()', which isn't getting called, the `C-g' press is ! still noticed, and as soon as `inhibit-quit' is set back to nil, a ! quit will be signalled at the next QUIT macro. Thus, what ! `inhibit-quit' really does is defer quits until after the quit- ! inhibitted period. ! 4. Another consideration, introduced by XEmacs, is critical quitting. ! If you press `Control-Shift-G' instead of just `C-g', `quit-flag' ! is set to `critical' instead of to t. When QUIT processes this ! value, it *ignores* the value of `inhibit-quit'. This allows you ! to quit even out of a quit-inhibitted section of code! ! Furthermore, when `signal_quit()' notices that it was invoked as a ! result of a critical quit, it automatically invokes the debugger ! (which otherwise would only happen when `debug-on-quit' is set to ! t). ! 5. Well, I explained above about how `quit-flag' gets set correctly, ! but I began with a disclaimer stating that this was the old way of ! doing things. What's done now? Well, first of all, the SIGIO ! handler (which formerly checked all pending events to see if ! there's a `C-g') now does nothing but set a flag - or actually two ! flags, something_happened and quit_check_signal_happened. There ! are two flags because the QUIT macro is now used for more than ! just handling QUIT; it's also used for running asynchronous ! timeout handlers that have recently expired, and perhaps other ! things. The idea here is that the QUIT macros occur extremely ! often in the code, but only occur at places that are relatively ! safe - in particular, if an error occurs, nothing will get ! completely trashed. ! 6. Now, let's look at QUIT again. ! 7. UNFINISHED. Note, however, that as of the point when this ! comment got committed to CVS (mid-2001), the interaction between ! reading `C-g' as an event and processing it as QUIT was overhauled ! to (for the first time) be understandable and actually work ! correctly. Now, the way things work is that if `C-g' is pressed ! while XEmacs is blocking at the top level, waiting for a user ! event, it will be read as an event; otherwise, it will cause QUIT. ! (This includes times when XEmacs is blocking, but not waiting for ! a user event, e.g. `accept-process-output' and ! `wait_delaying_user_events()'.) Formerly, this was supposed to ! happen, but didn't always due to a bizarre and broken scheme, ! documented in `next_event_internal' like this: ! If we read a `C-g', then set `quit-flag' but do not discard ! the `C-g'. The callers of `next_event_internal()' will do ! one of two things: ! ! 1. set `Vquit_flag' to Qnil. (`next-event' does this.) This ! will cause the ^G to be treated as a normal keystroke. ! ! 2. not change `Vquit_flag' but attempt to enqueue the ^G, ! at which point it will be discarded. The next time QUIT ! is called, it will notice that `Vquit_flag' was set. ! ! This required weirdness in `enqueue_command_event_1' like this: ! ! put the event on the typeahead queue, unless the event is the ! quit char, in which case the `QUIT' which will occur on the ! next trip through this loop is all the processing we should ! do - leaving it on the queue would cause the quit to be ! processed twice. ! ! And further weirdness elsewhere, none of which made any sense, and ! didn't work, because (e.g.) it required that QUIT never happen ! anywhere inside `next_event_internal()' or any callers when `C-g' ! should be read as a user event, which was impossible to implement ! in practice. ! ! Now what we do is fairly simple. Callers of ! `next_event_internal()' that want `C-g' read as a user event call ! `begin_dont_check_for_quit()'. `next_event_internal()', when it ! gets a `C-g', simply sets `Vquit_flag' (just as when a `C-g' is ! detected during the operation of `QUIT' or `QUITP'), and then ! tries to `QUIT'. This will fail if blocked by the previous call, ! at which point `next_event_internal()' will return the `C-g' as an ! event. To unblock things, first set `Vquit_flag' to nil (it was ! set to t when the `C-g' was read, and if we don't reset it, the ! next call to `QUIT' will quit), and then `unbind_to()' the depth ! returned by `begin_dont_check_for_quit()'. It makes no difference ! is `QUIT' is called a zillion times in `next_event_internal()' or ! anywhere else, because it's blocked and will never signal. ! ! 34.2.1 Reentrancy Problems due to QUIT Checking ! ----------------------------------------------- ! ! Checking for QUIT can do quite a long of things - since it pumps the ! event loop, this may cause arbitrary code to get executed, garbage ! collection to happen. etc. (In fact, garbage collection cannot happen ! because it is inhibited.) This has led to crashes when functions get ! called reentrantly when not expecting it. Example: ! Crash - reentrant `re_match_2()' ! -------------------------------- ! /* dont_check_for_quit is set in three circumstances: ! (1) when we are in the process of changing the window ! configuration. The frame might be in an inconsistent state, ! which will cause assertion failures if we check for QUIT. ! (2) when we are reading events, and want to read the C-g ! as an event. The normal check for quit will discard the C-g, ! which would be bad. ! (3) when we're going down with a fatal error. we're most likely ! in an inconsistent state, and we definitely don't want to be ! interrupted. */ ! /* We should *not* conditionalize on Vinhibit_quit, or ! critical-quit (Control-Shift-G) won't work right. */ ! /* WARNING: Even calling check_quit(), without actually dispatching ! a quit signal, can result in arbitrary Lisp code getting executed ! -- at least under Windows. (Not to mention obvious Lisp ! invocations like asynchronous timer callbacks.) Here's a sample ! stack trace to demonstrate: ! NTDLL! DbgBreakPoint@0 address 0x77f9eea9 ! assert_failed(const char * 0x012d036c, int 4596, const char * 0x012d0354) line 3478 ! re_match_2_internal(re_pattern_buffer * 0x012d6780, const unsigned char * 0x00000000, int 0, const unsigned char * 0x022f9328, int 34, int 0, re_registers * 0x012d53d0 search_regs, int 34) line 4596 + 41 bytes ! re_search_2(re_pattern_buffer * 0x012d6780, const char * 0x00000000, int 0, const char * 0x022f9328, int 34, int 0, int 34, re_registers * 0x012d53d0 search_regs, int 34) line 4269 + 37 bytes ! re_search(re_pattern_buffer * 0x012d6780, const char * 0x022f9328, int 34, int 0, int 34, re_registers * 0x012d53d0 search_regs) line 4031 + 37 bytes ! string_match_1(long 31222628, long 30282164, long 28377092, buffer * 0x022fde00, int 0) line 413 + 69 bytes ! Fstring_match(long 31222628, long 30282164, long 28377092, long 28377092) line 436 + 34 bytes ! Ffuncall(int 3, long * 0x008297f8) line 3488 + 168 bytes ! execute_optimized_program(const unsigned char * 0x020ddc50, int 6, long * 0x020ddf50) line 744 + 16 bytes ! funcall_compiled_function(long 34407748, int 1, long * 0x00829aec) line 516 + 53 bytes ! Ffuncall(int 2, long * 0x00829ae8) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x020ddc90, int 4, long * 0x020ddf90) line 744 + 16 bytes ! funcall_compiled_function(long 34407720, int 1, long * 0x00829e28) line 516 + 53 bytes ! Ffuncall(int 2, long * 0x00829e24) line 3523 + 17 bytes ! mapcar1(long 15, long * 0x00829e48, long 34447820, long 34187868) line 2929 + 11 bytes ! Fmapcar(long 34447820, long 34187868) line 3035 + 21 bytes ! Ffuncall(int 3, long * 0x00829f20) line 3488 + 93 bytes ! execute_optimized_program(const unsigned char * 0x020c2b70, int 7, long * 0x020dd010) line 744 + 16 bytes ! funcall_compiled_function(long 34407580, int 2, long * 0x0082a210) line 516 + 53 bytes ! Ffuncall(int 3, long * 0x0082a20c) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x020cf810, int 6, long * 0x020cfb10) line 744 + 16 bytes ! funcall_compiled_function(long 34407524, int 0, long * 0x0082a580) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082a57c) line 3523 + 17 bytes ! run_hook_with_args_in_buffer(buffer * 0x022fde00, int 1, long * 0x0082a57c, int 0) line 3980 + 13 bytes ! run_hook_with_args(int 1, long * 0x0082a57c, int 0) line 3993 + 23 bytes ! Frun_hooks(int 1, long * 0x0082a57c) line 3847 + 19 bytes ! run_hook(long 34447484) line 4094 + 11 bytes ! unsafe_handle_wm_initmenu_1(frame * 0x01dbb000) line 736 + 11 bytes ! unsafe_handle_wm_initmenu(long 28377092) line 807 + 11 bytes ! condition_case_1(long 28377116, long (long)* 0x0101c827 unsafe_handle_wm_initmenu(long), long 28377092, long (long, long)* 0x01005fa4 mswindows_modal_loop_error_handler(long, long), long 28377092) line 1692 + 7 bytes ! mswindows_protect_modal_loop(long (long)* 0x0101c827 unsafe_handle_wm_initmenu(long), long 28377092) line 1194 + 32 bytes ! mswindows_handle_wm_initmenu(HMENU__ * 0x00010199, frame * 0x01dbb000) line 826 + 17 bytes ! mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 278, unsigned int 65945, long 0) line 3089 + 31 bytes ! USER32! UserCallWinProc@20 + 24 bytes ! USER32! DispatchClientMessage@20 + 47 bytes ! USER32! __fnDWORD@4 + 34 bytes ! NTDLL! KiUserCallbackDispatcher@12 + 19 bytes ! USER32! DispatchClientMessage@20 address 0x77e163cc ! USER32! DefWindowProcW@16 + 34 bytes ! qxeDefWindowProc(HWND__ * 0x000501da, unsigned int 274, unsigned int 61696, long 98) line 1188 + 22 bytes ! mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 274, unsigned int 61696, long 98) line 3362 + 21 bytes ! USER32! UserCallWinProc@20 + 24 bytes ! USER32! DispatchClientMessage@20 + 47 bytes ! USER32! __fnDWORD@4 + 34 bytes ! NTDLL! KiUserCallbackDispatcher@12 + 19 bytes ! USER32! DispatchClientMessage@20 address 0x77e163cc ! USER32! DefWindowProcW@16 + 34 bytes ! qxeDefWindowProc(HWND__ * 0x000501da, unsigned int 262, unsigned int 98, long 540016641) line 1188 + 22 bytes ! mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 262, unsigned int 98, long 540016641) line 3362 + 21 bytes ! USER32! UserCallWinProc@20 + 24 bytes ! USER32! DispatchMessageWorker@8 + 244 bytes ! USER32! DispatchMessageW@4 + 11 bytes ! qxeDispatchMessage(const tagMSG * 0x0082c684 {msg=0x00000106 wp=0x00000062 lp=0x20300001}) line 989 + 10 bytes ! mswindows_drain_windows_queue() line 1345 + 9 bytes ! emacs_mswindows_quit_p() line 3947 ! event_stream_quit_p() line 666 ! check_quit() line 686 ! check_what_happened() line 437 ! re_match_2_internal(re_pattern_buffer * 0x012d5a18, const unsigned char * 0x00000000, int 0, const unsigned char * 0x02235000, int 23486, int 14645, re_registers * 0x012d53d0 search_regs, int 23486) line 4717 + 14 bytes ! re_search_2(re_pattern_buffer * 0x012d5a18, const char * 0x02235000, int 23486, const char * 0x0223b38e, int 0, int 14645, int 8841, re_registers * 0x012d53d0 search_regs, int 23486) line 4269 + 37 bytes ! search_buffer(buffer * 0x022fde00, long 29077572, long 13789, long 23487, long 1, int 1, long 28377092, long 28377092, int 0) line 1224 + 89 bytes ! search_command(long 29077572, long 46975, long 28377116, long 28377092, long 28377092, int 1, int 1, int 0) line 1054 + 151 bytes ! Fre_search_forward(long 29077572, long 46975, long 28377116, long 28377092, long 28377092) line 2147 + 31 bytes ! Ffuncall(int 4, long * 0x0082ceb0) line 3488 + 216 bytes ! execute_optimized_program(const unsigned char * 0x02047810, int 13, long * 0x02080c10) line 744 + 16 bytes ! funcall_compiled_function(long 34187208, int 3, long * 0x0082d1b8) line 516 + 53 bytes ! Ffuncall(int 4, long * 0x0082d1b4) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x01e96a10, int 6, long * 0x020ae510) line 744 + 16 bytes ! funcall_compiled_function(long 34186676, int 3, long * 0x0082d4a0) line 516 + 53 bytes ! Ffuncall(int 4, long * 0x0082d49c) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02156b50, int 4, long * 0x020c2db0) line 744 + 16 bytes ! funcall_compiled_function(long 34186564, int 2, long * 0x0082d780) line 516 + 53 bytes ! Ffuncall(int 3, long * 0x0082d77c) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x0082d964, int 3, long * 0x020c2d70) line 744 + 16 bytes ! Fbyte_code(long 29405156, long 34352480, long 7) line 2392 + 38 bytes ! Feval(long 34354440) line 3290 + 187 bytes ! condition_case_1(long 34354572, long (long)* 0x01087232 Feval(long), long 34354440, long (long, long)* 0x01084764 run_condition_case_handlers(long, long), long 28377092) line 1692 + 7 bytes ! condition_case_3(long 34354440, long 28377092, long 34354572) line 1779 + 27 bytes ! execute_rare_opcode(long * 0x0082dc7c, const unsigned char * 0x01b090af, int 143) line 1269 + 19 bytes ! execute_optimized_program(const unsigned char * 0x01b09090, int 6, long * 0x020ae590) line 654 + 17 bytes ! funcall_compiled_function(long 34186620, int 0, long * 0x0082df68) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082df64) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02195470, int 1, long * 0x020c2df0) line 744 + 16 bytes ! funcall_compiled_function(long 34186508, int 0, long * 0x0082e23c) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082e238) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x01e5d410, int 6, long * 0x0207d410) line 744 + 16 bytes ! funcall_compiled_function(long 34186312, int 1, long * 0x0082e524) line 516 + 53 bytes ! Ffuncall(int 2, long * 0x0082e520) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x02108fb0, int 2, long * 0x020c2e30) line 744 + 16 bytes ! funcall_compiled_function(long 34186340, int 0, long * 0x0082e7fc) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082e7f8) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x020fe150, int 2, long * 0x01e6f510) line 744 + 16 bytes ! funcall_compiled_function(long 31008124, int 0, long * 0x0082ebd8) line 516 + 53 bytes ! Ffuncall(int 1, long * 0x0082ebd4) line 3523 + 17 bytes ! run_hook_with_args_in_buffer(buffer * 0x022fde00, int 1, long * 0x0082ebd4, int 0) line 3980 + 13 bytes ! run_hook_with_args(int 1, long * 0x0082ebd4, int 0) line 3993 + 23 bytes ! Frun_hooks(int 1, long * 0x0082ebd4) line 3847 + 19 bytes ! Ffuncall(int 2, long * 0x0082ebd0) line 3509 + 14 bytes ! execute_optimized_program(const unsigned char * 0x01ef2210, int 5, long * 0x01da8e10) line 744 + 16 bytes ! funcall_compiled_function(long 31020440, int 2, long * 0x0082eeb8) line 516 + 53 bytes ! Ffuncall(int 3, long * 0x0082eeb4) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x0082f09c, int 3, long * 0x01d89390) line 744 + 16 bytes ! Fbyte_code(long 31102388, long 30970752, long 7) line 2392 + 38 bytes ! Feval(long 31087568) line 3290 + 187 bytes ! condition_case_1(long 30961240, long (long)* 0x01087232 Feval(long), long 31087568, long (long, long)* 0x01084764 run_condition_case_handlers(long, long), long 28510180) line 1692 + 7 bytes ! condition_case_3(long 31087568, long 28510180, long 30961240) line 1779 + 27 bytes ! execute_rare_opcode(long * 0x0082f450, const unsigned char * 0x01ef23ec, int 143) line 1269 + 19 bytes ! execute_optimized_program(const unsigned char * 0x01ef2310, int 6, long * 0x01da8f10) line 654 + 17 bytes ! funcall_compiled_function(long 31020412, int 1, long * 0x0082f740) line 516 + 53 bytes ! Ffuncall(int 2, long * 0x0082f73c) line 3523 + 17 bytes ! execute_optimized_program(const unsigned char * 0x020fe650, int 3, long * 0x01d8c490) line 744 + 16 bytes ! funcall_compiled_function(long 31020020, int 2, long * 0x0082fa14) line 516 + 53 bytes ! Ffuncall(int 3, long * 0x0082fa10) line 3523 + 17 bytes ! Fcall_interactively(long 29685180, long 28377092, long 28377092) line 1008 + 22 bytes ! Fcommand_execute(long 29685180, long 28377092, long 28377092) line 2929 + 17 bytes ! execute_command_event(command_builder * 0x01be1900, long 36626492) line 4048 + 25 bytes ! Fdispatch_event(long 36626492) line 4341 + 70 bytes ! Fcommand_loop_1() line 582 + 9 bytes ! command_loop_1(long 28377092) line 495 ! condition_case_1(long 28377188, long (long)* 0x01064fb9 command_loop_1(long), long 28377092, long (long, long)* 0x010649d0 cmd_error(long, long), long 28377092) line 1692 + 7 bytes ! command_loop_3() line 256 + 35 bytes ! command_loop_2(long 28377092) line 269 ! internal_catch(long 28457612, long (long)* 0x01064b20 command_loop_2(long), long 28377092, int * volatile 0x00000000) line 1317 + 7 bytes ! initial_command_loop(long 28377092) line 305 + 25 bytes ! STACK_TRACE_EYE_CATCHER(int 1, char * * 0x01b63ff0, char * * 0x01ca5300, int 0) line 2501 ! main(int 1, char * * 0x01b63ff0, char * * 0x01ca5300) line 2938 ! XEMACS! mainCRTStartup + 180 bytes ! _start() line 171 ! KERNEL32! BaseProcessStart@4 + 115547 bytes ! [explain dont_check_for_quit() et al]  ! File: internals.info, Node: Profiling, Next: Asynchronous Timeouts, Prev: Control-G (Quit) Checking, Up: Asynchronous Events; Quit Checking ! 34.3 Profiling ! ============== ! We implement our own profiling scheme so that we can determine things ! like which Lisp functions are occupying the most time. Any standard ! OS-provided profiling works on C functions, which is not always that ! useful - and inconvenient, since it requires compiling with profile ! info and can't be retrieved dynamically, as XEmacs is running. ! The basic idea is simple. We set a profiling timer using setitimer ! (ITIMER_PROF), which generates a SIGPROF every so often. (This runs not ! in real time but rather when the process is executing or the system is ! running on behalf of the process - at least, that is the case under ! Unix. Under MS Windows and Cygwin, there is no `setitimer()', so we ! simulate it using multimedia timers, which run in real time. To make ! the results a bit more realistic, we ignore ticks that go off while ! blocking on an event wait. Note that Cygwin does provide a simulation ! of `setitimer()', but it's in real time anyway, since Windows doesn't ! provide a way to have process-time timers, and furthermore, it's broken, ! so we don't use it.) When the signal goes off, we see what we're in, and ! add 1 to the count associated with that function. ! It would be nice to use the Lisp allocation mechanism etc. to keep ! track of the profiling information (i.e. to use Lisp hash tables), but ! we can't because that's not safe - updating the timing information ! happens inside of a signal handler, so we can't rely on not being in ! the middle of Lisp allocation, garbage collection, `malloc()', etc. ! Trying to make it work would be much more work than it's worth. ! Instead we use a basic (non-Lisp) hash table, which will not conflict ! with garbage collection or anything else as long as it doesn't try to ! resize itself. Resizing itself, however (which happens as a result of ! a `puthash()'), could be deadly. To avoid this, we make sure, at ! points where it's safe (e.g. `profile_record_about_to_call()' - ! recording the entry into a function call), that the table always has ! some breathing room in it so that no resizes will occur until at least ! that many items are added. This is safe because any new item to be ! added in the sigprof would likely have the ! `profile_record_about_to_call()' called just before it, and the ! breathing room is checked. ! In general: any entry that the sigprof handler puts into the table ! comes from a backtrace frame (except "Processing Events at Top Level", ! and there's only one of those). Either that backtrace frame was added ! when profiling was on (in which case `profile_record_about_to_call()' ! was called and the breathing space updated), or when it was off - and in ! this case, no such frames can have been added since the last time ! `start-profile' was called, so when `start-profile' is called we make ! sure there is sufficient breathing room to account for all entries ! currently on the stack. ! Jan 1998: In addition to timing info, I have added code to remember ! call counts of Lisp funcalls. The `profile_increase_call_count()' ! function is called from `Ffuncall()', and serves to add data to ! Vcall_count_profile_table. This mechanism is much simpler and ! independent of the SIGPROF-driven one. It uses the Lisp allocation ! mechanism normally, since it is not called from a handler. It may even ! be useful to provide a way to turn on only one profiling mechanism, but ! I haven't done so yet. -hniksic ! Dec 2002: Total overhaul of the interface, making it sane and easier ! to use. -ben ! Feb 2003: Lots of rewriting of the internal code. Add ! GC-consing-usage, total GC usage, and total timing to the information ! tracked. Track profiling overhead and allow the ability to have ! internal sections (e.g. internal-external conversion, byte-char ! conversion) that are treated like Lisp functions for the purpose of ! profiling. -ben ! BEWARE: If you are modifying this file, be *very* careful. Correctly ! implementing the "total" values is very tricky due to the possibility of ! recursion and of functions already on the stack when starting to ! profile/still on the stack when stopping.  ! File: internals.info, Node: Asynchronous Timeouts, Next: Exiting, Prev: Profiling, Up: Asynchronous Events; Quit Checking ! 34.4 Asynchronous Timeouts ! ========================== !  ! File: internals.info, Node: Exiting, Prev: Asynchronous Timeouts, Up: Asynchronous Events; Quit Checking ! 34.5 Exiting ! ============ ! Ben's capsule summary about expected and unexpected exits from XEmacs. ! Expected exits occur when the user directs XEmacs to exit, for ! example by pressing the close button on the only frame in XEmacs, or by ! typing `C-x C-c'. This runs `save-buffers-kill-emacs', which saves any ! necessary buffers, and then exits using the primitive `kill-emacs'. ! However, unexpected exits occur in a few different ways: ! * A memory access violation or other hardware-generated exception ! occurs. This is the worst possible problem to deal with, because ! the fault can occur while XEmacs is in any state whatsoever, even ! quite unstable ones. As a result, we need to be *extremely* ! careful what we do. ! * We are using one X display (or if we've used more, we've closed the ! others already), and some hardware or other problem happens and ! suddenly we've lost our connection to the display. In this ! situation, things are not so dire as in the last one; our code ! itself isn't trashed, so we can continue execution as normal, ! after having set things up so that we can exit at the appropriate ! time. Our exit still needs to be of the emergency nature; we have ! no displays, so any attempts to use them will fail. We simply ! want to auto-save (the single most important thing to do during ! shut-down), do minimal cleanup of stuff that has an independent ! existence outside of XEmacs, and exit. ! Currently, both unexpected exit scenarios described above set ! `preparing_for_armageddon' to indicate that nonessential and possibly ! dangerous things should not be done, specifically: ! - no garbage collection. ! - no hooks are run. ! - no messages of any sort from autosaving. ! - autosaving tries harder, ignoring certain failures. ! - existing frames are not deleted. ! (Also, all places that set `preparing_for_armageddon' also set ! `dont_check_for_quit'. This happens separately because it's also ! necessary to set other variables to make absolutely sure no quitting ! happens.) ! In the first scenario above (the access violation), we also set ! `fatal_error_in_progress'. This causes more things to not happen: ! - assertion failures do not abort. ! - printing code does not do code conversion or gettext when printing ! to stdout/stderr.  ! File: internals.info, Node: Lstreams, Next: Subprocesses, Prev: Asynchronous Events; Quit Checking, Up: Top ! 35 Lstreams ! *********** ! An "lstream" is an internal Lisp object that provides a generic ! buffering stream implementation. Conceptually, you send data to the ! stream or read data from the stream, not caring what's on the other end ! of the stream. The other end could be another stream, a file ! descriptor, a stdio stream, a fixed block of memory, a reallocating ! block of memory, etc. The main purpose of the stream is to provide a ! standard interface and to do buffering. Macros are defined to read or ! write characters, so the calling functions do not have to worry about ! blocking data together in order to achieve efficiency. ! * Menu: ! * Creating an Lstream:: Creating an lstream object. ! * Lstream Types:: Different sorts of things that are streamed. ! * Lstream Functions:: Functions for working with lstreams. ! * Lstream Methods:: Creating new lstream types. !  ! File: internals.info, Node: Creating an Lstream, Next: Lstream Types, Prev: Lstreams, Up: Lstreams ! 35.1 Creating an Lstream ! ======================== ! Lstreams come in different types, depending on what is being interfaced ! to. Although the primitive for creating new lstreams is ! `Lstream_new()', generally you do not call this directly. Instead, you ! call some type-specific creation function, which creates the lstream ! and initializes it as appropriate for the particular type. ! All lstream creation functions take a MODE argument, specifying what ! mode the lstream should be opened as. This controls whether the ! lstream is for input and output, and optionally whether data should be ! blocked up in units of MULE characters. Note that some types of ! lstreams can only be opened for input; others only for output; and ! others can be opened either way. #### Richard Mlynarik thinks that ! there should be a strict separation between input and output streams, ! and he's probably right. ! MODE is a string, one of ! `"r"' ! Open for reading. ! `"w"' ! Open for writing. ! `"rc"' ! Open for reading, but "read" never returns partial MULE characters. ! `"wc"' ! Open for writing, but never writes partial MULE characters. !  ! File: internals.info, Node: Lstream Types, Next: Lstream Functions, Prev: Creating an Lstream, Up: Lstreams ! 35.2 Lstream Types ! ================== ! stdio ! filedesc ! lisp-string ! fixed-buffer ! resizing-buffer ! dynarr ! lisp-buffer ! print ! decoding ! encoding  ! File: internals.info, Node: Lstream Functions, Next: Lstream Methods, Prev: Lstream Types, Up: Lstreams ! 35.3 Lstream Functions ! ====================== ! -- Function: Lstream * Lstream_new (Lstream_implementation *IMP, const ! char *MODE) ! Allocate and return a new Lstream. This function is not really ! meant to be called directly; rather, each stream type should ! provide its own stream creation function, which creates the stream ! and does any other necessary creation stuff (e.g. opening a file). ! -- Function: void Lstream_set_buffering (Lstream *LSTR, ! Lstream_buffering BUFFERING, int BUFFERING_SIZE) ! Change the buffering of a stream. See `lstream.h'. By default the ! buffering is `STREAM_BLOCK_BUFFERED'. ! -- Function: int Lstream_flush (Lstream *LSTR) ! Flush out any pending unwritten data in the stream. Clear any ! buffered input data. Returns 0 on success, -1 on error. ! -- Macro: int Lstream_putc (Lstream *STREAM, int C) ! Write out one byte to the stream. This is a macro and so it is ! very efficient. The C argument is only evaluated once but the ! STREAM argument is evaluated more than once. Returns 0 on ! success, -1 on error. ! -- Macro: int Lstream_getc (Lstream *STREAM) ! Read one byte from the stream. This is a macro and so it is very ! efficient. The STREAM argument is evaluated more than once. ! Return value is -1 for EOF or error. ! -- Macro: void Lstream_ungetc (Lstream *STREAM, int C) ! Push one byte back onto the input queue. This will be the next ! byte read from the stream. Any number of bytes can be pushed back ! and will be read in the reverse order they were pushed back--most ! recent first. (This is necessary for consistency--if there are a ! number of bytes that have been unread and I read and unread a ! byte, it needs to be the first to be read again.) This is a macro ! and so it is very efficient. The C argument is only evaluated ! once but the STREAM argument is evaluated more than once. ! -- Function: int Lstream_fputc (Lstream *STREAM, int C) ! -- Function: int Lstream_fgetc (Lstream *STREAM) ! -- Function: void Lstream_fungetc (Lstream *STREAM, int C) ! Function equivalents of the above macros. ! -- Function: Bytecount Lstream_read (Lstream *STREAM, void *DATA, ! Bytecount SIZE) ! Read SIZE bytes of DATA from the stream. Return the number of ! bytes read. 0 means EOF. -1 means an error occurred and no bytes ! were read. ! -- Function: Bytecount Lstream_write (Lstream *STREAM, void *DATA, ! Bytecount SIZE) ! Write SIZE bytes of DATA to the stream. Return the number of ! bytes written. -1 means an error occurred and no bytes were ! written. ! -- Function: void Lstream_unread (Lstream *STREAM, void *DATA, ! Bytecount SIZE) ! Push back SIZE bytes of DATA onto the input queue. The next call ! to `Lstream_read()' with the same size will read the same bytes ! back. Note that this will be the case even if there is other ! pending unread data. ! -- Function: int Lstream_close (Lstream *STREAM) ! Close the stream. All data will be flushed out. ! -- Function: void Lstream_reopen (Lstream *STREAM) ! Reopen a closed stream. This enables I/O on it again. This is not ! meant to be called except from a wrapper routine that reinitializes ! variables and such--the close routine may well have freed some ! necessary storage structures, for example. ! -- Function: void Lstream_rewind (Lstream *STREAM) ! Rewind the stream to the beginning.  ! File: internals.info, Node: Lstream Methods, Prev: Lstream Functions, Up: Lstreams ! 35.4 Lstream Methods ! ==================== ! -- Lstream Method: Bytecount reader (Lstream *STREAM, unsigned char ! *DATA, Bytecount SIZE) ! Read some data from the stream's end and store it into DATA, which ! can hold SIZE bytes. Return the number of bytes read. A return ! value of 0 means no bytes can be read at this time. This may be ! because of an EOF, or because there is a granularity greater than ! one byte that the stream imposes on the returned data, and SIZE is ! less than this granularity. (This will happen frequently for ! streams that need to return whole characters, because ! `Lstream_read()' calls the reader function repeatedly until it has ! the number of bytes it wants or until 0 is returned.) The lstream ! functions do not treat a 0 return as EOF or do anything special; ! however, the calling function will interpret any 0 it gets back as ! EOF. This will normally not happen unless the caller calls ! `Lstream_read()' with a very small size. ! This function can be `NULL' if the stream is output-only. ! -- Lstream Method: Bytecount writer (Lstream *STREAM, const unsigned ! char *DATA, Bytecount SIZE) ! Send some data to the stream's end. Data to be sent is in DATA ! and is SIZE bytes. Return the number of bytes sent. This ! function can send and return fewer bytes than is passed in; in that ! case, the function will just be called again until there is no ! data left or 0 is returned. A return value of 0 means that no ! more data can be currently stored, but there is no error; the data ! will be squirreled away until the writer can accept data. (This is ! useful, e.g., if you're dealing with a non-blocking file ! descriptor and are getting `EWOULDBLOCK' errors.) This function ! can be `NULL' if the stream is input-only. ! -- Lstream Method: int rewinder (Lstream *STREAM) ! Rewind the stream. If this is `NULL', the stream is not seekable. ! -- Lstream Method: int seekable_p (Lstream *STREAM) ! Indicate whether this stream is seekable--i.e. it can be rewound. ! This method is ignored if the stream does not have a rewind ! method. If this method is not present, the result is determined ! by whether a rewind method is present. ! -- Lstream Method: int flusher (Lstream *STREAM) ! Perform any additional operations necessary to flush the data in ! this stream. ! -- Lstream Method: int pseudo_closer (Lstream *STREAM) ! -- Lstream Method: int closer (Lstream *STREAM) ! Perform any additional operations necessary to close this stream ! down. May be `NULL'. This function is called when ! `Lstream_close()' is called or when the stream is ! garbage-collected. When this function is called, all pending data ! in the stream will already have been written out. ! -- Lstream Method: Lisp_Object marker (Lisp_Object LSTREAM, void ! (*MARKFUN) (Lisp_Object)) ! Mark this object for garbage collection. Same semantics as a ! standard `Lisp_Object' marker. This function can be `NULL'. !  ! File: internals.info, Node: Subprocesses, Next: Interface to MS Windows, Prev: Lstreams, Up: Top ! 36 Subprocesses ! *************** ! The fields of a process are: ! `name' ! A string, the name of the process. ! `command' ! A list containing the command arguments that were used to start ! this process. ! `filter' ! A function used to accept output from the process instead of a ! buffer, or `nil'. ! `sentinel' ! A function called whenever the process receives a signal, or `nil'. ! `buffer' ! The associated buffer of the process. ! `pid' ! An integer, the Unix process ID. ! `childp' ! A flag, non-`nil' if this is really a child process. It is `nil' ! for a network connection. ! `mark' ! A marker indicating the position of the end of the last output ! from this process inserted into the buffer. This is often but not ! always the end of the buffer. ! `kill_without_query' ! If this is non-`nil', killing XEmacs while this process is still ! running does not ask for confirmation about killing the process. ! `raw_status_low' ! `raw_status_high' ! These two fields record 16 bits each of the process status ! returned by the `wait' system call. ! `status' ! The process status, as `process-status' should return it. ! `tick' ! `update_tick' ! If these two fields are not equal, a change in the status of the ! process needs to be reported, either by running the sentinel or by ! inserting a message in the process buffer. ! `pty_flag' ! Non-`nil' if communication with the subprocess uses a PTY; `nil' ! if it uses a pipe. ! `infd' ! The file descriptor for input from the process. ! `outfd' ! The file descriptor for output to the process. ! `subtty' ! The file descriptor for the terminal that the subprocess is using. ! (On some systems, there is no need to record this, so the value is ! `-1'.) ! `tty_name' ! The name of the terminal that the subprocess is using, or `nil' if ! it is using pipes. ! * Menu: ! * Ben's separate stderr notes:: Probably obsolete.  ! File: internals.info, Node: Ben's separate stderr notes, Up: Subprocesses ! 36.0.1 Ben's separate stderr notes (probably obsolete) ! ------------------------------------------------------ ! This node contains some notes that Ben kept on his separate subprocess ! workspace. These notes probably describe changes and features that have ! already been included in XEmacs 21.5; somebody should check and/or ask ! Ben. ! ben-separate-stderr-improved-error-trapping ! =========================================== ! this is an old workspace, very close to being done, containing ! * subprocess stderr output can be read separately; needed to fully ! implement call-process with asynch. subprocesses. ! * huge improvements to the internal error-trapping routines (i.e. the ! routines that call Lisp code and trap errors); Lisp code can now be ! called from within redisplay. ! * cleanup and simplification of C-g handling; some things work now ! that never used to. ! * see the ChangeLogs in the workspace. !  ! File: internals.info, Node: Interface to MS Windows, Next: Interface to the X Window System, Prev: Subprocesses, Up: Top ! 37 Interface to MS Windows ! ************************** ! * Menu: ! * Different kinds of Windows environments:: ! * Windows Build Flags:: ! * Windows I18N Introduction:: ! * Modules for Interfacing with MS Windows:: ! * CHANGES from 21.4-windows branch:: Probably obsolete. !  ! File: internals.info, Node: Different kinds of Windows environments, Next: Windows Build Flags, Prev: Interface to MS Windows, Up: Interface to MS Windows ! 37.1 Different kinds of Windows environments ! ============================================ ! (a) operating system (OS) vs. window system vs. Win32 API vs. C runtime library (CRT) vs. and compiler ! ...................................................................................................... ! There are various Windows operating systems (Windows NT, 2000, XP, 95, ! 98, ME, etc.), which come in two basic classes: Windows NT (NT, 2000, ! XP, and all future versions) and 9x (95, 98, ME). 9x-class operating ! systems are a kind of hodgepodge of a 32-bit upper layer on top of a ! 16-bit MS-DOS-compatible lower layer. NT-class operating systems are ! written from the ground up as 32-bit (there are also 64-bit versions ! available now), and provide many more features and much greater ! stability, since there is full memory protection between all processes ! and the between processes and the system. NT-class operating systems ! also provide emulation for DOS programs inside of a "sandbox" (i.e. a ! walled-off environment in which one DOS program can screw up another ! one, but there is theoretically no way for a DOS program to screw up the ! OS itself). From the perspective of XEmacs, the different between NT ! and 9x is very important in Unicode support (not really provided under ! 9x - see `intl-win32.c') and subprocess creation, among other things. ! The operating system provides the framework for accessing files and ! devices and running programs. From the perspective of a program, the ! operating system provides a set of services. At the lowest level, the ! way to call these services is dependent on the processor the OS is ! running on, but a portable interface is provided to C programs through ! functions called "system calls". Under Windows, this interface is ! called the Win32 API, and includes file-manipulation calls such as ! `CreateFile()' and `ReadFile()', process-creation calls such as ! `CreateProcess()', etc. ! This concept of system calls goes back to Unix, where similar ! services are available but through routines with different, simpler ! names, such as `open()', `read()', `fork()', `execve()', etc. In ! addition, Unix provides a higher layer of routines, called the C ! Runtime Library (CRT), which provide higher-level, more convenient ! versions of the same services (e.g. "stream-oriented" file routines ! such as `fopen()' and `fread()') as well as various other utility ! functions, such as string-manipulation routines (e.g. `strcpy()' and ! `strcmp()'). ! For compatibility, a C Runtime Library (CRT) is also provided under ! Windows, which provides a partial implementation of both the Unix CRT ! and the Unix system-call API, implemented using the Win32 API. The CRT ! sources come with Visual C++ (VC++). For example, under VC++ 6, look in ! the CRT/SRC directory, e.g. for me (ben): /Program Files/Microsoft ! Visual Studio/VC98/CRT/SRC. The CRT is provided using either MSVCRT ! (dynamically linked) or `LIBC.LIB' (statically linked). ! The window system provides the framework for creating overlapped ! windows and unifying signals provided by various devices (input devices ! such as the keyboard and mouse, timers, etc.) into a single event queue ! (or "message queue", under Windows). Like the operating system, the ! window system can be viewed from the perspective of a program as a set ! of services provided by an API of function calls. Under Windows, ! window-system services are also available through the Win32 API, while ! under UNIX the window system is typically a separate component (e.g. the ! X Windowing System, aka X Windows or X11). The term "GUI" ("graphical ! user interface") is often used to refer to the services provided by the ! window system, or to a windowing interface provided by a program. ! The Win32 API is implemented by various dynamic libraries, or DLL's. ! The most important are KERNEL32, USER32, and GDI32. KERNEL32 implements ! the basic file-system and process services. USER32 implements the ! fundamental window-system services such as creating windows and handling ! messages. GDI32 implements higher-level drawing capabilities - fonts, ! colors, lines, etc. ! C programs are compiled into executables using a compiler. Under ! Unix, a compiler usually comes as part of the operating system, but not ! under Windows, where the compiler is a separate product. Even under ! Unix, people often install their own compilers, such as gcc. Under ! Windows, the Microsoft-standard compiler is Visual C++ (VC++). ! It is possible to provide an emulation of any API using any other, as ! long as the underlying API provides the suitable functionality. This is ! what Cygwin (www.cygwin.com) does. It provides a fairly complete POSIX ! emulation layer (POSIX is a government standard for Unix behavior) on ! top of MS Windows - in particular, providing the file-system, process, ! tty, and signal semantics that are part of a modern, standard Unix ! operating system. Cygwin does this using its own DLL, `cygwin1.dll', ! which makes calls to the Win32 API services in `kernel32.dll'. Cygwin ! also provides its own implementation of the C runtime library, called ! `newlib' (`libcygwin.a'; `libc.a' and `libm.a' are symlinked to it), ! which is implemented on top of the Unix system calls provided in ! `cygwin1.dll'. In addition, Cygwin provides static import libraries ! that give you direct access to the Win32 API - XEmacs uses this to ! provide GUI support under Cygwin. Cygwin provides a version of GCC ! (the GNU Project C compiler) that is set up to automatically link with ! the appropriate Cygwin libraries. Cygwin also provides, as optional ! components, pre-compiled binaries for a great number of open-source ! programs compiled under the Cygwin environment. This includes all of ! the standard Unix file-system, text-manipulation, development, ! networking, database, etc. utilities, a version of X Windows that uses ! the Win32 API underlyingly (see below), and compilations of nearly all ! other common open-source packages (Apache, TeX, [X]Emacs, Ghostscript, ! GTK, ImageMagick, etc.). ! Similarly, you can emulate the functionality of X Windows using the ! Win32 component of the Win32 API. Cygwin provides a package to do this, ! from the XFree86 project. Other versions of X under Windows also exist, ! such as the MicroImages MI/X server. Each version potentially can come ! comes with its own header and library files, allowing you to compile ! X-Windows programs. ! All of these different operating system and emulation layers can make ! for a fair amount of confusion, so: ! (b) CRT is not the same as VC++ ! ............................... ! Note that the CRT is *NOT* (completely) part of VC++. True, if you link ! statically, the CRT (in the form of `LIBC.LIB', which comes with VC++) ! will be inserted into the executable (.EXE), but otherwise the CRT will ! be separate. The dynamic version of the CRT is provided by `MSVCRT.DLL' ! (or `MSVCRTD.DLL', for debugging), which comes with Windows. Hence, ! it's possible to use a different compiler and still link with MSVCRT - ! which is exactly what MinGW does. ! (c) CRT is not the same as the Win32 API ! ........................................ ! Note also that the CRT is totally separate from the Win32 API. They ! provide different functions and are implemented in different DLL's. ! They are also different levels - the CRT is implemented on top of ! Win32. Sometimes the CRT and Win32 both have their own versions of ! similar concepts, such as locales. These are typically maintained ! separately, and can get out of sync. Do not assume that changing a ! setting in the CRT will have any effect on Win32 API routines using a ! similar concept unless the CRT docs specifically say so. Do not assume ! that behavior described for CRT functions applies to Win32 API or ! vice-versa. Note also that the CRT knows about and is implemented on ! top of the Win32 API, while the Win32 API knows nothing about the CRT. ! (d) MinGW is not the same as Cygwin ! ................................... ! As described in (b), Microsoft's version of the CRT (`MSVCRT.DLL') is ! provided as part of Windows, separate from VC++, which must be ! purchased. Hence, it is possible to write MSVCRT to provide CRT ! services without using VC++. This is what MinGW (www.mingw.org) does - ! it is a port of GCC that will use MSVCRT. The reason one might want to ! do this is (a) it is free, and (b) it does not require a separately ! installed DLL, as Cygwin does. (#### Maybe MinGW targets CRTDLL, not ! MSVCRT? If so, what is CRTDLL, and how does it differ from MSVCRT and ! `LIBC.LIB'?) Primarily, what MinGW provides is patches to GCC (now ! integrated into the standard distribution) and its own header files and ! import libraries that are compatible with MSVCRT. The best way to think ! of MinGW is as simply another Windows compiler, like how there used to ! be Microsoft and Borland compilers. Because MinGW programs use all the ! same libraries as VC++ programs, and hence the same services are ! available, programs that compile under VC++ should compile under MinGW ! with very little change, whereas programs that compile under Cygwin will ! look quite different. ! The confusion between MinGW and Cygwin is the confusion between the ! environment that a compiler runs under and the target environment of a ! program, i.e. the environment that a program is compiled to run under. ! It's theoretically possible, for example, to compile a program under ! Windows and generate a binary that can only be run under Linux, or ! vice-versa - or, for that matter, to use Windows, running on an Intel ! machine to write and a compile a program that will run on the Mac OS, ! running on a PowerPC machine. This is called cross-compiling, and while ! it may seem rather esoteric, it is quite normal when you want to ! generate a program for a machine that you cannot develop on - for ! example, a program that will run on a Palm Pilot. Originally, this is ! how MinGW worked - you needed to run GCC under a Cygwin environment and ! give it appropriate flags, telling it to use the MinGW headers and ! target `MSVCRT.DLL' rather than `CYGWIN1.DLL'. (In fact, Cygwin ! standardly comes with MinGW's header files.) This was because GCC was ! written with Unix in mind and relied on a large amount of Unix-specific ! functionality. To port GCC to Windows without using a POSIX emulation ! layer would mean a lot of rewriting of GCC. Eventually, however, this ! was done, and it GCC was itself compiled using MinGW. The result is ! that currently you can develop MinGW applications either under Cygwin ! or under native Windows. ! (e) Operating system is not the same as window system ! ..................................................... ! As per the above discussion, we can use either Native Windows (the OS ! part of Win32 provided by `KERNEL32.DLL' and the Windows CRT as ! provided by MSVCRT or CLL) or Cygwin to provide operating-system ! functionality, and we can use either Native Windows (the windowing part ! of Win32 as provided by `USER32.DLL' and `GDI32.DLL') or X11 to provide ! window-system functionality. This gives us four possible build ! environments. It's currently possible to build XEmacs with at least ! three of these combinations - as far as I know native + X11 is no ! longer supported, although it used to be (support used to exist in ! `xemacs.mak' for linking with some X11 libraries available from ! somewhere, but it was bit-rotting and you could always use Cygwin; #### ! what happens if we try to compile with MinGW, native OS + X11?). This ! may still seem confusing, so: ! Native OS + native windowing ! We call `CreateProcess()' to run subprocesses (`process-nt.c'), ! and `CreateWindowEx()' to create a top-level window ! (`frame-msw.c'). We use `nt/xemacs.mak' to compile with VC++, ! linking with the Windows CRT (`MSVCRT.DLL' or `LIBC.LIB') and with ! the various Win32 DLL's (`KERNEL32.DLL', `USER32.DLL', ! `GDI32.DLL'); or we use `src/Makefile[.in.in]' to compile with ! GCC, telling it (e.g. -mno-cygwin, see `s/mingw32.h') to use MinGW ! (which will end up linking with `MSVCRT.DLL'), and linking GCC ! with -lshell32 -lgdi32 -luser32 etc. (see `configure.in'). ! Cygwin + native windowing ! We call `fork()'/`execve()' to run subprocesses ! (`process-unix.c'), and `CreateWindowEx()' to create a top-level ! window (`frame-msw.c'). We use `src/Makefile[in.in]' to compile ! with GCC (it will end up linking with `CYGWIN1.DLL') and link GCC ! with -lshell32 -lgdi32 -luser32 etc. (see `configure.in'). ! Cygwin + X11 ! We call `fork()'/`execve()' to run subprocesses ! (`process-unix.c'), and `XtCreatePopupShell()' to create a ! top-level window (`frame-x.c'). We use `src/Makefile[.in.in]' to ! compile with GCC (it will end up linking with `CYGWIN1.DLL') and ! link GCC with -lXt, -lX11, etc. (see `configure.in'). ! Finally, if native OS + X11 were possible, it might look something ! like ! [Native OS + X11] ! We call `CreateProcess()' to run subprocesses (`process-nt.c'), ! and `XtCreatePopupShell()' to create a top-level window ! (`frame-x.c'). We use `nt/xemacs.mak' to compile with VC++, ! linking with the Windows CRT (`MSVCRT.DLL' or `LIBC.LIB') and with ! the various X11 DLL's (`XT.DLL', `XLIB.DLL', etc.); or we use ! `src/Makefile[.in.in]' to compile with GCC, telling it (e.g. ! -mno-cygwin, see `s/mingw32.h') to use MinGW (which will end up ! linking with `MSVCRT.DLL'), and linking GCC with -lXt, -lX11, etc. ! (see `configure.in'). ! One of the reasons that we maintain the ability to build under Cygwin ! and X11 on Windows, when we have native support, is that it allows ! Windows compilers to test under a Unix-like environment.  ! File: internals.info, Node: Windows Build Flags, Next: Windows I18N Introduction, Prev: Different kinds of Windows environments, Up: Interface to MS Windows ! 37.2 Windows Build Flags ! ======================== ! `CYGWIN' ! for Cygwin-only stuff. ! `WIN32_NATIVE' ! Win32 native OS-level stuff (files, process, etc.). Applies ! whenever linking against the native C libraries - i.e. all ! compilations with VC++ and with MINGW, but never Cygwin. ! `HAVE_X_WINDOWS' ! for X Windows (regardless of whether under MS Win) ! `HAVE_MS_WINDOWS' ! MS Windows native windowing system (anything related to the ! appearance of the graphical screen). May or may not apply to any ! of VC++, MINGW, Cygwin. ! ! Finally, there's also the MINGW build environment, which uses GCC ! (similar to Cygwin), but native MS Windows libraries rather than a ! POSIX emulation layer (the Cygwin approach). This environment defines ! WIN32_NATIVE, but also defines MINGW, which is used mostly because uses ! its own include files (related to Cygwin), which have a few things ! messed up. ! Formerly, we had a whole host of flags. Here's the conversion, for ! porting code from GNU Emacs and such: ! Old Constant New Constant ! --------------------------------------------------------------- ! `WINDOWSNT' `WIN32_NATIVE' ! `WIN32' `WIN32_NATIVE' ! `_WIN32' `WIN32_NATIVE' ! `HAVE_WIN32' `WIN32_NATIVE' ! `DOS_NT' `WIN32_NATIVE' ! `HAVE_NTGUI' `WIN32_NATIVE', unless it ends up already bracketed ! by this ! `HAVE_FACES' always true ! `MSDOS' determine whether this code is really specific to ! MS-DOS (and not Windows - e.g. DJGPP code); if so, ! delete the code; otherwise, convert to `WIN32_NATIVE' ! (we do not support MS-DOS w/DOS Extender under XEmacs) ! `__CYGWIN__' `CYGWIN' ! `__CYGWIN32__' `CYGWIN' ! `__MINGW32__' `MINGW'  ! File: internals.info, Node: Windows I18N Introduction, Next: Modules for Interfacing with MS Windows, Prev: Windows Build Flags, Up: Interface to MS Windows ! 37.3 Windows I18N Introduction ============================== ! *Abstract:* This page provides an overview of the aspects of the Win32 ! internationalization API that are relevant to XEmacs, including the ! basic distinction between multibyte and Unicode encodings. Also ! included are pointers to how XEmacs should make use of this API. ! The Win32 API is quite well-designed in its handling of strings ! encoded for various character sets. The API is geared around the idea ! that two different methods of encoding strings should be supported. ! These methods are called multibyte and Unicode, respectively. The ! multibyte encoding is compatible with ASCII strings and is a more ! efficient representation when dealing with strings containing primarily ! ASCII characters, but it has a great number of serious deficiencies and ! limitations, including that it is very difficult and error-prone to work ! with strings in this encoding, and any particular string in a multibyte ! encoding can only contain characters from a very limited number of ! character sets. The Unicode encoding rectifies all of these ! deficiencies, but it is not compatible with ASCII strings (in other ! words, an existing program will not be able to handle the encoded ! strings unless it is explicitly modified to do so), and it takes up ! twice as much memory space as multibyte encodings when encoding a purely ! ASCII string. ! Multibyte encodings use a variable number of bytes (either one or ! two) to represent characters. ASCII characters are also represented by ! a single byte with its high bit not set, and non-ASCII characters are ! represented by one or two bytes, the first of which always has its high ! bit set. (The second byte, when it exists, may or may not have its high ! bit set.) There is no single multibyte encoding. Instead, there is ! generally one encoding per non-ASCII character set. Such an encoding is ! capable of representing (besides ASCII characters, of course) only ! characters from one (or possibly two) particular character sets. ! Multibyte encoding makes processing of strings very difficult. For ! example, given a pointer to the beginning of a character within a ! string, finding the pointer to the beginning of the previous character ! may require backing up all the way to the beginning of the string, and ! then moving forward. Also, an operation such as separating out the ! components of a path by searching for backslashes will fail if it's ! implemented in the simplest (but not multibyte-aware) fashion, because ! it may find what appears to be a backslash, but which is actually the ! second byte of a two-byte character. Also, the limited number of ! character sets that any particular multibyte encoding can represent ! means that loss of data is likely if a string is converted from the ! XEmacs internal format into a multibyte format. ! For these reasons, the C code in XEmacs should never do any sort of ! work with multibyte encoded strings (or with strings in any external ! encoding for that matter). Strings should always be maintained in the ! internal encoding, which is predictable, and converted to an external ! encoding only at the point where the string moves from the XEmacs C ! code and enters a system library function. Similarly, when a string is ! returned from a system library function, it should be immediately ! converted into the internal coding before any operations are done on it. ! Unicode, unlike multibyte encodings, is a fixed-width encoding where ! every character is represented using 16 bits. It is also capable of ! encoding all the characters from all the character sets in common use in ! the world. The predictability and completeness of the Unicode encoding ! makes it a very good encoding for strings that may contain characters ! from many character sets mixed up with each other. At the same time, of ! course, it is incompatible with routines that expect ASCII characters ! and also incompatible with general string manipulation routines, which ! will encounter a great number of what would appear to be embedded nulls ! in the string. It also takes twice as much room to encode strings ! containing primarily ASCII characters. This is why XEmacs does not use ! Unicode or similar encoding internally for buffers. ! The Win32 API cleverly deals with the issue of 8 bit vs. 16 bit ! characters by declaring a type called `"TCHAR"' which specifies a ! generic character, either 8 bits or 16 bits. Generally `TCHAR' is ! defined to be the same as the simple C type `char', unless the ! preprocessor constant `UNICODE' is defined, in which case `TCHAR' is ! defined to be `WCHAR', which is a 16 bit type. Nearly all functions in ! the Win32 API that take strings are defined to take strings that are ! actually arrays of `TCHAR's. There is a type `LPTSTR' which is defined ! to be a string of `TCHAR's and another type `LPCTSTR' which is a const ! string of `TCHAR's. The theory is that any program that uses `TCHAR's ! exclusively to represent characters and does not make assumptions about ! the size of a `TCHAR' or the way that the characters are encoded should ! work transparently regardless of whether the `UNICODE' preprocessor ! constant is defined, which is to say, regardless of whether 8 bit ! multibyte or 16 bit Unicode characters are being used. The way that ! this is actually implemented is that every Win32 API function that takes ! a string as an argument actually maps to one of two functions which are ! suffixed with an `A' (which stands for ANSI, and means multibyte ! strings) or `W' (which stands for wide, and means Unicode strings). ! The mapping is, of course, controlled by the same `UNICODE' ! preprocessor constant. Generally all structures containing strings in ! them actually map to one of two different kinds of structures, with ! either an `A' or a `W' suffix after the structure name. ! Unfortunately, not all of the implementations of the Win32 API ! implement all of the functionality described above. In particular, ! Windows 95 does not implement very much Unicode functionality. It does ! implement functions to convert multibyte-encoded strings to and from ! Unicode strings, and provides Unicode versions of certain low-level ! functions like `ExtTextOut()'. In fact, all of the rest of the Unicode ! versions of API functions are just stubs that return an error. ! Conversely, all versions of Windows NT completely implement all the ! Unicode functionality, but some versions (especially versions before ! Windows NT 4.0) don't implement much of the multibyte functionality. ! For this reason, as well as for general code cleanliness, XEmacs needs ! to be written in such a way that it works with or without the `UNICODE' ! preprocessor constant being defined. ! Getting XEmacs to run when all strings are Unicode primarily ! involves removing any assumptions made about the size of characters. ! Remember what I said earlier about how the point of conversion between ! internally and externally encoded strings should occur at the point of ! entry or exit into or out of a library function. With this in mind, an ! externally encoded string in XEmacs can be treated simply as an ! arbitrary sequence of bytes of some length which has no particular ! relationship to the length of the string in the internal encoding. ! #### The rest of this is *out-of-date* and needs to be written to ! reference the actual coding systems or aliases that we currently use. ! [[ To facilitate this, the enum `external_data_format', which is ! declared in `lisp.h', is expanded to contain three new formats, which ! are `FORMAT_LOCALE', `FORMAT_UNICODE' and `FORMAT_TSTR'. ! `FORMAT_LOCALE' always causes encoding into a multibyte string ! consistent with the encoding of the current locale. The functions to ! handle locales are different under Unix and Windows and locales are a ! process property under Unix and a thread property under Windows, but ! the concepts are basically the same. `FORMAT_UNICODE' of course causes ! encoding into Unicode and `FORMAT_TSTR' logically maps to either ! `FORMAT_LOCALE' or `FORMAT_UNICODE' depending on the `UNICODE' ! preprocessor constant. ! Under Unix the behavior of `FORMAT_TSTR' is undefined and this ! particular format should not be used. Under Windows however ! `FORMAT_TSTR' should be used for pretty much all of the Win32 API ! calls. The other two formats should only be used in particular APIs ! that specifically call for a multibyte or Unicode encoded string ! regardless of the `UNICODE' preprocessor constant. String constants ! that are to be passed directly to Win32 API functions, such as the ! names of window classes, need to be bracketed in their definition with ! a call to the macro `TEXT'. This awfully named macro, which comes out ! of the Win32 API, appropriately makes a string of either regular or ! wide chars, which is to say this string may be prepended with an `L' ! (causing it to be a wide string) depending on the `UNICODE' ! preprocessor constant. ! By the way, if you're wondering what happened to `FORMAT_OS', I ! think that this format should go away entirely because it is too vague ! and should be replaced by more specific formats as they are defined. ]] ! Use Qnative for Unix conversion, Qmswindows_tstr for Windows ... + String constants that are to be passed directly to Win32 API + functions, such as the names of window classes, need to be bracketed in + their definition with a call to the macro XETEXT. This appropriately + makes a string of either regular or wide chars, which is to say this + string may be prepended with an L (causing it to be a wide string) + depending on XEUNICODE_P.  ! File: internals.info, Node: Modules for Interfacing with MS Windows, Next: CHANGES from 21.4-windows branch, Prev: Windows I18N Introduction, Up: Interface to MS Windows ! 37.4 Modules for Interfacing with MS Windows ! ============================================ + There are two different general Windows-related include files in src. ! Uses are approximately: ! `syswindows.h' ! Wrapper around `', including missing defines as ! necessary. Includes stuff needed on both Cygwin and native ! Windows, regardless of window system chosen. Includes definitions ! needed for Unicode conversion/encapsulation, and other ! Mule-related stuff, plus various other prototypes and ! Windows-specific, but not GUI-specific, stuff. ! `console-msw.h' ! Used on both Cygwin and native Windows, but only when native window ! system (as opposed to X) chosen. Includes `syswindows.h'. ! Summary of files: ! `console-msw.h' ! include file for native windowing (otherwise, `console-x.h', etc.) ! `console-msw.c, frame-msw.c, etc.' ! native windowing, as above ! `process-nt.c' ! subprocess support for native OS (otherwise, `process-unix.c') ! `nt.c' ! support routines used under native OS ! `win32.c' ! support routines used under both OS environments ! `syswindows.h' ! support header for both environments ! `nt/xemacs.mak' ! Makefile for VC++ (otherwise, `src/Makefile.in.in') ! `s/windowsnt.h' ! s header for basic native-OS defines, VC++ compiler ! `s/mingw32.h' ! s header for basic native-OS defines, GCC/MinGW compiler ! `s/cygwin.h' ! s header for basic Cygwin defines ! `s/win32-native.h' ! s header for basic native-OS defines, all compilers ! `s/win32-common.h' ! s header for defines for both OS environments ! `intl-win32.c' ! internationalization functions for both OS environments ! `intl-encap-win32.c' ! Unicode encapsulation functions for both OS environments ! `intl-auto-encap-win32.c' ! Auto-generated Unicode encapsulation functions ! `intl-auto-encap-win32.h' ! Auto-generated Unicode encapsulation headers diff -c 'xemacs-21.5.25/info/internals.info-4' 'xemacs-21.5.26/info/internals.info-4' Index: ./info/internals.info-4 *** ./info/internals.info-4 Sun Feb 26 22:31:24 2006 --- ./info/internals.info-4 Sat Apr 1 04:05:23 2006 *************** *** 46,51 **** --- 46,2532 ---- Foundation instead of in the original English.  + File: internals.info, Node: CHANGES from 21.4-windows branch, Prev: Modules for Interfacing with MS Windows, Up: Interface to MS Windows + + 37.5 CHANGES from 21.4-windows branch (probably obsolete) + ========================================================= + + This node contains the `CHANGES-msw' log that Andy Piper kept while he + was maintaining the Windows branch of 21.4. These changes have + (presumably) long since been merged to both 21.4 and 21.5, but let's not + throw the list away yet. + + CHANGES-msw + =========== + + This file briefly describes all mswindows-specific changes to XEmacs in + the OXYMORON series of releases. The mswindows release branch contains + additional changes on top of the mainline XEmacs release. These changes + are deemed necessary for XEmacs to be fully functional under mswindows. + It is not intended that these changes cause problems on UNIX systems, + but they have not been tested on UNIX platforms. Caveat Emptor. + + See the file `CHANGES-release' for a full list of mainline changes. + + to XEmacs 21.4.9 "Informed Management (Windows)" + ================================================ + + * Fix layout of widgets so that the search dialog works. + + * Fix focus capture of widgets under X. + + to XEmacs 21.4.8 "Honest Recruiter (Windows)" + ============================================= + + * All changes from 21.4.6 and 21.4.7. + + * Make sure revert temporaries are not visiting files. Suggested by + Mike Alexander. + + * File renaming fix from Mathias Grimmberger. + + * Fix printer metrics on windows 95 from Jonathan Harris. + + * Fix layout of widgets so that the search dialog works. + + * Fix focus capture of widgets under X. + + * Buffers tab doc fixes from John Palmieri. + + * Sync with FSF custom `:set-after' behavior. + + * Virtual window manager freeze fix from Rick Rankin. + + * Fix various printing problems. + + * Enable windows printing on cygwin. + + to XEmacs 21.4.7 "Economic Science (Windows)" + ============================================= + + * All changes from 21.4.6. + + * Fix problems with auto-revert with noconfirm. + + * Undo autoconf 2.5x changes. + + * Undo 21.4.7 process change. + + to XEmacs 21.4.6 "Common Lisp (Windows)" + + * Made native registry entries match the installer. + + * Fixed mousewheel lockups. + + * Frame iconifcation fix from Adrian Aichner. + + * Fixed some printing problems. + + * Netinstaller updated to support kit revisions. + + * Fixed customize popup menus. + + * Fixed problems with too many dialog popups. + + * Netinstaller fixed to correctly upgrade shortcuts when upgrading + core XEmacs. + + * Fix for virtual window managers from Adrian Aichner. + + * Installer registers all C++ file types. + + * Short-filename fix from Peter Arius. + + * Fix for GC assertions from Adrian Aichner. + + * Winclient DDE client from Alastair Houghton. + + * Fix event assert from Mike Alexander. + + * Warning removal noticed by Ben Wing. + + * Redisplay glyph height fix from Ben Wing. + + * Printer margin fix from Jonathan Harris. + + * Error dialog fix suggested by Thomas Vogler. + + * Fixed revert-buffer to not revert in the case that there is + nothing to be done. + + * Glyph-baseline fix from Nix. + + * Fixed clipping of wide glyphs in non-zero-length extents. + + * Windows build fixes. + + * Fixed `:initial-focus' so that it works. + + to XEmacs 21.4.5 "Civil Service (Windows)" + ========================================== + + * Fixed a scrollbar problem when selecting the frame with focus. + + * Fixed `mswindows-shell-execute' under cygwin. + + * Added a new function `mswindows-cygwin-to-win32-path' for JDE. + + * Added support for dialog-based directory selection. + + * The installer version has been updated to the 21.5 netinstaller. + The 21.5 installer now does proper dde file association and adds + uninstall capability. + + * Handle leak fix from Mike Alexander. + + * New release build script. + +  + File: internals.info, Node: Interface to the X Window System, Next: Dumping, Prev: Interface to MS Windows, Up: Top + + 38 Interface to the X Window System + *********************************** + + Mostly undocumented. + + * Menu: + + * Lucid Widget Library:: An interface to various widget sets. + * Modules for Interfacing with X Windows:: + +  + File: internals.info, Node: Lucid Widget Library, Next: Modules for Interfacing with X Windows, Prev: Interface to the X Window System, Up: Interface to the X Window System + + 38.1 Lucid Widget Library + ========================= + + Lwlib is extremely poorly documented and quite hairy. The author(s) + blame that on X, Xt, and Motif, with some justice, but also sufficient + hypocrisy to avoid drawing the obvious conclusion about their own work. + + The Lucid Widget Library is composed of two more or less independent + pieces. The first, as the name suggests, is a set of widgets. These + widgets are intended to resemble and improve on widgets provided in the + Motif toolkit but not in the Athena widgets, including menubars and + scrollbars. Recent additions by Andy Piper integrate some "modern" + widgets by Edward Falk, including checkboxes, radio buttons, progress + gauges, and index tab controls (aka notebooks). + + The second piece of the Lucid widget library is a generic interface + to several toolkits for X (including Xt, the Athena widget set, and + Motif, as well as the Lucid widgets themselves) so that core XEmacs + code need not know which widget set has been used to build the + graphical user interface. + + * Menu: + + * Generic Widget Interface:: The lwlib generic widget interface. + * Scrollbars:: + * Menubars:: + * Checkboxes and Radio Buttons:: + * Progress Bars:: + * Tab Controls:: + +  + File: internals.info, Node: Generic Widget Interface, Next: Scrollbars, Prev: Lucid Widget Library, Up: Lucid Widget Library + + 38.1.1 Generic Widget Interface + ------------------------------- + + In general in any toolkit a widget may be a composite object. In Xt, + all widgets have an X window that they manage, but typically a complex + widget will have widget children, each of which manages a subwindow of + the parent widget's X window. These children may themselves be + composite widgets. Thus a widget is actually a tree or hierarchy of + widgets. + + For each toolkit widget, lwlib maintains a tree of `widget_values' + which mirror the hierarchical state of Xt widgets (including Motif, + Athena, 3D Athena, and Falk's widget sets). Each `widget_value' has + `contents' member, which points to the head of a linked list of its + children. The linked list of siblings is chained through the `next' + member of `widget_value'. + + +-----------+ + | composite | + +-----------+ + | + | contents + V + +-------+ next +-------+ next +-------+ + | child |----->| child |----->| child | + +-------+ +-------+ +-------+ + | + | contents + V + +-------------+ next +-------------+ + | grand child |----->| grand child | + +-------------+ +-------------+ + + The `widget_value' hierarchy of a composite widget with two simple + children and one composite child. + + The `widget_instance' structure maintains the inverse view of the + tree. As for the `widget_value', siblings are chained through the + `next' member. However, rather than naming children, the + `widget_instance' tree links to parents. + + +-----------+ + | composite | + +-----------+ + A + | parent + | + +-------+ next +-------+ next +-------+ + | child |----->| child |----->| child | + +-------+ +-------+ +-------+ + A + | parent + | + +-------------+ next +-------------+ + | grand child |----->| grand child | + +-------------+ +-------------+ + + The `widget_value' hierarchy of a composite widget with two simple + children and one composite child. + + This permits widgets derived from different toolkits to be updated + and manipulated generically by the lwlib library. For instance + `update_one_widget_instance' can cope with multiple types of widget and + multiple types of toolkit. Each element in the widget hierarchy is + updated from its corresponding `widget_value' by walking the + `widget_value' tree. This has desirable properties. For example, + `lw_modify_all_widgets' is called from `glyphs-x.c' and updates all the + properties of a widget without having to know what the widget is or + what toolkit it is from. Unfortunately this also has its hairy + properties; the lwlib code quite complex. And of course lwlib has to + know at some level what the widget is and how to set its properties. + + The `widget_instance' structure also contains a pointer to the root + of its tree. Widget instances are further confi + +  + File: internals.info, Node: Scrollbars, Next: Menubars, Prev: Generic Widget Interface, Up: Lucid Widget Library + + 38.1.2 Scrollbars + ----------------- + +  + File: internals.info, Node: Menubars, Next: Checkboxes and Radio Buttons, Prev: Scrollbars, Up: Lucid Widget Library + + 38.1.3 Menubars + --------------- + +  + File: internals.info, Node: Checkboxes and Radio Buttons, Next: Progress Bars, Prev: Menubars, Up: Lucid Widget Library + + 38.1.4 Checkboxes and Radio Buttons + ----------------------------------- + +  + File: internals.info, Node: Progress Bars, Next: Tab Controls, Prev: Checkboxes and Radio Buttons, Up: Lucid Widget Library + + 38.1.5 Progress Bars + -------------------- + +  + File: internals.info, Node: Tab Controls, Prev: Progress Bars, Up: Lucid Widget Library + + 38.1.6 Tab Controls + ------------------- + +  + File: internals.info, Node: Modules for Interfacing with X Windows, Prev: Lucid Widget Library, Up: Interface to the X Window System + + 38.2 Modules for Interfacing with X Windows + =========================================== + + Emacs.ad.h + + A file generated from `Emacs.ad', which contains XEmacs-supplied + fallback resources (so that XEmacs has pretty defaults). + + EmacsFrame.c + EmacsFrame.h + EmacsFrameP.h + + These modules implement an Xt widget class that encapsulates a frame. + This is for ease in integrating with Xt. The EmacsFrame widget covers + the entire X window except for the menubar; the scrollbars are + positioned on top of the EmacsFrame widget. + + *Warning:* Abandon hope, all ye who enter here. This code took an + ungodly amount of time to get right, and is likely to fall apart + mercilessly at the slightest change. Such is life under Xt. + + EmacsManager.c + EmacsManager.h + EmacsManagerP.h + + These modules implement a simple Xt manager (i.e. composite) widget + class that simply lets its children set whatever geometry they want. + It's amazing that Xt doesn't provide this standardly, but on second + thought, it makes sense, considering how amazingly broken Xt is. + + EmacsShell-sub.c + EmacsShell.c + EmacsShell.h + EmacsShellP.h + + These modules implement two Xt widget classes that are subclasses of + the TopLevelShell and TransientShell classes. This is necessary to deal + with more brokenness that Xt has sadistically thrust onto the backs of + developers. + + xgccache.c + xgccache.h + + These modules provide functions for maintenance and caching of GC's + (graphics contexts) under the X Window System. This code is junky and + needs to be rewritten. + + select-msw.c + select-x.c + select.c + select.h + + This module provides an interface to the X Window System's concept of + "selections", the standard way for X applications to communicate with + each other. + + xintrinsic.h + xintrinsicp.h + xmmanagerp.h + xmprimitivep.h + + These header files are similar in spirit to the `sys*.h' files and + buffer against different implementations of Xt and Motif. + + * `xintrinsic.h' should be included in place of `'. + + * `xintrinsicp.h' should be included in place of `'. + + * `xmmanagerp.h' should be included in place of `'. + + * `xmprimitivep.h' should be included in place of `'. + + xmu.c + xmu.h + + These files provide an emulation of the Xmu library for those systems + (i.e. HPUX) that don't provide it as a standard part of X. + + ExternalClient-Xlib.c + ExternalClient.c + ExternalClient.h + ExternalClientP.h + ExternalShell.c + ExternalShell.h + ExternalShellP.h + extw-Xlib.c + extw-Xlib.h + extw-Xt.c + extw-Xt.h + + These files provide the "external widget" interface, which allows an + XEmacs frame to appear as a widget in another application. To do this, + you have to configure with `--external-widget'. + + `ExternalShell*' provides the server (XEmacs) side of the connection. + + `ExternalClient*' provides the client (other application) side of + the connection. These files are not compiled into XEmacs but are + compiled into libraries that are then linked into your application. + + `extw-*' is common code that is used for both the client and server. + + Don't touch this code; something is liable to break if you do. + +  + File: internals.info, Node: Dumping, Next: Future Work, Prev: Interface to the X Window System, Up: Top + + 39 Dumping + ********** + + * Menu: + + * Dumping Justification:: + * Overview:: + * Data descriptions:: + * Dumping phase:: + * Reloading phase:: + * Remaining issues:: + +  + File: internals.info, Node: Dumping Justification, Next: Overview, Prev: Dumping, Up: Dumping + + 39.1 Dumping Justification + ========================== + + The C code of XEmacs is just a Lisp engine with a lot of built-in + primitives useful for writing an editor. The editor itself is written + mostly in Lisp, and represents around 100K lines of code. Loading and + executing the initialization of all this code takes a bit a time (five + to ten times the usual startup time of current xemacs) and requires + having all the lisp source files around. Having to reload them each + time the editor is started would not be acceptable. + + The traditional solution to this problem is called dumping: the build + process first creates the lisp engine under the name `temacs', then + runs it until it has finished loading and initializing all the lisp + code, and eventually creates a new executable called `xemacs' including + both the object code in `temacs' and all the contents of the memory + after the initialization. + + This solution, while working, has a huge problem: the creation of the + new executable from the actual contents of memory is an extremely + system-specific process, quite error-prone, and which interferes with a + lot of system libraries (like malloc). It is even getting worse + nowadays with libraries using constructors which are automatically + called when the program is started (even before `main()') which tend to + crash when they are called multiple times, once before dumping and once + after (IRIX 6.x `libz.so' pulls in some C++ image libraries thru + dependencies which have this problem). Writing the dumper is also one + of the most difficult parts of porting XEmacs to a new operating system. + Basically, `dumping' is an operation that is just not officially + supported on many operating systems. + + The aim of the portable dumper is to solve the same problem as the + system-specific dumper, that is to be able to reload quickly, using only + a small number of files, the fully initialized lisp part of the editor, + without any system-specific hacks. + +  + File: internals.info, Node: Overview, Next: Data descriptions, Prev: Dumping Justification, Up: Dumping + + 39.2 Overview + ============= + + The portable dumping system has to: + + 1. At dump time, write all initialized, non-quickly-rebuildable data + to a file [Note: currently named `xemacs.dmp', but the name will + change], along with all information needed for the reloading. + + 2. When starting xemacs, reload the dump file, relocate it to its new + starting address if needed, and reinitialize all pointers to this + data. Also, rebuild all the quickly rebuildable data. + + Note: As of 21.5.18, the dump file has been moved inside of the + executable, although there are still problems with this on some systems. + +  + File: internals.info, Node: Data descriptions, Next: Dumping phase, Prev: Overview, Up: Dumping + + 39.3 Data descriptions + ====================== + + The more complex task of the dumper is to be able to write memory blocks + on the heap (lisp objects, i.e. lrecords, and C-allocated memory, such + as structs and arrays) to disk and reload them at a different address, + updating all the pointers they include in the process. This is done by + using external data descriptions that give information about the layout + of the blocks in memory. + + The specification of these descriptions is in lrecord.h. A + description of an lrecord is an array of struct memory_description. + Each of these structs include a type, an offset in the block and some + optional parameters depending on the type. For instance, here is the + string description: + + static const struct memory_description string_description[] = { + { XD_BYTECOUNT, offsetof (Lisp_String, size) }, + { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT(0, 1) }, + { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, + { XD_END } + }; + + The first line indicates a member of type Bytecount, which is used by + the next, indirect directive. The second means "there is a pointer to + some opaque data in the field `data'". The length of said data is + given by the expression `XD_INDIRECT(0, 1)', which means "the value in + the 0th line of the description (welcome to C) plus one". The third + line means "there is a Lisp_Object member `plist' in the Lisp_String + structure". `XD_END' then ends the description. + + This gives us all the information we need to move around what is + pointed to by a memory block (C or lrecord) and, by transitivity, + everything that it points to. The only missing information for dumping + is the size of the block. For lrecords, this is part of the + lrecord_implementation, so we don't need to duplicate it. For C blocks + we use a struct sized_memory_description, which includes a size field + and a pointer to an associated array of memory_description. + +  + File: internals.info, Node: Dumping phase, Next: Reloading phase, Prev: Data descriptions, Up: Dumping + + 39.4 Dumping phase + ================== + + Dumping is done by calling the function `pdump()' (in `dumper.c') which + is invoked from Fdump_emacs (in `emacs.c'). This function performs a + number of tasks. + + * Menu: + + * Object inventory:: + * Address allocation:: + * The header:: + * Data dumping:: + * Pointers dumping:: + +  + File: internals.info, Node: Object inventory, Next: Address allocation, Prev: Dumping phase, Up: Dumping phase + + 39.4.1 Object inventory + ----------------------- + + The first task is to build the list of the objects to dump. This + includes: + + * lisp objects + + * other memory blocks (C structures, arrays. etc) + + We end up with one `pdump_block_list_elt' per object group (arrays + of C structs are kept together) which includes a pointer to the first + object of the group, the per-object size and the count of objects in the + group, along with some other information which is initialized later. + + These entries are linked together in `pdump_block_list' structures + and can be enumerated thru either: + + 1. the `pdump_object_table', an array of `pdump_block_list', one per + lrecord type, indexed by type number. + + 2. the `pdump_opaque_data_list', used for the opaque data which does + not include pointers, and hence does not need descriptions. + + 3. the `pdump_desc_table', which is a vector of + `memory_description'/`pdump_block_list' pairs, used for non-opaque + C memory blocks. + + This uses a marking strategy similar to the garbage collector. Some + differences though: + + 1. We do not use the mark bit (which does not exist for generic + memory blocks anyway); we use a big hash table instead. + + 2. We do not use the mark function of lrecords but instead rely on the + external descriptions. This happens essentially because we need to + follow pointers to generic memory blocks and opaque data in + addition to Lisp_Object members. + + This is done by `pdump_register_object()', which handles Lisp_Object + variables, and `pdump_register_block()' which handles generic memory + blocks (C structures, arrays, etc.), which both delegate the + description management to `pdump_register_sub()'. + + The hash table doubles as a map object to pdump_block_list_elmt (i.e. + allows us to look up a pdump_block_list_elmt with the object it points + to). Entries are added with `pdump_add_block()' and looked up with + `pdump_get_block()'. There is no need for entry removal. The hash + value is computed quite simply from the object pointer by + `pdump_make_hash()'. + + The roots for the marking are: + + 1. the `staticpro''ed variables (there is a special + `staticpro_nodump()' call for protected variables we do not want to + dump). + + 2. the Lisp_Object variables registered via + `dump_add_root_lisp_object' (`staticpro()' is equivalent to + `staticpro_nodump()' + `dump_add_root_lisp_object()'). + + 3. the data-segment memory blocks registered via `dump_add_root_block' + (for blocks with relocatable pointers), or `dump_add_opaque' (for + "opaque" blocks with no relocatable pointers; this is just a + shortcut for calling `dump_add_root_block' with a NULL + description). + + 4. the pointer variables registered via `dump_add_root_block_ptr', + each of which points to a block of heap memory (generally a C + structure or array). Note that `dump_add_root_block_ptr' is not + technically necessary, as a pointer variable can be seen as a + special case of a data-segment memory block and registered using + `dump_add_root_block'. Doing it this way, however, would require + another level of static structures declared. Since pointer + variables are quite common, `dump_add_root_block_ptr' is provided + for convenience. Note also that internally we have to treat it + separately from `dump_add_root_block' rather than writing the + former as a call to the latter, since we don't have support for + creating and using memory descriptions on the fly - they must all + be statically declared in the data-segment. + + This does not include the GCPRO'ed variables, the specbinds, the + catchtags, the backlist, the redisplay or the profiling info, since we + do not want to rebuild the actual chain of lisp calls which end up to + the dump-emacs call, only the global variables. + + Weak lists and weak hash tables are dumped as if they were their + non-weak equivalent (without changing their type, of course). This has + not yet been a problem. + +  + File: internals.info, Node: Address allocation, Next: The header, Prev: Object inventory, Up: Dumping phase + + 39.4.2 Address allocation + ------------------------- + + The next step is to allocate the offsets of each of the objects in the + final dump file. This is done by `pdump_allocate_offset()' which is + called indirectly by `pdump_scan_by_alignment()'. + + The strategy to deal with alignment problems uses these facts: + + 1. real world alignment requirements are powers of two. + + 2. the C compiler is required to adjust the size of a struct so that + you can have an array of them next to each other. This means you + can have an upper bound of the alignment requirements of a given + structure by looking at which power of two its size is a multiple. + + 3. the non-variant part of variable size lrecords has an alignment + requirement of 4. + + Hence, for each lrecord type, C struct type or opaque data block the + alignment requirement is computed as a power of two, with a minimum of + 2^2 for lrecords. `pdump_scan_by_alignment()' then scans all the + `pdump_block_list_elmt''s, the ones with the highest requirements + first. This ensures the best packing. + + The maximum alignment requirement we take into account is 2^8. + + `pdump_allocate_offset()' only has to do a linear allocation, + starting at offset 256 (this leaves room for the header and keeps the + alignments happy). + +  + File: internals.info, Node: The header, Next: Data dumping, Prev: Address allocation, Up: Dumping phase + + 39.4.3 The header + ----------------- + + The next step creates the file and writes a header with a signature and + some random information in it. The `reloc_address' field, which + indicates at which address the file should be loaded if we want to avoid + post-reload relocation, is set to 0. It then seeks to offset 256 (base + offset for the objects). + +  + File: internals.info, Node: Data dumping, Next: Pointers dumping, Prev: The header, Up: Dumping phase + + 39.4.4 Data dumping + ------------------- + + The data is dumped in the same order as the addresses were allocated by + `pdump_dump_data()', called from `pdump_scan_by_alignment()'. This + function copies the data to a temporary buffer, relocates all pointers + in the object to the addresses allocated in step Address Allocation, + and writes it to the file. Using the same order means that, if we are + careful with lrecords whose size is not a multiple of 4, we are ensured + that the object is always written at the offset in the file allocated + in step Address Allocation. + +  + File: internals.info, Node: Pointers dumping, Prev: Data dumping, Up: Dumping phase + + 39.4.5 Pointers dumping + ----------------------- + + A bunch of tables needed to reassign properly the global pointers are + then written. They are: + + 1. the pdump_root_block_ptrs dynarr + + 2. the pdump_opaques dynarr + + 3. a vector of all the offsets to the objects in the file that + include a description (for faster relocation at reload time) + + 4. the pdump_root_objects and pdump_weak_object_chains dynarrs. + + For each of the dynarrs we write both the pointer to the variables + and the relocated offset of the object they point to. Since these + variables are global, the pointers are still valid when restarting the + program and are used to regenerate the global pointers. + + The `pdump_weak_object_chains' dynarr is a special case. The + variables it points to are the head of weak linked lists of lisp objects + of the same type. Not all objects of this list are dumped so the + relocated pointer we associate with them points to the first dumped + object of the list, or Qnil if none is available. This is also the + reason why they are not used as roots for the purpose of object + enumeration. + + Some very important information like the `staticpros' and + `lrecord_implementations_table' are handled indirectly using + `dump_add_opaque' or `dump_add_root_block_ptr'. + + This is the end of the dumping part. + +  + File: internals.info, Node: Reloading phase, Next: Remaining issues, Prev: Dumping phase, Up: Dumping + + 39.5 Reloading phase + ==================== + + 39.5.1 File loading + ------------------- + + The file is mmap'ed in memory (which ensures a PAGESIZE alignment, at + least 4096), or if mmap is unavailable or fails, a 256-bytes aligned + malloc is done and the file is loaded. + + Some variables are reinitialized from the values found in the header. + + The difference between the actual loading address and the + reloc_address is computed and will be used for all the relocations. + + 39.5.2 Putting back the pdump_opaques + ------------------------------------- + + The memory contents are restored in the obvious and trivial way. + + 39.5.3 Putting back the pdump_root_block_ptrs + --------------------------------------------- + + The variables pointed to by pdump_root_block_ptrs in the dump phase are + reset to the right relocated object addresses. + + 39.5.4 Object relocation + ------------------------ + + All the objects are relocated using their description and their offset + by `pdump_reloc_one'. This step is unnecessary if the reloc_address is + equal to the file loading address. + + 39.5.5 Putting back the pdump_root_objects and pdump_weak_object_chains + ----------------------------------------------------------------------- + + Same as Putting back the pdump_root_block_ptrs. + + 39.5.6 Reorganize the hash tables + --------------------------------- + + Since some of the hash values in the lisp hash tables are + address-dependent, their layout is now wrong. So we go through each of + them and have them resorted by calling `pdump_reorganize_hash_table'. + +  + File: internals.info, Node: Remaining issues, Prev: Reloading phase, Up: Dumping + + 39.6 Remaining issues + ===================== + + The build process will have to start a post-dump xemacs, ask it the + loading address (which will, hopefully, be always the same between + different xemacs invocations) [[unfortunately, not true on Linux with + the ExecShield feature]] and relocate the file to the new address. + This way the object relocation phase will not have to be done, which + means no writes in the objects and that, because of the use of mmap, the + dumped data will be shared between all the xemacs running on the + computer. + + Some executable signature will be necessary to ensure that a given + dump file is really associated with a given executable, or random + crashes will occur. Maybe a random number set at compile or configure + time thru a define. This will also allow for having + differently-compiled xemacsen on the same system (mule and no-mule + comes to mind). + + The DOC file contents should probably end up in the dump file. + +  + File: internals.info, Node: Future Work, Next: Future Work Discussion, Prev: Dumping, Up: Top + + 40 Future Work + ************** + + * Menu: + + * Future Work -- General Suggestions:: + * Future Work -- Elisp Compatibility Package:: + * Future Work -- Drag-n-Drop:: + * Future Work -- Standard Interface for Enabling Extensions:: + * Future Work -- Better Initialization File Scheme:: + * Future Work -- Keyword Parameters:: + * Future Work -- Property Interface Changes:: + * Future Work -- Toolbars:: + * Future Work -- Menu API Changes:: + * Future Work -- Removal of Misc-User Event Type:: + * Future Work -- Mouse Pointer:: + * Future Work -- Extents:: + * Future Work -- Version Number and Development Tree Organization:: + * Future Work -- Improvements to the `xemacs.org' Website:: + * Future Work -- Keybindings:: + * Future Work -- Byte Code Snippets:: + * Future Work -- Lisp Stream API:: + * Future Work -- Multiple Values:: + * Future Work -- Macros:: + * Future Work -- Specifiers:: + * Future Work -- Display Tables:: + * Future Work -- Making Elisp Function Calls Faster:: + * Future Work -- Lisp Engine Replacement:: + * Future Work -- Better Rendering Support:: + +  + File: internals.info, Node: Future Work -- General Suggestions, Next: Future Work -- Elisp Compatibility Package, Prev: Future Work, Up: Future Work + + 40.1 Future Work - General Suggestions + ====================================== + + Jamie Zawinski's XEmacs Wishlist + -------------------------------- + + This document is based on Jamie Zawinski's xemacs wishlist + (http://www.jwz.org/doc/xemacs-wishlist.html). Throughout this + page, "I" refers to Jamie. + + The list has been substantially reformatted and edited to fit the + needs of this site. If you have any soul at all, you'll go check + out the original. OK? You should also check out some other + wishlists + (http://www.xemacs.org/Releases/Public-21.2/execution.html#wishlists). + + About the List + .............. + + I've ranked these (roughly) from easiest to hardest; though of all of + them, I think the debugger improvements would be the most useful. I + think the combination of emacs+gdb is the best Unix development + environment currently available, but it's still lamentably primitive + and extremely frustrating (much like Unix itself), especially if you + know what kinds of features more modern integrated debuggers have. + + XEmacs Wishlist + ............... + + *Improve the keyboard macro system.* + Keyboard macros are one of the most useful concepts that emacs has + to offer, but there's room for improvement. + + *Make it possible to embed one macro inside of another.* + Often, I'll define a keyboard macro, and then realize that + I've left something out, or that there's more that I need to + do; for example, I may define a macro that does something to + the current line, and then realize that I want to apply it to + a lot of lines. So, I'd like this to work: + + C-x ( + ; start macro #1 + ... + ; (do stuff) + C-x ) + ; done with macro #1 + ... + ; (do stuff) + C-x ( + ; start macro #2 + C-x e + ; execute macro #1 (splice it into macro #2) + C-s foo + ; move forward to the next spot + C-x ) + ; done with macro #2 + C-u 1000 C-x e + ; apply the new macro + + That is, simply, one should be able to wrap new text around an + existing macro. I can't tell you how many times I've defined + a complex macro but left out the "`C-n C-a'" at the end... + + Yes, you can accomplish this with M-x name-last-kbd-macro, but + that's a pain. And it's also more permanent than I'd often + like. + + *Make it possible to correct errors when defining a macro.* + Right now, the act of defining a macro stops if you get an + error while defining it, and all of the characters you've + already typed into the macro are gone. It needn't be that + way. I think that, when that first error occurs, the user + should be given the option of taking the last command off of + the macro and trying again. + + The macro-reader knows where the bounds of multi-character + command sequences are, and it could even keep track of the + corresponding undo records; rubbing out the previous entry on + the macro could also undo any changes that command had made. + (This should also work if the macro spans multiple buffers, + and should restore window configurations as well.) + + You'd want multi-level undo for this as well, so maybe the + way to go would be to add some new key sequence which was + used only as the back-up-inside-a-keyboard-macro-definition + command. + + I'm not totally sure that this would end up being very usable; + maybe it would be too hard to deal with. Which brings us to: + + *Make it possible to edit a keyboard macro after it has been defined.* + I only just discovered `edit-kbd-macro' (`C-x C-k'). It is + very, very cool. + + The trick it does of showing the command which will be + executed is somewhat error-prone, as it can only look up + things in the current map or the global map; if the macro + changed buffers, it wouldn't be displaying the right + commands. (One of the things I often use macros for is + operating on many files at once, by bringing up a dired buffer + of those files, editing them, and then moving on to the next.) + + However, if the act of recording a macro also kept track of + the actual commands that had gotten executed, it could make + use of that info as well. + + Another way of editing a macro, other than as text in a + buffer, would be to have a command which single-steps a + macro: you would lean on the space bar to watch the macro + execute one character (command?) at a time, and then when + you reached the point you wanted to change, you could do some + gesture to either: insert some keystrokes into the middle of + the macro and then continue; or to replace the rest of the + macro from here to the end; or something. + + Another similar hack might be to convert a macro to the + equivalent lisp code, so that one could tweak it later in + ways that would be too hard to do from the keyboard (wrapping + parts of it in `while' loops or something.) (`M-x + insert-kbd-macro' isn't really what I'm talking about here: I + mean insert the list of commands, not the list of keystrokes.) + + *Save my wrists!* + In the spirit of the ``teach-extended-commands-p'' variable, it + would be interesting if emacs would keep track of what are the + commands I use most often, perhaps grouped by proximity or mode - + it would then be more obvious which commands were most likely + candidates for placement on a toolbar, or popup menu, or just a + more convenient key binding. + + Bonus points if it figures out that I type "`bt\n'" and + "`ret\ny\n'" into my `*gdb*' buffer about a hundred thousand times + a day. + + *XmCreateFileSelectionBox* + The thing that "File/Open..." pops up has excellent _hack_ value, + but as a user interface, it's an abomination. Isn't it time + someone added a real file selection dialog already? (For the + Motifly-challenged, the Athena-based file selector that GhostView + uses seems adequate.) + + *Improve the toolbar system.* + It's great that XEmacs has a toolbar, but it's damn near impossible + to customize it. + + *Make it easy to define new toolbar buttons.* + Currently, to define a toolbar button that has a text + equivalent, one must edit a pixmap, and put the text there! + That's prohibitive. One should be able to add some kind of + generic toolbar button, with a plain icon or none at all, but + which has a text label, without having to use a paint program. + + *Make it easy to have customized, mode-local toolbars.* + In my `c-mode-hook', for example, I can add a couple of new + keybindings, and delete a few others, and to do that, I don't + have to duplicate the entire definition of the `c-mode-map'. + Making mode-local additions and subtractions to the toolbars + should be as easy. + + *Make it easy to have customized, mode-local popup menus.* + The same situation holds for the right-mouse-button popup + menu; one should be able to add new commands to those menus + without difficulty. One problem is that each mode which does + have a popup menu implements it in a different way... + + *Make the External Widget work.* + About half of the work is done to make a replacement for the + `XmText' widget which offloads editing responsibility to an + external Emacs process. Someone should finish that. The benefit + here would be that then, any Motif program could be linked such + that all editing happened with a real Emacs behind it. (If you're + Athena-minded, flavor with `Text' instead of `XmText' - it's + probably easy to make it work with both.) + + The part of this that is done already is the ability to run an + Emacs screen on a Window object that has been created by another + process (this is what the `ExternalClient.c' and `ExternalShell.c' + stuff is.) What is left to be done is, adding the + text-widget-editor aspects of this. + + First, the emacs screen being displayed on that window would have + to be one without a modeline, and one which behaved sensibly in + the context of "I am a small multi-line text area embedded in a + dialog box" as opposed to "I am a full-on text editor and lord of + all that I survey." + + Second, the API that the (non-emacs-aware) user of the `XmText' + widget expects would need to be implemented: give the caller the + ability to pull the edited text string back out, and so on. The + idea here being, hooking up emacs as the widget editor should be as + transparent as possible. + + *Bring the debugger interface into the eighties.* + Some of you may have seen my `gdb-highlight.el' package, that I + posted to gnu.emacs.sources last month. I think it's really cool, + but there should be a lot more work in that direction. For those + of you who haven't seen it, what it does is watch text that gets + inserted into the `*gdb*' buffer and make very nearly everything + be clickable and have a context-sensitive menu. Generally, the + types that are noticed are: + + * function names; + + * variable and parameter names; + + * structure slots; + + * source file names; + + * type names; + + * breakpoint numbers; + + * stack frame numbers. + + Any time one of those objects is presented in the `*gdb*' buffer, + it is mousable. Clicking middle button on it takes some default + action (edits the function, selects the stack frame, disables the + breakpoint, ...) Clicking the right button pops up a menu of + commands, including commands specific to the object under the + mouse, and/or other objects on the same line. + + So that's all well and good, and I get far more joy out of what + this code does for me than I expected, but there are still a bunch + of limitations. The debugger interface needs to do much, much more. + + *Make gdbsrc-mode not suck.* + The idea behind `gdbsrc-mode' is on the side of the angels: + one should be able to focus on the source code and not on the + debugger buffer, absolutely. But the implementation is just + awful. + + First and foremost, it should not change "modes" (in the more + general sense). Any commands that it defines should be on + keys which are exclusively used for that purpose, not keys + which are normally self-inserting. I can't be the only person + who usually has occasion to actually _edit_ the sources which + the debugger has chosen to display! Switching into and out of + `gdbsrc-mode' is prohibitive. + + I want to be looking at my sources at all times, yet I don't + want to have to give up my source-editing gestures. I think + the right way to accomplish this is to put the gdbsrc + commands on the toolbar and on popup menus; or to let the + user define their own keys (I could see devoting my + key to "step", or something common like that.) + + Also it's extremely frustrating that one can't turn off + gdbsrc mode once it has been loaded, without exiting and + restarting emacs; that alone means that I'd probably never + take the time to learn how to use it, without first having + taken the time to repair it... + + *Make it easier access to variable values.* + I want to be able to double-click on a variable name to + highlight it, and then drag it to the debugger window to have + its value printed. + + I want gestures that let me write as well as read: for + example, to store value A into slot B. + + *Make all breakpoints visible.* + Any time there is a running gdb which has breakpoints, the + buffers holding the lines on which those breakpoints are set + should have icons in them. These icons should be + context-sensitive: I should be able to pop up a menu to + enable or disable them, to delete them, to change their + commands or conditions. + + I should also be able to _move_ them. It's annoying when you + have a breakpoint with a complex condition or command on it, + and then you realize that you really want it to be at a + different location. I want to be able to drag-and-drop the + icon to its new home. + + *Make a debugger status display window.* + * I want a window off to the side that shows persistent + information - it should have a pane which is a + drag-editable, drag-reorderable representation of the + elements on gdb's "display" list; they should be + displayed here instead of being just dumped in with the + rest of the output in the `*gdb*' buffer. + + * I want a pane that displays the current call-stack and + nothing else. I want a pane that displays the arguments + and locals of the currently-selected frame and nothing + else. I want these both to update as I move around on + the stack. + + * Since the unfortunate reality is that excavating this + information from gdb can be slow, it would be a good + idea for these panes to have a toggle button on them + which meant "stop updating", so that when I want to move + fast, I can, but I can easily get the display back when + I need it again. + + The reason for all of this is that I spend entirely too much + time scrolling around in the `*gdb*' buffer; with + gdb-highlight, I can just click on a line in the backtrace + output to go to that frame, but I find that I spend a lot of + time _looking_ for that backtrace: since it's mixed in with + all the other random output, I waste time looking around for + things (and usually just give up and type "`bt'" again, then + thrash around as the buffer scrolls, and I try to find the + lower frames that I'm interested in, as they have invariably + scrolled off the window already... + + *Save and restore breakpoints across emacs/debugger sessions.* + This would be especially handy given that gdb leaks like a + sieve, and with a big program, I only get a few dozen + relink-and-rerun attempts before gdb has blown my swap space. + + *Keep breakpoints in sync with source lines.* + When a program is recompiled and then reloaded into gdb, the + breakpoints often end up in less-than-useful places. For + example, when I edit text which occurs in a file anywhere + before a breakpoint, emacs is aware that the line of the bp + hasn't changed, but just that it is in a different place + relative to the top of the file. Gdb doesn't know this, so + your breakpoints end up getting set in the wrong places + (usually the maximally inconvenient places, like _after_ a + loop instead of _inside_ it). But emacs knows, so emacs should + inform the debugger, and move the breakpoints back to the + places they were intended to be. + + (Possibly the OOBR stuff does some of this, but can't tell, because + I've never been able to get it to do anything but beep at me and + mumble about environments. I find it pretty funny that the manual + keeps explaining to me how intuitive it is, without actually + giving me a clue how to launch it...) + + *Add better dialog box features.* + It'd be nice to be able to create more complex dialog boxes from + emacs-lisp: ones with checkboxes, radio button groups, text + fields, and popup menus. + + *Add embeddable dialog boxes.* + One of the things that the now-defunct Energize code (the C side of + it, that is) could do was embed a dialog box between the toolbar + and the main text area - buffers could have control panels + associated with them, that had all kinds of complex behavior. + + *Make the mark-stack be visible.* + You know, I've encountered people who have been using emacs for + years, and never use the mark stack for navigation. I can't live + without it; "`C-u C-SPC'" is among my most common gestures. + + 1. It would be a lot easier to realize what's going to happen + if the marks on the mark stack were visible. They could be + displayed as small "caret" glyphs, for example; something + large enough to be visible, but not easily mistaken for a + character or for the cursor. + + 2. The marks and the selected region should be visible in the + scrollbar as well - I don't remember where I first saw this + idea, but it's very cool: there's a second, + less-strongly-rendered "thumb" in the scrollbar which + indicates the position and size of the selection; and there + are tiny tick-marks which indicate the positions of the saved + points. + + 3. Markers which are in registers (`point-to-register', `C-x + /') should be displayed differently (more prominent.) + + 4. It'd be cool if you could pick up markers and move them + around, to adjust the points you'll be coming back to later. + + *Write a new garbage collector.* + The emacs GC is very primitive; it is also, fortunately, a rather + well isolated module, and it would not be a very big task to swap + it with a new one (once that new one was written, that is.) Someone + should go bone up on modern GC techniques, and then just dive right + in... + + *Add support for lexical scope to the emacs-lisp runtime.* + Yadda yadda, this list goes to eleven. + + Subject: *Re: XEmacs wishlist* Date: Wed, 14 May 1997 16:18:23 -0700 + From: Jamie Zawinski Newsgroups: comp.emacs.xemacs, + comp.emacs + + Andreas Schwab wrote: + + _Use `C-u C-x (': _ + + _start-kbd-macro: + Non-nil arg (prefix arg) means append to last macro defined; This + begins by re-executing that macro as if you typed it again. _ + + Cool, I didn't know it did that... + + But it only lets you append. I often want to prepend, or embed the + macro multiple times (motion 1, C-x e, motion 2, C-x e, motion 3.) + + 21.2 Showstoppers + ----------------- + + Author: Ben Wing (mailto:ben@xemacs.org) + + DISTRIBUTION ISSUES + + A. Unified Source Tarball. + + Packages go under root/lib/xemacs/xemacs-packages and no one ever has + to mess with -package-path and the result can be moved from one + directory to another pre- or post-install. + + Unified Binary Tarballs with Packages. + + Same principles as above. + + If people complain, we can also provide split binary tarballs + (architecture dependent and independent) and place these files in a + subdirectory so as not to confuse the majority just looking for one + tarball. + + Under Windows, we need to provide a WISE-style GUI setup program. + It's already there but needs some work so you can select "all" packages + easily (should be the default). + + Parallel Root and Package Trees. + + If the user downloads separately, the main source and the packages, + he will naturally untar them into the same directory. This results in + the parallel root and package structure. We should support this as a + "last resort," i.e., if we find no packages anywhere and are about to + resign ourselves to not having packages, then look for a parallel + package tree. The user who sets things up like this should be able to + either run in place or "make install" and get a proper installed + XEmacs. Never should the user have to touch -package-path. + + II. WINDOWS PRINTING + + Looks like the internals are done but not the GUI. This must be + working in 21.2. + + III. WINDOWS MULE + + Basic support should be there. There's already a patch to get things + started and I'll be doing more work to make this real. + + IV. GUTTER ETC. + + This stuff needs to be "stable" and generally free from bugs. Any + APIs we create need to be well-reviewed or marked clearly as + experimental. + + V. PORTABLE DUMPER + + Last bits need to be cleaned up. This should be made the "default" + for a while to flush-out problems. Under Microsoft Windows, Portable + Dumper must be the default in 21.2 because of the problems with the + existing dump process. + + COMMENT: I'd like to feature freeze this pretty soon and create a + 21.3 tree where all of my major overhauls of Mule-related stuff will go + in. At the same time or around, we need to do the move-around in the + repository (or create a new one) and "upgrade" to the latest CVS server. + +  + File: internals.info, Node: Future Work -- Elisp Compatibility Package, Next: Future Work -- Drag-n-Drop, Prev: Future Work -- General Suggestions, Up: Future Work + + 40.2 Future Work - Elisp Compatibility Package + ============================================== + + Author: Ben Wing (mailto:ben@xemacs.org) + + A while ago I created a package called Sysdep, which aimed to be a + forward compatibility package for Elisp. The idea was that instead of + having to write your package using the oldest version of Emacs that you + wanted to support, you could use the newest XEmacs API, and then simply + load the Sysdep package, which would automatically define the new API in + terms of older APIs as necessary. The idea of this package was good, + but its design wasn't perfect, and it wasn't widely adopted. I propose + a new package called Compat that corrects the design flaws in Sysdep, + and hopefully will be adopted by most of the major packages. + + In addition, this package will provide macros that can be used to + bracket code as necessary to disable byte compiler warnings generated as + a result of supporting the APIs of different versions of Emacs; or + rather the Compat package strives to provide useful constructs to make + doing this support easier, and these constructs have the side effect of + not causing spurious byte compiler warnings. The idea here is that it + should be possible to create well-written, clean, and understandable + Elisp that supports both older and newer APIs, and has no byte compiler + warnings. Currently many warnings are unavoidable, and as a result, + they are simply ignored, which also causes a lot of legitimate warnings + to be ignored. + + The approach taken by the Sysdep package to make sure that the newest + API was always supported was fairly simple: when the Sysdep package was + loaded, it checked for the existence of new API functions, and if they + weren't defined, it defined them in terms of older API functions that + were defined. This had the advantage that the checks for which API + functions were defined were done only once at load time rather than each + time the function was called. However, the fact that the new APIs were + globally defined caused a lot of problems with unwanted interactions, + both with other versions of the Sysdep package provided as part of other + packages, and simply with compatibility code of other sorts in packages + that would determine whether an API existed by checking for the + existence of certain functions within that API. In addition, the Sysdep + package did not scale well because it defined all of the functions that + it supported, regardless of whether or not they were used. + + The Compat package remedies the first problem by ensuring that the + new APIs are defined only within the lexical scope of the packages that + actually make use of the Compat package. It remedies the second problem + by ensuring that only definitions of functions that are actually used + are loaded. This all works roughly according to the following scheme: + + 1. Part of the Compat package is a module called the Compat + generator. This module is actually run as an additional step + during byte compilation of a package that uses Compat. This can + happen either through the makefile or through the use of an + `eval-when-compile' call within the package code itself. What the + generator does is scan all of the Lisp code in the package, + determine which function calls are made that the Compat package + knows about, and generates custom `compat' code that conditionally + defines just these functions when the package is loaded. The + custom `compat' code can either be written to a separate Lisp file + (for use with multi-file packages), or inserted into the beginning + of the Lisp file of a single file package. (In the latter case, + the package indicates where this generated code should go through + the use of magic comments that mark the beginning and end of the + section. Some will say that doing this trick is bad juju, but I + have done this sort of thing before, and it works very well in + practice). + + 2. The functions in the custom `compat' code have their names + prefixed with both the name of the package and the word `compat', + ensuring that there will be no name space conflicts with other + functions in the same package, or with other packages that make + use of the Compat package. + + 3. The actual definitions of the functions in the custom `compat' + code are determined at run time. When the equivalent API already + exists, the wrapper functions are simply defined directly in terms + of the actual functions, so that the only run time overhead from + using the Compat package is one additional function call. + (Alternatively, even this small overhead could be avoided by + retrieving the definitions of the actual functions and supplying + them as the definitions of the wrapper functions. However, this + appears to me to not be completely safe. For example, it might + have bad interactions with the advice package). + + 4. The code that wants to make use of the custom `compat' code is + bracketed by a call to the construct `compat-execute'. What this + actually does is lexically bind all of the function names that are + being redefined with macro functions by using the Common Lisp + macro macrolet. (The definition of this macro is in the CL + package, but in order for things to work on all platforms, the + definition of this macro will presumably have to be copied and + inserted into the custom `compat' code). + + + In addition, the Compat package should define the macro + `compat-if-fboundp'. Similar macros such as `compile-when-fboundp' and + `compile-case-fboundp' could be defined using similar principles). The + `compat-if-fboundp' macro behaves just like an `(if (fboundp ...) ...)' + clause when executed, but in addition, when it's compiled, it ensures + that the code inside the `if-true' sub-block will not cause any byte + compiler warnings about the function in question being unbound. I + think that the way to implement this would be to make + `compat-if-fboundp' be a macro that does what it's supposed to do, but + which defines its own byte code handler, which ensures that the + particular warning in question will be suppressed. (Actually ensuring + that just the warning in question is suppressed, and not any others, + might be rather tricky. It certainly requires further thought). + + Note: An alternative way of avoiding both warnings about unbound + functions and warnings about obsolete functions is to just call the + function in question by using `funcall', instead of calling the + function directly. This seems rather inelegant to me, though, and + doesn't make it obvious why the function is being called in such a + roundabout manner. Perhaps the Compat package should also provide a + macro `compat-funcall', which works exactly like `funcall', but which + indicates to anyone reading the code why the code is expressed in such + a fashion. + + If you're wondering how to implement the part of the Compat generator + where it scans Lisp code to find function calls for functions that it + wants to do something about, I think the best way is to simply process + the code using the Lisp function `read' and recursively descend any + lists looking for function names as the first element of any list + encountered. This might extract out a few more functions than are + actually called, but it is almost certainly safer than doing anything + trickier like byte compiling the code, and attempting to look for + function calls in the result. (It could also be argued that the names + of the functions should be extracted, not only from the first element of + lists, but anywhere `symbol' occurs. For example, to catch places + where a function is called using `funcall' or `apply'. However, such + uses of functions would not be affected by the surrounding macrolet + call, and so there doesn't appear to be any point in extracting them). + +  + File: internals.info, Node: Future Work -- Drag-n-Drop, Next: Future Work -- Standard Interface for Enabling Extensions, Prev: Future Work -- Elisp Compatibility Package, Up: Future Work + + 40.3 Future Work - Drag-n-Drop + ============================== + + Author: Ben Wing (mailto:ben@xemacs.org) + + *Abstract:* I propose completely redoing the drag-n-drop interface + to make it powerful and extensible enough to support such concepts as + drag over and drag under visuals and context menus invoked when a drag + is done with the right mouse button, to allow drop handlers to be + defined for all sorts of graphical elements including buffers, extents, + mode lines, toolbar items, menubar items, glyphs, etc., and to allow + different packages to add and remove drop handlers for the same drop + sites without interfering with each other. The changes are extensive + enough that I think they can only be implemented in version 22, and the + drag-n-drop interface should remain experimental until then. + + The new drag-n-drop interface centers around the twin concepts of + "drop site" and "drop handler". A "drop site" specifies a particular + graphical element where an object can be dropped onto, and a "drop + handler" encapsulates all of the behavior that happens when such an + object is dragged over and dropped onto a drop site. + + Each drop site has an object associated with it which is passed to + functions that are part of the drop handlers associated with that site. + The type of this object depends on the graphical element that comprises + the drop site. The drop site object can be a buffer, an extent, a + glyph, a menu path, a toolbar item path, etc. (These last two object + types are defined in Lisp Interface Changes (lisp-interface.html) in + the sections on menu and toolbar API changes. If we wanted to allow + drops onto other kinds of drop sites, for example mode lines, we would + have to create corresponding path objects). Each such object type + should be able to be accessed using the generalized property interface + defined above, and should have a property called `drop-handlers' + associated with it that specifies all of the drop handlers associated + with the drop site. Normally, this property is not accessed directly, + but instead by using the drop handler API defined below, and Lisp + packages should not make any assumptions about the format of the data + contained in the `drop-handlers' property. + + Each drop handler has an object of type `drop-handler' associated + with it, whose primary purpose is to be a container for the various + properties associated with a particular drop handler. These could + include, for example, a function invoked when the drop occurs, a context + menu invoked when a drop occurs as a result of a drag with the right + mouse button, functions invoked when a dragged object enters, leaves, or + moves within a drop site, the shape that the mouse pointer changes to + when an object is dragged over a drop site that allows this particular + object to be dropped onto it, the MIME types (actually a regular + expression matching the MIME types) of the allowable objects that can be + dropped onto the drop site, a "package tag" (a symbol specifying the + package that created the drop handler, used for identification + purposes), etc. The drop handler object is passed to the functions that + are invoked as a result of a drag or a drop, most likely indirectly as + one of the properties of the drag or drop event passed to the function. + Properties of a drop handler object are accessed and modified in the + standard fashion using the generalized property interface. + + A drop handler is added to a drop site using the `add-drop-handler' + function. The drop handler itself can either be created separately + using the `make-drop-handler' function and then passed in as one of the + parameters to `add-drop-handler', or it will be created automatically + by the `add-drop-handler' function, if the drop handler argument is + omitted, but keyword arguments corresponding to the valid keyword + properties for a drop handler are specified in the `add-drop-handler' + call. Other functions, such as `find-drop-handler', `add-drop-handler' + (when specifying a drop handler before which the drop handler in + question is to be added), `remove-drop-handler' etc. should be defined + with obvious semantics. All of these functions take or return a drop + site object which, as mentioned above, can be one of several object + types corresponding to graphical elements. Defined drop handler + functions locate a particular drop handler using either the `MIME-type' + or `package-tag' property of the drop handler, as defined above. + + Logically, the drop handlers associated with a particular drop site + are an ordered list. The first drop handler whose specified MIME type + matches the MIME type of the object being dragged or dropped controls + what happens to this object. This is important particularly because the + specified MIME type of the drop handler can be a regular expression + that, for example, matches all audio objects with any sub-type. + + In the current drag-n-drop API, there is a distinction made between + objects with an associated MIME type and objects with an associated URL. + I think that this distinction is arbitrary, and should not exist. All + objects should have a MIME type associated with them, and a new + XEmacs-specific MIME type should be defined for URLs, file names, etc. + as necessary. I am not even sure that this is necessary, however, as + the MIME specification may specify a general concept of a pointer or + link to an object, which is exactly what we want. Also in some cases + (for example, the name of a file that is locally available), the pointer + or link will have another MIME type associated with it, which is the + type of the object that is being pointed to. I am not quite sure how we + should handle URL and file name objects being dragged, but I am positive + that it needs to be integrated with the mechanism used when an object + itself is being dragged or dropped. + + As is described in a separate page (misc-user-event.html), the + `misc-user-event' event type should be removed and split up into a + number of separate event types. Two such event types would be + `drag-event' and `drop-event'. A drop event is used when an object is + actually dropped, and a drag event is used if a function is invoked as + part of the dragging process. (Such a function would typically be used + to control what are called "drag under visuals", which are changes to + the appearance of the drop site reflecting the fact that a compatible + object is being dragged over it). The drag events and drop events + encapsulate all of the information that is pertinent to the drag or + drop action occurring, including such information as the actual MIME + type of the object in question, the drop handler that caused a function + to be invoked, the mouse event (or possibly even a keyboard event) + corresponding to the user's action that is causing the drag or drop, + etc. This event is always passed to any function that is invoked as a + result of the drag or drop. There should never be any need to refer to + the `current-mouse-event' variable, and in fact, this variable should + not be changed at all during a drag or a drop. + +  + File: internals.info, Node: Future Work -- Standard Interface for Enabling Extensions, Next: Future Work -- Better Initialization File Scheme, Prev: Future Work -- Drag-n-Drop, Up: Future Work + + 40.4 Future Work - Standard Interface for Enabling Extensions + ============================================================= + + Author: Ben Wing (mailto:ben@xemacs.org) + + *Abstract:* Apparently, if you know the name of a package (for + example, `fusion'), you can load it using the `require' function, but + there's no standard way to turn it on or turn it off. The only way to + figure out how to do that is to go read the source file, where + hopefully the comments at the start tell you the appropriate magic + incantations that you need to run in order to turn the extension on or + off. There really needs to be standard functions, such as + `enable-extension' and `disable-extension', to do this sort of thing. + It seems like a glaring omission that this isn't currently present, and + it's really surprising to me that nobody has remarked on this. + + The easy part of this is defining the interface, and I think it + should be done as soon as possible. When the package is loaded, it + simply calls some standard function in the package system, and passes + it the names of enable and disable functions, or perhaps just one + function that takes an argument specifying whether to enable or + disable. In any case, this data is kept in a table which is used by the + `enable-extension' and `disable-extension' function. There should also + be functions such as `extension-enabled-p' and + `enabled-extension-list', and so on with obvious semantics. The hard + part is actually getting packages to obey this standard interface, but + this is mitigated by the fact that the changes needed to support this + interface are so simple. + + I have been conceiving of these enabling and disabling functions as + turning the feature on or off globally. It's probably also useful to + have a standard interface returning a extension on or off in just the + particular buffer. Perhaps then the appropriate interface would involve + registering a single function that takes an argument that specifies + various things, such as turn off globally, turn on globally, turn on or + off in the current buffer, etc. + + Part of this interface should specify the correct way to define + global key bindings. The correct rule for this, of course, is that the + key bindings should not happen when the package is loaded, which is + often how things are currently done, but only when the extension is + actually enabled. The key bindings should go away when the extension is + disabled. I think that in order to support this properly, we should + expand the keymap interface slightly, so that in addition to other + properties associated with each key binding is a list of shadow + bindings. Then there should be a function called + `define-key-shadowing', which is just like `define-key' but which also + remembers the previous key binding in a shadow list. Then there can be + another function, something like `undefine-key', which restores the + binding to the most recently added item on the shadow list. There are + already hash tables associated with each key binding, and it should be + easy to stuff additional values, such as a shadow list, into the hash + table. Probably there should also be functions called + `global-set-key-shadowing' and `global-unset-key-shadowing' with + obvious semantics. + + Once this interface is defined, it should be easy to expand the + custom package so it knows about this interface. Then it will be + possible to put all sorts of extensions on the options menu so that + they could be turned off and turned on very easily, and then when you + save the options out to a file, the design settings for whether these + extensions are enabled or not are saved out with it. A whole lot of + custom junk that's been added to a lot of different packages could be + removed. After doing this, we might want to think of a way to classify + extensions according to how likely we think the user will want to use + them. This way we can avoid the problem of having a list of 100 + extensions and the user not being able to figure out which ones might + be useful. Perhaps the most useful extensions would appear immediately + on the extensions menu, and the less useful ones would appear in a + submenu of that, and another submenu might contain even less useful + extensions. Of course the package authors might not be too happy with + this, but the users probably will be. I think this at least deserves a + thought, although it's possible you might simply want to maintain a + list on the web site of extensions and a judgment on first of all, how + commonly a user might want this extension, and second of all, how well + written and bug-free the package is. Both of these sorts of judgments + could be obtained by doing user surveys if need be. + +  + File: internals.info, Node: Future Work -- Better Initialization File Scheme, Next: Future Work -- Keyword Parameters, Prev: Future Work -- Standard Interface for Enabling Extensions, Up: Future Work + + 40.5 Future Work - Better Initialization File Scheme + ==================================================== + + Author: Ben Wing (mailto:ben@xemacs.org) + + *Abstract:* A proposal is outlined for converting XEmacs to use the + `.xemacs' subdirectory for its initialization files instead of putting + them in the user's home directory. In the process, a general + pre-initialization scheme is created whereby all of the initialization + parameters, such as the location of the initialization files, whether + these files are loaded or not, where the initial frame is created, etc. + that are currently specified by command line arguments, by environment + variables, and other means, can be specified in a uniform way using + Lisp code. Reasonable default behavior for everything will still be + provided, and the older, simpler means can be used if desired. + Compatibility with the current location and name of the initialization + file, and the current ill-chosen use for the `.xemacs' directory is + maintained, and the problem of how to gracefully migrate a user from the + old scheme into the new scheme while still allowing the user to use GNU + Emacs or older versions of XEmacs is solved. A proposal for changing + the way that the initial frame is mapped is also outlined; this would + allow the user's initialization file to control the way that the initial + frame appears without resorting to hacks, while still making echo area + messages visible as they appear, and allowing the user to debug errors + in the initialization file. + + Principles in the new scheme + ---------------------------- + + 1. XEmacs has a defined "pre-initialization process". This process, + whose purpose is to compute the values of the parameters that + control how the initializiaton process proceeds, occurs as early + as possible after the Lisp engine has been initialized, and in + particular, it occurs before any devices have been opened, or + before any initialization parameters are set that could reasonably + be expected to be changed. In fact, the pre-initialization + process should take care of setting these parameters. The code + that implements the pre-initialization process should be written + in Lisp and should be called from the Lisp function + `normal-top-level', and the general way that the user customizes + this process should also be done using Lisp code. + + 2. The pre-initialization process involves a number of properties, + for example the directory containing the user initialization files + (normally the `.xemacs' subdirectory), the name of the user init + file, the name of the custom init file, where and what type the + initial device is, whether and when the initial frame is mapped, + etc. A standard interface is provided for getting and setting the + values of these properties using functions such as + `set-pre-init-property', `pre-init-property', etc. At various + points during the pre-initialization process, the value of many of + these properties can be undecided, which means that at the end of + the process, the value of these properties will be derived from + other properties in some fashion that is specific to each property. + + 3. The default values of these properties are set first from the + registry under Windows, then from environment variables, then from + command line switches, such as `-q' and `-nw'. + + 4. One of the command line switches is `-pre-init', whose value is a + Lisp expression to be evaluated at pre-initialization time, + similar to the `-eval' command line switch. This allows any + pre-initialization property to be set from the command line. + + 5. Let's define the term "to determine a pre-initialization + property" to mean if the value of a property is undetermined, it + is computed and set according to a rule that is specific to the + property. Then after the pre-init properties are initialized from + the registry, from the environment variables, from command line + arguments, two of the pre-init properties (specifically the init + file directory and the location of the "pre-init file") are + determined. The purpose of the pre-init file is to contain Lisp + code that is run at pre-initialization time, and to control how + the initialization proceeds. It is a bit similar to the standard + init file, but the code in the pre-init file shouldn't do anything + other than set pre-init properties. Executing any code that does + I/O might not produce expected results because the only device that + will exist at the time is probably a stream device connected to the + standard I/O of the XEmacs process. + + 6. After the pre-init file has been run, all of the rest of the + pre-init properties are determined, and these values are then used + to control the initialization process. Some of the rules used in + determining specific properties are: + + 1. If the `.xemacs' sub-directory exists, and it's not + obviously a package root (which probably means that it + contains a file like `init.el' or `pre-init.el', or if + neither of those files is present, then it doesn't contain + any sub-directories or files that look like what would be in + a package root), then it becomes the value of the init file + directory. Otherwise the user's home directory is used. + + 2. If the init file directory is the user's home directory, + then the init file is called `.emacs'. Otherwise, it's + called `init.el'. + + 3. If the init file directory is the user's home directory, + then the pre-init file is called `.xemacs-pre-init.el'. + Otherwise it's called `pre-init.el'. (One of the reasons for + this rule has to do with the dialog box that might be + displayed at startup. This will be described below.) + + 4. If the init file directory is the user's home directory, + then the custom init file is called `.xemacs-custom-init.el'. + Otherwise, it's called `custom-init.el'. + + + 7. After the first normal device is created, but before any frames + are created on it, the XEmacs initialization code checks to see if + the old init file scheme is being used, which is to say that the + init file directory is the same as the user's home directory. If + that's the case, then normally a dialog box comes up (or a + question is asked on the terminal if XEmacs is being run in a + non-windowing mode) which asks if the user wants to migrate his + initialization files to the new scheme. The possible responses + are *Yes*, *No*, and *No, and don't ask this again*. If this last + response is chosen, then the file `.xemacs-pre-init.el' in the + user's home directory is created or appended to with a line of + Lisp code that sets up a pre-init property indicating that this + dialog box shouldn't come up again. If the *Yes* option is + chosen, then any package root files in `.xemacs' are moved into + `.xemacs/packages', the file `.emacs' is moved into + `.xemacs/init.el' and `.emacs' in the home directory becomes a + symlink to this file. This way some compatibility is still + maintained with GNU Emacs and older versions of XEmacs. The code + that implements this has to be written very carefully to make sure + that it doesn't accidentally delete or mess up any of the files + that get moved around. + + + The custom init file + -------------------- + + The "custom init file" is where the custom package writes its options. + This obviously needs to be a separate file from the standard init file. + It should also be loaded before the init file rather than after, as is + usually done currently, so that the init file can override these + options if it wants to. + + Frame mapping + ------------- + + In addition to the above scheme, the way that XEmacs handles mapping the + initial frame should be changed. However, this change perhaps should be + delayed to a later version of XEmacs because of the user visible changes + that it entails and the possible breakage in people's init files that + might occur. (For example, if the rest of the scheme is implemented in + 21.2, then this part of the scheme might want to be delayed until + version 22.) The basic idea is that the initial frame is not created + before the initialization file is run, but instead a banner frame is + created containing the XEmacs logo, a button that allows the user to + cancel the execution of the init file and an area where messages that + are output in the process of running this file are displayed. This area + should contain a number of lines, which makes it better than the current + scheme where only the last message is visible. After the init file is + done, the initial frame is mapped. This way the init file can make face + changes and other such modifications that affect initial frame and then + have the initial frame correctly come up with these changes and not see + any frame dancing or other problems that exist currently. + + There should be a function that allows the initialization file to + explicitly create and map the first frame if it wants to. There should + also be a pre-init property that controls whether the banner frame + appears (of course it defaults to true) a property controlling when the + initial frame is created (before or after the init file, defaulting to + after), and a property controlling whether the initial frame is mapped + (normally true, but will be false if the `-unmapped' command line + argument is given). + + If an error occurs in the init file, then the initial frame should + always be created and mapped at that time so that the error is displayed + and the debugger has a place to be invoked. + +  + File: internals.info, Node: Future Work -- Keyword Parameters, Next: Future Work -- Property Interface Changes, Prev: Future Work -- Better Initialization File Scheme, Up: Future Work + + 40.6 Future Work - Keyword Parameters + ===================================== + + Author: Ben Wing (mailto:ben@xemacs.org) + + NOTE: These changes are partly motivated by the various + user-interface changes elsewhere in this document, and partly for Mule + support. In general the various APIs in this document would benefit + greatly from built-in keywords. + + I would like to make keyword parameters an integral part of Elisp. + The idea here is that you use the `&key' identifier in the + parameter list of a function and all of the following parameters + specified are keyword parameters. This means that when these arguments + are specified in a function call, they are immediately preceded in the + argument list by a "keyword", which is a symbol beginning with the `:' + character. This allows any argument to be specified independently of + any other argument with no need to place the arguments in any + particular order. This is particularly useful for functions that take + many optional parameters; using keyword parameters makes the code much + cleaner and easier to understand. + + The `cl' package already provides keyword parameters of a sort, but + I would like to make this more integrated and useable in a standard + fashion. The interface that I am proposing is essentially compatible + with the keyword interface in Common Lisp, but it may be a subset of the + Common Lisp functionality, especially in the first implementation. + There is one departure from the Common Lisp specification that I would + like to make in order to make it much easier to add keyword parameters + to existing functions with optional parameters, and in general, to make + optional and keyword parameters coexist more easily. The Common Lisp + specification indicates that if a function has both optional and keyword + parameters, the optional parameters are always processed before the + keyword parameters. This means, for example, that if a function has + three required parameters, two optional parameters, and some number of + keyword parameters following, and the program attempts to call this + function by passing in the three required arguments, and then some + keyword arguments, the first keyword specified and the argument + following it get assigned to the first and second optional parameters as + specified in the function definition. This is certainly not what is + intended, and means that if a function defines both optional and keyword + parameters, any calls of this function must specify `nil' for all of + the optional arguments before using any keywords. If the function + definition is later changed to add more optional parameters, all + existing calls to this function that use any keyword arguments will + break. This problem goes away if we simply process keyword parameters + before the optional parameters. + + The primary changes needed to support the keyword syntax are: + + 1. The subr object type needs to be modified to contain additional + slots for the number and names of any keyword parameters. + + 2. The implementation of the `funcall' function needs to be modified + so that it knows how to process keyword parameters. This is the + only place that will require very much intricate coding, and much + of the logic that would need to be added can be lifted directly + from the `cl' code. + + 3. A new macro, similar to the `DEFUN' macro, and probably called + `DEFUN_WITH_KEYWORDS', needs to be defined so that built-in Lisp + primitives containing keywords can be created. Now, the + `DEFUN_WITH_KEYWORDS' macro should take an additional parameter + which is a string, which consists of the part of the lambda list + declaration for this primitive that begins with the `&key' + specifier. This string is parsed in the `DEFSUBR' macro during + XEmacs initialization, and is converted into the appropriate + structure that needs to be stored into the subr object. In + addition, the MAX_ARGS parameter of the `DEFUN' macro needs to be + incremented by the number of keyword parameters and these + parameters are passed to the C function simply as extra parameters + at the end. The `DEFSUBR' macro can sort out the actual number of + required, optional and keyword parameters that the function takes, + once it has parsed the keyword parameter string. (An alternative + that might make the declaration of a primitive a little bit easier + to understand would involve adding another parameter to the + `DEFUN_WITH_KEYWORDS' macro that specifies the number of keyword + parameters. However, this would require some additional + complexity in the preprocessor definition of the + `DEFUN_WITH_KEYWORDS' macro, and probably isn't worth + implementing). + + 4. The byte compiler would have to be modified slightly so that it + knows about keyword parameters when it parses the parameter + declaration of a function. For example, so that it issues the + correct warnings concerning calls to that function with incorrect + arguments. + + 5. The `make-docfile' program would have to be modified so that it + generates the correct parameter lists for primitives defined using + the `DEFUN_WITH_KEYWORDS' macro. + + 6. Possibly other aspects of the help system that deal with function + descriptions might have to be modified. + + 7. A helper function might need to be defined to make it easier for + primitives that use both the `&rest' and `&key' specifiers + to parse their argument lists. + + + Internal API for C primitives with keywords - necessary for many of the new Mule APIs being defined. + ---------------------------------------------------------------------------------------------------- + + DEFUN_WITH_KEYWORDS (Ffoo, "foo", 2, 5, 6, ALLOW_OTHER_KEYWORDS, + (ichi, ARG_NIL), (ni, ARG_NIL), (san, ARG_UNBOUND), 0, + (arg1, arg2, arg3, arg4, arg5) + ) + { + ... + } + + -> C fun of 12 args: + + (arg1, ... arg5, ichi, ..., roku, other keywords) + + Circled in blue is actual example declaration + + DEFUN_WITH_KEYWORDS (Ffoo, "foo", 1,2,0 (bar, baz) <- arg list + [ MIN ARGS, MAX ARGS, something that could be REST, SPECIFY_DEFAULT or + REST_SPEC] + + [#KEYWORDS [ ALLOW_OTHER, SPECIFY_DEFAULT, ALLOW_OTHER_SPECIFY_DEFAULT + 6, ALLOW_OTHER_SPECIFY_DEFAULT, + + (ichi, 0) (ni, 0), (san, DEFAULT_UNBOUND), (shi, "t"), (go, "5"), + (roku, "(current-buffer)") + <- specifies arguments, default values (string to be read into Lisp + data during init; then forms evalled at fn ref time. + + ,0 <- [INTERACTIVE SPEC] ) + + LO = Lisp_Object + + -> LO Ffoo (LO bar, LO baz, LO ichi, LO ni, LO san, LO shi, LO go, + LO roku, int numkeywords, LO *other_keywords) + + #define DEFUN_WITH_KEYWORDS (fun, funstr, minargs, maxargs, argspec, \ + #args, num_keywords, keywordspec, keywords, intspec) \ + LO fun (DWK_ARGS (maxargs, args) \ + DWK_KEYWORDS (num_keywords, keywordspec, keywords)) + + #define DWK_KEYWORDS (num_keywords, keywordspec, keywords) \ + DWK_KEYWORDS ## keywordspec (keywords) + DWK_OTHER_KEYWORDS ## keywordspec) + + #define DWK_KEYWORDS_ALLOW_OTHER (x,y) + DWK_KEYWORDS (x,y) + + #define DWK_KEYWORDS_ALLOW_OTHER_SPECIFICATIONS (x,y) + DWK_KEYWORDS_SPECIFY_DEFAULT (x,y) + + #define DWK_KEYWORDS_SPECIFY_DEFAULT (numkey, key) + ARGLIST_CAR ## numkey key + + #define ARGLT_GRZ (x,y) LO CAR x, LO CAR y + +  + File: internals.info, Node: Future Work -- Property Interface Changes, Next: Future Work -- Toolbars, Prev: Future Work -- Keyword Parameters, Up: Future Work + + 40.7 Future Work - Property Interface Changes + ============================================= + + Author: Ben Wing (mailto:ben@xemacs.org) + + In my past work on XEmacs, I already expanded the standard property + functions of `get', `put', and `remprop' to work on objects other than + symbols and defined an additional function `object-plist' for this + interface. I'd like to expand this interface further and advertise it + as the standard way to make property changes in objects, especially the + new objects that are going to be defined in order to support the added + user interface features of version 22. My proposed changes are as + follows: + + 1. A new concept associated with each property called a "default + value" is introduced. (This concept already exists, but not in a + well-defined way.) The default value is the value that the + property assumes for certain value retrieval functions such as + `get' when it is "unbound", which is to say that its value has not + been explicitly specified. Note: the way to make a property + unbound is to call `remprop'. Note also that for some built-in + properties, setting the property to its default value is + equivalent to making it unbound. + + 2. The behavior of the `get' function is modified. If the `get' + function is called on a property that is unbound and the third, + optional DEFAULT argument is `nil', then the default value of the + property is returned. If the DEFAULT argument is not `nil', then + whatever was specified as the value of this argument is returned. + For the most part, this is upwardly compatible with the existing + definition of `get' because all user-defined properties have an + initial default value of `nil'. Code that calls the `get' + function and specifies `nil' for the DEFAULT argument, and expects + to get `nil' returned if the property is unbound, is almost + certainly wrong anyway. + + 3. A new function, `get1' is defined. This function does not take a + default argument like the `get' function. Instead, if the property + is unbound, an error is signaled. Note: `get' can be implemented + in terms of `get1'. + + 4. New functions `property-default-value' and `property-bound-p' are + defined with the obvious semantics. + + 5. An additional function `property-built-in-p' is defined which + takes two arguments, the first one being a symbol naming an object + type, and the second one specifying a property, and indicates + whether the property name has a built-in meaning for objects of + that type. + + 6. It is not necessary, or even desirable, for all object types to + allow user-defined properties. It is always possible to simulate + user-defined properties for an object by using a weak hash table. + Therefore, whether an object allows a user to define properties or + not should depend on the meaning of the object. If an object does + not allow user-defined properties, the `put' function should + signal an error, such as `undefined-property', when given any + property other than those that are predefined. + + 7. A function called `user-defined-properties-allowed-p' should be + defined with the obvious semantics. (See the previous item.) + + 8. Three more functions should be defined, called + `built-in-property-name-list', `property-name-list', and + `user-defined-property-name-list'. + + + Another idea: + + (define-property-method + predicate object-type + predicate cons :(KEYWORD) (all lists beginning with KEYWORD) + + :put putfun + :get + :remprop + :object-props + :clear-properties + :map-properties + + e.g. (define-property-method 'hash-table + :put #'(lambda (obj key value) (puthash key obj value))) + +  + File: internals.info, Node: Future Work -- Toolbars, Next: Future Work -- Menu API Changes, Prev: Future Work -- Property Interface Changes, Up: Future Work + + 40.8 Future Work - Toolbars + =========================== + + * Menu: + + * Future Work -- Easier Toolbar Customization:: + * Future Work -- Toolbar Interface Changes:: + +  + File: internals.info, Node: Future Work -- Easier Toolbar Customization, Next: Future Work -- Toolbar Interface Changes, Prev: Future Work -- Toolbars, Up: Future Work -- Toolbars + + 40.8.1 Future Work - Easier Toolbar Customization + ------------------------------------------------- + + Author: Ben Wing (mailto:ben@xemacs.org) + + *Abstract:* One of XEmacs' greatest strengths is its ability to be + customized endlessly. Unfortunately, it is often too difficult to + figure out how to do this. There has been some recent work like the + Custom package, which helps in this regard, but I think there's a lot + more work that needs to be done. Here are some ideas (which certainly + could use some more thought). + + Although there is currently an `edit-toolbar' package, it is not + well integrated with XEmacs, and in general it is much too hard to + customize the way toolbars look. I would like to see an interface that + works a bit like the way things work under Windows, where you can + right-click on a toolbar to get a menu of options that allows you to + change aspects of the toolbar. The general idea is that if you + right-click on an item itself, you can do things to that item, whereas + if you right-click on a blank part of a toolbar, you can change the + properties of the toolbar. Some of the items on the right-click menu + for a particular toolbar button should be specified by the button + itself. Others should be standard. For example, there should be an + *Execute* item which simply does what would happen if you left-click on + a toolbar button. There should probably be a *Delete* item to get rid + of the toolbar button and a *Properties* item, which brings up a + property sheet that allows you to do things like change the icon and + the command string that's associated with the toolbar button. + + The options to change the appearance of the toolbar itself should + probably appear both on the context menu for specific buttons, and on + the menu that appears when you click on a blank part of the toolbar. + That way, if there isn't a blank part of the toolbar, you can still + change the toolbar appearance. As for what appears in these items, in + Outlook Express, for example, there are three different menu items, one + of which is called *Buttons*, which brings up, or pops up a window + which allows you to edit the toolbar, which for us could pop up a new + frame, which is running `edit-toolbar.el'. The second item is called + *Align*, which contains a submenu that says *Top*, *Bottom*, *Left*, + and *Right*, which will be just like setting the default toolbar + position. The third one says *Text Labels*, which would just let you + select whether there are captions or not. I think all three of these + are useful and are easy to implement in XEmacs. These things also need + to be integrated with custom so that a user can control whether these + options apply to all sessions, and in such a case can save the settings + out to an options file. `edit-toolbar.el' in particular needs to + integrate with custom. Currently it has some sort of hokey stuff of + its own, which it saves out to a `.toolbar' file. Another useful + option to have, once we draw the captions dynamically rather than using + pre-generated ones, would be the ability to change the font size of the + captions. I'm sure that Kyle, for one, would appreciate this. + + (This is incomplete.....) + +  + File: internals.info, Node: Future Work -- Toolbar Interface Changes, Prev: Future Work -- Easier Toolbar Customization, Up: Future Work -- Toolbars + + 40.8.2 Future Work - Toolbar Interface Changes + ---------------------------------------------- + + Author: Ben Wing (mailto:ben@xemacs.org) + + I propose changing the way that toolbars are specified to make them + more flexible. + + 1. A new format for the vector that specifies a toolbar item is + allowed. In this format, the first three items of the vector are + required and are, respectively, a caption, a glyph list, and a + callback. The glyph list and callback arguments are the same as + in the current toolbar item specification, and the caption is a + string specifying the caption text placed below the toolbar glyph. + The caption text is required so that toolbar items can be + identified for the purpose of retrieving and changing their + property values. Putting the caption first also makes it easy to + distinguish between the new and the old toolbar item vector + formats. In the old format, the first item, the glyph list, is + either a list or a symbol. In the new format, the first item is a + string. In the new format, following the three required items, + are optional keyword items specified using keywords in the same + format as the menu item vector format. The keywords that should + be predefined are: `:help-echo', `:context-menu', + `:drop-handlers', and `:enabled-p'. The `:enabled-p' and + `:help-echo' keyword arguments are the same as the third and + fourth items in the old toolbar item vector format. The + `:context-menu' keyword is a list in standard menu format that + specifies additional items that will appear when the context menu + for the toolbar item is popped up. (Typically, this happens when + the right mouse button is clicked on the toolbar item). The + `:drop-handlers' keyword is for use by the new drag-n-drop + interface (see Drag-n-Drop Interface Changes (drag-n-drop.html) ), + and is not normally specified or modified directly. + + 2. Conceivably, there could also be keywords that are associated + with a toolbar itself, rather than with a particular toolbar item. + These keyword properties would be specified using keywords and + arguments that occur before any toolbar item vectors, similarly to + how things are done in menu specifications. Possible properties + could include `:captioned-p' (whether the captions are visible + under the toolbar), `:glyphs-visible-p' (whether the toolbar + glyphs are visible), and `:context-menu' (additional items that + will appear on the context menus for all toolbar items and + additionally will appear on the context menu that is popped up + when the right mouse button is clicked over a portion of the + toolbar that does not have any toolbar buttons in it). The + current standard practice with regards to such properties seems to + be to have separate specifiers, such as `left-toolbar-width', + `right-toolbar-width', `left-toolbar-visible-p', + `right-toolbar-visible-p', etc. It could easily be argued that + there should be no such toolbar specifiers and that all such + properties should be part of the toolbar instantiator itself. In + this scheme, the only separate specifiers that would exist for + individual properties would be default values. There are a lot of + reasons why an interface change like this makes sense. For + example, currently when VM sets its toolbar, it also sets the + toolbar width and similar properties. If you change which edge of + the frame the VM toolbar occurs in, VM will also have to go and + modify all of the position-specific toolbar specifiers for all of + the other properties associated with a toolbar. It doesn't really + seem to make sense to me for the user to be specifying the width + and visibility and such of specific toolbars that are attached to + specific edges because the user should be free to move the + toolbars around and expect that all of the toolbar properties + automatically move with the toolbar. (It is also easy to imagine, + for example, that a toolbar might not be attached to the edge of + the frame at all, but might be floating somewhere on the user's + screen). With an interface where these properties are separate + specifiers, this has to be done manually. Currently, having the + various toolbar properties be inside of toolbar instantiators + makes them difficult to modify, but this will be different with + the API that I propose below. + + 3. I propose an API for modifying toolbar and toolbar item + properties, as well as making other changes to toolbar + instantiators, such as inserting or deleting toolbar items. This + API is based around the concept of a path. There are two kinds of + paths here - "toolbar paths" and "toolbar item paths". Each kind + of path is an object (of type `toolbar-path' and + `toolbar-item-path', respectively) whose properties specify the + location in a toolbar instantiator where changes to the + instantiator can be made. A toolbar path, for example, would be + created using the `make-toolbar-path' function, which takes a + toolbar specifier (or optionally, a symbol, such as `left', + `right', `default', or `nil', which refers to a particular + toolbar), and optionally, parameters such as the locale and the + tag set, which specify which actual instantiator inside of the + toolbar specifier is to be modified. A toolbar item path is + created similarly using a function called + `make-toolbar-item-path', which takes a toolbar specifier and a + string naming the caption of the toolbar item to be modified, as + well as, of course, optionally the locale and tag set parameters + and such. + + The usefulness of these path objects is as arguments to functions + that will use them as pointers to the place in a toolbar + instantiator where the modification should be made. Recall, for + example, the generalized property interface described above. If a + function such as `get' or `put' is called on a toolbar path or + toolbar item path, it will use the information contained in the + path object to retrieve or modify a property located at the end of + the path. The toolbar path objects can also be passed to new + functions that I propose defining, such as `add-toolbar-item', + `delete-toolbar-item', and `find-toolbar-item'. These functions + should be parallel to the functions for inserting, deleting, + finding, etc. items in a menu. The toolbar item path objects can + also be passed to the drop-handler functions defined in + Drag-n-Drop Interface Changes (drag-n-drop.html) to retrieve or + modify the drop handlers that are associated with a toolbar item. + (The idea here is that you can drag an object and drop it onto a + toolbar item, just as you could onto a buffer, an extent, a menu + item, or any other graphical element). + + 4. We should at least think about allowing for separate default and + buffer-local toolbars. The user should either be able to position + these toolbars one above the other, or side by side, occupying a + single toolbar line. In the latter case, the boundary between the + toolbars should be draggable, and if a toolbar takes up more room + than is allocated for it, there should be arrows that appear on + one or both sides of the toolbar so that the items in the toolbar + can be scrolled left or right. (For that matter, this sort of + interface should exist even when there is only one toolbar that is + on a particular toolbar line, because the toolbar may very well + have more items than can be displayed at once, and it's silly in + such a case if it's impossible to access the items that are not + currently visible). + + 5. The default context menu for toolbars (which should be specified + using a specifier called `default-toolbar-context-menu' according + to the rules defined above) should contain entries allowing the + user to modify the appearance of a toolbar. Entries would + include, for example, whether the toolbar is captioned, whether + the glyphs for the toolbar are visible (if the toolbar is + captioned but its glyphs are not visible, the toolbar appears as + nothing but text; you can set things up this way, for example, in + Netscape), an option that brings up a package for editing the + contents of a toolbar, an option to allow the caption face to be + dchanged (perhaps thorough jan `edit-faces' or `custom' + interface), etc. + + +  + File: internals.info, Node: Future Work -- Menu API Changes, Next: Future Work -- Removal of Misc-User Event Type, Prev: Future Work -- Toolbars, Up: Future Work + + 40.9 Future Work - Menu API Changes + =================================== + + Author: Ben Wing (mailto:ben@xemacs.org) + + 1. I propose making a specifier for the menubar associated with the + frame. The specifier should be called `default-menubar' and + should replace the existing `current-menubar' variable. This + would increase the power of the menubar interface and bring it in + line with the toolbar interface. (In order to provide proper + backward compatibility, we might have to complete the symbol value + handler mechanism (symbol-value-handlers.html)) + + 2. I propose an API for modifying menu instantiators similar to the + API composed above for toolbar instantiators. A new object called + a "menu path" (of type `menu-path') can be created using the + `make-menu-path' function, and specifies a location in a particular + menu instantiator where changes can be made. The first argument to + `make-menu-path' specifies which menu to modify and can be a + specifier, a value such as `nil' (which means to modify the default + menubar associated with the selected frame), or perhaps some other + kind of specification referring to some other menu, such as the + context menus invoked by the right mouse button. The second + argument to `make-menu-path', also required, is a list of zero or + more strings that specifies the particular menu or menu item in + the instantiator that is being referred to. The remaining + arguments are optional and would be a locale, a tag set, etc. The + menu path object can be passed to `get', `put' or other standard + property functions to access or modify particular properties of a + menu or a menu item. It can also be passed to expanded versions + of the existing functions such as `find-menu-item', + `delete-menu-item', `add-menu-button', etc. (It is really a shame + that `add-menu-item' is an obsolete function because it is a much + better name than `add-menu-button'). Finally, the menu path + object can be passed to the drop-handler functions described in + Drag-n-Drop Interface Changes (drag-n-drop.html) to access or + modify the drop handlers that are associated with a particular + menu item. + + 3. New keyword properties should be added to the menu item vector. + These include `:help-echo', `:context-menu' and `:drop-handlers', + with similar semantics to the corresponding keywords for toolbar + items. (It may seem a bit strange at first to have a context menu + associated with a particular menu item, but it is a user interface + concept that exists both in Open Look and in Windows, and really + makes a lot of sense if you give it a bit of thought). These + properties may not actually be implemented at first, but at least + the keywords for them should be defined. + + +  + File: internals.info, Node: Future Work -- Removal of Misc-User Event Type, Next: Future Work -- Mouse Pointer, Prev: Future Work -- Menu API Changes, Up: Future Work + + 40.10 Future Work - Removal of Misc-User Event Type + =================================================== + + Author: Ben Wing (mailto:ben@xemacs.org) + + *Abstract:* This page describes why the misc-user event type should + be split up into a number of different event types, and how to do this. + + The misc-user event should not exist as a single event type. It + should be split up into a number of different event types: one for + scrollbar events, one for menu events, and one or two for drag-n-drop + events. Possibly there will be other event types created in the + future. The reason for this is that the misc-user event was a bad + design choice when I made it, and it has only gotten worse with + Oliver's attempts to add features to it to make it be used for + drag-n-drop. I know that there was originally a separate drag-n-drop + event type, and it was folded into the misc-user event type on my + recommendation, but I have now realized the error of my ways. I had + originally created a single event type in an attempt to prevent some + Lisp programs from breaking because they might have a case statement + over various event types, and would not be able to handle new event + types appearing. I think now that these programs simply need to be + written in a way to handle new event types appearing. It's not very + hard to do this. You just use predicates instead of doing a case + statement over the event type. If we preserve the existing predicate + called `misc-user-event-p', and just make sure that it evaluates to + true when given any user event type other than the standard simple + ones, then most existing code will not break either when we split the + event types up like this, or if we add any new event types in the + future. + + More specifically, the only clean way to design the misc-user event + type would be to add a sub-type field to it, and then have the nature + of all the other fields in the event type be dependent on this + sub-type. But then in essence, we'd just be reimplementing the whole + event-type scheme inside of misc-user events, which would be rather + pointless. + +  + File: internals.info, Node: Future Work -- Mouse Pointer, Next: Future Work -- Extents, Prev: Future Work -- Removal of Misc-User Event Type, Up: Future Work + + 40.11 Future Work - Mouse Pointer + ================================= + + * Menu: + + * Future Work -- Abstracted Mouse Pointer Interface:: + * Future Work -- Busy Pointer:: + +  + File: internals.info, Node: Future Work -- Abstracted Mouse Pointer Interface, Next: Future Work -- Busy Pointer, Prev: Future Work -- Mouse Pointer, Up: Future Work -- Mouse Pointer + + 40.11.1 Future Work - Abstracted Mouse Pointer Interface + -------------------------------------------------------- + + Author: Ben Wing (mailto:ben@xemacs.org) + + *Abstract:* We need to create a new image format that allows + standard pointer shapes to be specified in a way that works on all + Windows systems. I suggest that this be called `pointer', which has + one tag associated with it, named `:data', and whose value is a string. + The possible strings that can be specified here are predefined by + XEmacs, and are guaranteed to work across all Windows systems. This + means that we may need to provide our own definition for pointer shapes + that are not standard on some systems. In particular, there are a lot + more standard pointer shapes under X than under Windows, and most of + these pointer shapes are fairly useful. There are also a few pointer + shapes (I think the hand, for example) on Windows, but not on X. + Converting the X pointer shapes to Windows should be easy because the + definitions of the pointer shapes are simply XBM files, which we can + read under Windows. Going the other way might be a little bit more + difficult, but it should still not be that hard. + + While we're at it, we should change the image format currently called + `cursor-font' to `x-cursor-font', because it only works under X + Windows. We also need to change the format called `resource' to be + `mswindows-resource'. At least in the case of `cursor-font', the old + value should be maintained for compatibility as an obsolete alias. The + `resource' format was added so recently that it's possible that we can + just change it. + +  + File: internals.info, Node: Future Work -- Busy Pointer, Prev: Future Work -- Abstracted Mouse Pointer Interface, Up: Future Work -- Mouse Pointer + + 40.11.2 Future Work - Busy Pointer + ---------------------------------- + + Author: Ben Wing (mailto:ben@xemacs.org) + + Automatically make the mouse pointer switch to a busy shape (watch + signal) when XEmacs has been "busy" for more than, e.g. 2 seconds. + Define the "busy time" as the time since the last time that XEmacs was + ready to receive input from the user. An implementation might be: + + 1. Set up an asynchronous timeout, to signal after the busy time; + these are triggered through a call to QUIT so they will be + triggered even when the code is busy doing something. + + 2. We already have an "emacs_is_blocking" flag when we are waiting for + input. In the same place, when we are about to block and wait for + input (regardless of whether input is already present), maybe call + a hook, which in this case would remove the timer and put back the + normal mouse shape. Then when we exit the blocking stage (we got + some input), call another hook, which in this case will start the + timer. Note that we don't want these "blocking" hooks to be + triggered just because of an accept-process-output or some similar + thing that retrieves events, only to put them back onto a queue + for later processing. Maybe we want some sort of flag that's + bound by those routines saying that we aren't really waiting for + input. Making that flag Lisp-accessible allows it to be set by + similar sorts of Lisp routines (if there are any?) that loop + retrieving events but defer them, or only drain the queue, or + whatnot. #### Think about whether it would make some sense to try + and be more clever in our determinations of what counts as "real + waiting for user input", e.g. whether the event gets dispatched + (unfortunately this occurs way too late, we want to know to remove + the busy cursor *before* getting an event), maybe whether there + are any events waiting to be processed or we'll truly block, etc. + (e.g. one possibility if there is input on the queue already when + we "block" for input, don't remove the busy- wait pointer, but + trigger the removal of it when we dispatch a user event). + +  + File: internals.info, Node: Future Work -- Extents, Next: Future Work -- Version Number and Development Tree Organization, Prev: Future Work -- Mouse Pointer, Up: Future Work + + 40.12 Future Work - Extents + =========================== + + * Menu: + + * Future Work -- Everything should obey duplicable extents:: + +  + File: internals.info, Node: Future Work -- Everything should obey duplicable extents, Prev: Future Work -- Extents, Up: Future Work -- Extents + + 40.12.1 Future Work - Everything should obey duplicable extents + --------------------------------------------------------------- + + Author: Ben Wing (mailto:ben@xemacs.org) + + A lot of functions don't properly track duplicable extents. For + example, the `concat' function does, but the `format' function does + not, and extents in keymap prompts are not displayed either. All of + the functions that generate strings or string-like entities should + track the extents that are associated with the strings. Currently this + is difficult because there is no general mechanism implemented for doing + this. I propose such a general mechanism, which would not be hard to + implement, and would be easy to use in other functions that build up + strings. + + The basic idea is that we create a C structure that is analogous to a + Lisp string in that it contains string data and lists of extents for + that data. Unlike standard Lisp strings, however, this structure (let's + call it `lisp_string_struct') can be incrementally updated and its + allocation is handled explicitly so that no garbage is generated. (This + is important for example, in the event-handling code which would want to + use this structure, but needs to not generate any garbage for efficiency + reasons). Both the string data and the list of extents in this string + are handled using dynarrs so that it is easy to incrementally update + this structure. Functions should exist to create and destroy instances + of `lisp_string_struct' to generate a Lisp string from a + `lisp_string_struct' and vice-versa to append a sub-string of a Lisp + string to a `lisp_string_struct', to just append characters to a + `lisp_string_struct', etc. The only thing possibly tricky about + implementing these functions is implementing the copying of extents from + a Lisp string into a `lisp_string_struct'. However, there is already a + function `copy_string_extents()' that does basically this exact thing, + and it should be easy to create a modified version of this function. + +  File: internals.info, Node: Future Work -- Version Number and Development Tree Organization, Next: Future Work -- Improvements to the `xemacs.org' Website, Prev: Future Work -- Extents, Up: Future Work 40.13 Future Work - Version Number and Development Tree Organization *************** *** 3733,5950 **** *Customize* Customize needs to deal with all this stuff!! - -  - File: internals.info, Node: Better Rendering Support -- Current Status, Next: Better Rendering Support -- Configuration with the Interim Patches, Prev: Better Rendering Support -- Implementation, Up: Future Work -- Better Rendering Support - - 40.24.3 Better Rendering Support - Current Status - ------------------------------------------------- - - Stephen has a branch containing his stuff in XEmacs CVS. The branch - point tag is `sjt-xft-bp', roughly corresponding to XEmacs 21.5.18, and - branch tag is `sjt-xft'. - - 40.24.3.1 Bugs Reported in sjt-xft - .................................. - - `ChangeLogs' - A lot of these, especially for Eric and Matthias's work, are - missing. Mea culpa. - - `Options->Font' - `Options->Font Size' - These menus don't work. All fonts are greyed out. All sizes are - available, but many (most?) faces don't change size, in particular, - `default' does not. - - `Antialiased text bleeding outside of reported extent' - On my PowerBook G4 Titanium 15" screen, X.org server v6.8.1, - dimensions: 1280x833 pixels (433x282 millimeters), - resolution: 75x75 dots per inch, depth of root window: 24 - planes (yes, those dimensions are broken), with font "Bitstream - Vera Sans Mono-16:dpi=75" antialiased text may bleed out of the - extent reported by XftTextExtents and other such facilities. This - is most obvious with the underscore character in that font. The - bottom of the underscore is antialiased, and insertions or - deletions in the same line before the underscore leave a series of - "phantom" underlines. Except that it doesn't happen on the very - first such insertion or deletion after a window refresh. A - similar effect sometimes occurs with deletions at the end of the - line (no, I can't define "sometimes"). See also comments in - `redisplay-x.c', functions `x_output_string' and - `x_output_display_block'. (Mostly duplicated here.) - - I think this is probably an Xft bug, but I'm not sure. - -  - File: internals.info, Node: Better Rendering Support -- Configuration with the Interim Patches, Next: Better Rendering Support -- Modern Font Support, Prev: Better Rendering Support -- Current Status, Up: Future Work -- Better Rendering Support - - 40.24.4 Better Rendering Support - Configuration with the Interim Patches - ------------------------------------------------------------------------- - - For Stephen's `sjt-xft' branch, you should keep the following in mind - when configuring: - - * Although the menus don't work, it is possible to specify fonts for - _faces_ using `set-face-font' (and other specifier-changing - functions). - - There currently is no explicit way to specify that a particular - font be used only for a given language. However, since many fonts - support only a limited repertoire such as ISO 8859/1, you can use - the precedence of specifications for a given specifier locale to - get something of this effect for non-Latin character sets. This - will normally work rather poorly for multiple Latin character - sets, however, because the repertoires tend to have large amounts - of overlap. Support for specifying font by _language_ as well as - by character set is planned. - - Because fonts supporting other languages tend to support English as - well, if you want to use one font for English and another for the - other language, you must use the `append' method when adding font - specifications for the _other_ language. - - However, this leaves you with a problem if you want to change the - other language's font: you have to remove the existing - specification so it won't shadow the new one when you append. - - I use `define-specifier-tag' like this: - - (define-specifier-tag 'lang-ja) - ;; No, I don't try to do real work with this font! But it makes it - ;; obvious that I got the requested font. :-) - (set-face-font 'default "AirCut-14") - (set-face-font 'default "Kochi Mincho-14" nil '(lang-ja) 'append) - ;; Oops, too sober. Try something to match AirCut. - (set-face-font 'default "Mikachan-14" - nil '(lang-ja) 'remove-tag-set-append) - - * The only way to configure widget fonts at the present time is to - use X resources (or hack the source and rebuild). Currently - supported widgets are - * menubars - - * tab controls - - Here are the resources I use. *Warning:* _This interface will - change._ The tab control and menubar have separate Font and - XftFont resources, and use the X resource manager to instantiate a - FontStruct from the Font resource. There is no converter facility - for XftFont yet, and creating one that handles both FontStruct and - XftFont depending on XEmacs's configuration and the font name - seems error-prone at best. Probably we will should to a simple - string representation for this resource, and convert to a face in - XEmacs rather than a font in Xt/Xft. - XEmacs*Tabs.xftFont: Bitstream Vera Sans-16 - XEmacs*menubar*xftFont: Bitstream Vera Sans-16 - XEmacs.modeline.attributeFont: Bitstream Charter-16 - XEmacs.default.attributeFont: Bitstream Vera Sans Mono-16 - I highly recommend use of a proportional font in the modeline - because it allows a lot more text to fit there. (Previously the - font sizes were quite varied, and there was a comment that this - weirdness gave good balance. This isn't true on my main platform, - Mac OS X, and needs to be rechecked on Linux, where it was - observed.) - -  - File: internals.info, Node: Better Rendering Support -- Modern Font Support, Prev: Better Rendering Support -- Configuration with the Interim Patches, Up: Future Work -- Better Rendering Support - - 40.24.5 Better Rendering Support - Modern Font Support - ------------------------------------------------------ - - *NB: This subtree eventually needs to be moved to the Lispref.* - - This chapter describes integration of the `Xft' font support library - into XEmacs. This library is a layer over the separate `FreeType' - rendering engine and `fontconfig' font query and selection libraries. - `FreeType' provides rendering facilities for modern, good-looking - TrueType fonts with hinting and antialiasing, while `fontconfig' - provides a coherent interface to font query and selection which is - independent of the rendering engine, although currently it is only used - in `Xft' to interface to `FreeType'. - - From the user's point of view, `fontconfig' provides a naming - convention which is _precise_, _accurate_, and _convenient_. Precision - means that all properties available in the programming API can be - individually specified. Accuracy means that the truename of the font - is exactly the list of all properties specified by the font. Thus, the - anomolies that occur with XLFDs on many servers (including modern Linux - distributions with XFree86 or X.org servers) cannot occur. Convenience - is subjective, of course. However, `fontconfig' provides a - configuration system which (1) explicitly specifies the defaults and - substitutions that will be made in processing user queries, and (2) - allows the user to specify search configuration, abbreviations, - substitutions, and defaults that override the system's, in the same - format as used by system files. Further, a "standard minimal - configuration" is defined that ensures that at least _serif_, - _sans-serif_, and _monospace_ fonts are available on all `fontconfig' - systems. - - * Menu: - - * Modern Font Support -- Font Concepts:: GUI devices, fonts, glyphs, rendering. - * Modern Font Support -- fontconfig:: Querying and selecting fonts. - * Modern Font Support -- Xft:: Rendering fonts on X11. - -  - File: internals.info, Node: Modern Font Support -- Font Concepts, Next: Modern Font Support -- fontconfig, Up: Better Rendering Support -- Modern Font Support - - 40.24.5.1 Modern Font Support - Font Concepts - ............................................. - - In modern systems, displays are invariably "raster graphic devices", - which present an abstract interface of "pixel array" where each "pixel - value" is a color, and each pixel is individually mutable, and - (usually) readable. In XEmacs, such devices are collectively called - "GUI devices", as opposed to "TTY devices" which are character stream - devices but may support control sequences for setting the color of - individual characters, and the insertion position in a rectangular - array. Here we are concerned only with control of GUI devices but use - TTY devices as a standard for comparison. - - A "font" is an indexed collection of "glyphs", which are - specifications of character shapes. On a TTY device, these shapes are - entirely abstract, and the index is the identity function. Typically - fonts are embedded in TTY devices, the user has no control over the font - from within the application, and where choice is available, there is - limited selection, and no extensibility. Simple, functional, and ... - ugly. - - On GUI devices, the situation is different in every respect. Glyphs - may be provided by the device, the application, or the user. Additional - glyphs may be added at will at any of those levels. Arbitrary index - functions allow the same glyph to be used to display characters in - different languages or using application-specific codes. Glyphs have - concrete APIs, allowing fine control of rendering parameters, even - user-specified shapes. To provide convenient, consistent handling of - collections of glyphs, we need a well-defined font API. - - We can separate the necessary properties into two types: properties - which are common to all glyphs in the collection or a property of the - collection itself, and those which are glyph-specific. Henceforth, the - former are called "font properties" and the latter "glyph properties". - - Font properties include identification like the font "family", - font-wide design parameters like "slant" and "weight", font "metrics" - like "size" (nominal height) and "average width" used for approximate - layout (such as sizing a popup dialog), and properties like the - "default glyph" that are associated with the font for convenient use by - APIs, but aren't really an intrinsic property of the font as a - collection of glyphs. There may also be a "kerning table" (used to - improve spacing of adjacent glyphs). - - Glyph properties include the "index", glyph metrics such as - "ascent", "descent", "width", "offset" (the offset to the normal - position of the next glyph), "italic correction" (used to improve - spacing when slanted and unslanted glyphs are juxtaposed). Most - important, of course, is the glyph's shape, which is provided in a - format specific to a rendering engine. Common formats include bitmaps - (X11 BDF), Postcript programs (Type 1), and collections of spline curves - (TrueType). When the shape is not itself a bitmap, it must be - "rendered" to a pixmap, either a region on the display or a separate - object which is copied to the display. In that case, the shape may - include "multiple masters" or "hints" to allow context-specific - rendering which improves the appearance of the glyph on the display. - - Note that this use of "glyph" is mostly independent of the XEmacs - LISP glyph API. *Note Glyphs::. It is possible to extract a single - glyph from a font and encapsulate it in Lisp_Glyph object, but the LISP - glyph API allows access to only a very few glyph properties, none of - them related to the rendering process. - - XEmacs LISP does provide an API for selecting and querying fonts, in - the form of a fairly complete set of wrappers for `fontconfig' (*note - Modern Font Support -- fontconfig::). It also provides some control of - rendering of text via wrappers for `Xft' APIs (*note Modern Font - Support -- Xft::), but this API is quite incomplete. Also, since the - font selection and query facilities of `Xft' are provided by - `fontconfig', there is some confusion in the API. For example, use of - antialiasing to improve the appearance of rendered glyphs can be - enabled or disabled. The API for this is to set the `fontconfig' font - property `antialias' on the font. However, from the point of view of - `fontconfig' this is merely a hint that the rendering engine may or may - not respect. This property cannot be used to select only fonts - suitable for being antialiased, for example. And `rgba' (subpixel - geometry) and `dpi' (pixel density) are conceptually properties of the - display, not of either the font. They function as hints to the - rendering process. - - As a final confusing touch, `Xft' also provides some access to the - `XRender' extension provided by some modern X servers. This is mostly - limited to colors, but rectangle APIs are also provided. These are (of - course) completely independent of fonts, but `Xft' is designed for - client-side font rendering, and thus uses the `XRender' extension - heavily. - -  - File: internals.info, Node: Modern Font Support -- fontconfig, Next: Modern Font Support -- Xft, Prev: Modern Font Support -- Font Concepts, Up: Better Rendering Support -- Modern Font Support - - 40.24.5.2 Modern Font Support - fontconfig - .......................................... - - _Implementation notes_: The functions which initialize the library and - handle memory management (_e.g._, `FcInit' and `FcPatternDestroy') are - intentionally not wrapped (in the latter case, `fc-pattern-destroy' was - provided, but this was ill-considered and will be removed; LISP code - should *never* call this function). Thinking about some of the - auxiliary constructs used by `fontconfig' is in transition. The - `FcObjectSet' API has been internalized; it is exposed to LISP as a - list of strings. The `FcFontSet' API is still in use, but it also will - be internalized, probably as a list (alternatively, vector) of - `Lisp_fc_pattern' objects. Changing the representation of `fontconfig' - objects (property names) from LISP strings to keywords is under - consideration. - - If `Xft' (including `fontconfig') support is integrated into the - XEmacs build, XEmacs provides the symbol `xft' at initialization. - - XEmacs provides the following functions wrapping the `fontconfig' - library API. - - -- Function: fc-fontset-p object - Returns t if OBJECT is of type fc-fontset, nil otherwise. _This - API is likely to be removed in the near future._ - - -- Function: fc-fontset-count fcfontset - Counts the number of fc pattern objects stored in the fc fontset - object FCFONTSET. _This API is likely to be removed in the near - future._ - - -- Function: fc-fontset-ref fcfontset i - Return the fc pattern object at index I in fc fontset object - FCFONTSET. Return nil if the index exceeds the bounds of - FCFONTSET. _This API is likely to be removed in the near future._ - - -- Function: fc-fontset-destroy fcfontset - Explicitly deallocate FCFONTSET. _Do not call this function from - LISP code. You will crash. This API will be removed in the near - future._ - - -- Function: fc-pattern-p object - Returns t if OBJECT is of type fc-pattern, nil otherwise. - - -- Function: fc-pattern-create - Return a fresh and empty fc-pattern object. - - -- Function: fc-name-parse name - Parse string NAME as a fontconfig font name and return its - representation as a fc pattern object. - - -- Function: fc-name-unparse pattern - Unparse pattern object PATTERN to a string. - - `Xft''s similar function is actually a different API. We provide - both for now. (They probably invoke the same code from `fontconfig' - internally, but the `fontconfig' implementation is more conveniently - called from C.) - - -- Function: xft-name-unparse pattern - Unparse pattern object PATTERN to a string (using the `Xft' API). - - -- Function: fc-pattern-duplicate pattern - Make a copy of pattern object PATTERN and return it. - - -- Function: fc-pattern-add pattern property value - Add attributes to the pattern object PATTERN. PROPERTY is a - string naming the attribute to add, VALUE the value for this - attribute. - - VALUE may be a string, integer, float, or symbol, in which case - the value will be added as an FcChar8[], int, double, or FcBool - respectively. - - -- Function: fc-pattern-del pattern, property - Remove attribute PROPERTY from pattern object PATTERN. - - This is the generic interface to `FcPatternGet'. We don't support - the losing symbol-for-property interface. However, it might be a very - good idea to use keywords for property names in LISP. - - -- Function: fc-pattern-get pattern property &optional id type - From PATTERN, extract PROPERTY for the ID'th member, of type TYPE. - - PATTERN is an `Xft' (`fontconfig') pattern object. PROPERTY is a - string naming a `fontconfig' font property. Optional ID is a - nonnegative integer indexing the list of values for PROPERTY - stored in PATTERN, defaulting to 0 (the first value). Optional - TYPE is a symbol, one of 'string, 'boolean, 'integer, 'float, - 'double, 'matrix, 'charset, or 'void, corresponding to the FcValue - types. ('float is an alias for 'double). - - Symbols with names of the form `fc-result-DESCRIPTION' are - returned when the desired value is not available. These are - - fc-result-type-mismatch the value found has an unexpected type - fc-result-no-match there is no such attribute - fc-result-no-id there is no value for the requested ID - - The Lisp types returned will conform to TYPE: - - string string - boolean `t' or `nil' - integer integer - double (float) float - matrix not implemented - charset not implemented - void not implemented - - The types of the following standard properties are predefined by - fontconfig. The symbol 'fc-result-type-mismatch will be returned if the - object exists but TYPE does not match the predefined type. It is best - not to specify a type for predefined properties, as a mistake here - ensures error returns on the correct type. - - Each standard property has a convenience accessor defined in - `fontconfig.el', named in the form `fc-pattern-get-PROPERTY'. The - convenience functions are preferred to `fc-pattern-get' since a typo in - the string naming a property will result in a silent null return, while - a typo in a function name will usually result in a compiler or runtime - \"not fboundp\" error. You may use `defsubst' to define convenience - functions for non-standard properties. - - family String Font family name - style String Font style. Overrides weight and slant - slant Int Italic, oblique or roman - weight Int Light, medium, demibold, bold or black - size Double Point size - aspect Double Stretches glyphs horizontally before hinting - pixelsize Double Pixel size - spacing Int Proportional, monospace or charcell - foundry String Font foundry name - antialias Bool Whether glyphs can be antialiased - hinting Bool Whether the rasterizer should use hinting - verticallayout Bool Use vertical layout - autohint Bool Use autohinter instead of normal hinter - globaladvance Bool Use font global advance data - file String The filename holding the font - index Int The index of the font within the file - ftface FT_Face Use the specified FreeType face object - rasterizer String Which rasterizer is in use - outline Bool Whether the glyphs are outlines - scalable Bool Whether glyphs can be scaled - scale Double Scale factor for point->pixel conversions - dpi Double Target dots per inch - rgba Int unknown, rgb, bgr, vrgb, vbgr, none - subpixel geometry - minspace Bool Eliminate leading from line spacing - charset CharSet Unicode chars encoded by the font - lang String List of RFC-3066-style languages this font supports - - The FT_Face, Matrix, CharSet types are unimplemented, so the - corresponding properties are not accessible from Lisp at this time. If - the value of a property returned has type FT_Face, FcCharSet, or - FcMatrix, `fc-result-type-mismatch' is returned. - - The following properties which were standard in `Xft' v.1 are - obsolete in `Xft' v.2: `encoding', `charwidth', `charheight', `core', - and `render'. - - -- Function: fc-pattern-destroy pattern - Explicitly deallocate pattern object PATTERN. _Do not call this - function from LISP code. You will crash. This API will be removed - in the near future._ - - -- Function: fc-font-match device pattern - Return the font on DEVICE that most closely matches PATTERN. - - PATTERN is a `fontconfig' pattern object. DEVICE is an X11 - device. Returns a `fontconfig' pattern object representing the - closest match to the given pattern, or an error code. Possible - error codes are `fc-result-no-match' and `fc-result-no-id'. - - -- Function: fc-list-fonts-pattern-objects device pattern properties - List the fonts on DEVICE that match PATTERN for PROPERTIES. - DEVICE is an X11 device. PATTERN is a `fontconfig' pattern to be - matched. PROPERTIES is the list of property names (strings) that - should be included in each returned pattern. The result is a - `fontconfig' fontset object containing the set of unique matching - patterns. - - The PROPERTIES argument does not affect the matching. So, for - example, - - (mapcar #'fc-name-unparse - (let ((xfl (fc-list-fonts-pattern-objects nil - (fc-name-parse "FreeMono") '("style"))) - (i 0) - (fl nil)) - (while (< i (fc-fontset-count xfl)) - (push (fc-fontset-ref xfl i) fl) - (setq i (1+ i))) - fl)) - - will return something like `(":style=Bold" ":style=Medium" - ":style=Oblique" ":style=BoldOblique")' if you have the FreeFont - package installed. Note that the sets of objects in the target pattern - and the returned patterns don't even intersect. - - In using `fc-list-fonts-pattern-objects', be careful that only - intrinsic properties of fonts be included in the pattern. Those - properties included in the pattern must be matched, or the candidate - font will be eliminated from the list. When a font leaves a property - unspecified, it is considered to be a mismatch for any pattern with that - property specified. Thus, inclusion of extraneous properties will - result in the list being empty. Note that for scalable fonts (at - least), `size' is not an intrinsic property! Thus a specification such - as `"Bitstream Vera Sans-12"' will return an empty list regardless of - whether the font is available or not--probably not what you (as - programmer or user) want. - - The list is unsorted. In particular, the pattern - `":style=italic,oblique"' will not return italic fonts first, then - oblique ones. The fonts will be returned in some arbitrary order. - - _Implementation notes_: Fontset objects are slated for removal from - the API. In the future `fc-list-fonts-pattern-objects' will return a - list. The DEVICE argument is unused, ignored, and may be removed if - it's not needed to match other font-listing APIs. This name will be - changed to correspond to Ben's new nomenclature, probably simply - `fc-font-list'. - - -- Function: fc-font-sort device pattern trim - Return a fontset object listing all fonts sorted by proximity to - PATTERN. DEVICE is an X11 device. PATTERN is a fontconfig - pattern to be matched. Optional argument TRIM, if non-nil, means - to trim trailing fonts that do not contribute new characters to - the union repertoire. - - _Implementation notes_: Fontset objects are slated for removal from - the API. In the future `fc-font-sort' will return a list (or perhaps a - vector) of FcPatterns. The DEVICE argument is unused, ignored, and may - be removed if it's not needed to match other font-listing APIs. - - -- Function: fc-font-real-pattern fontname xdevice - Temporarily open font FONTNAME (a string) on device XDEVICE and - return the actual fc pattern matched by the Fc library. _This - function doesn't make much sense and will be removed from the API._ - - -- Function: xlfd-font-name-p fontname - Check whether string FONTNAME is a XLFD font name. - - -- Variable: xft-debug-level - Level of debugging messages to issue to stderr for XFT. A - nonnegative integer. Set to 0 to suppress all warnings. Default - is 1 to ensure a minimum of debugging output at initialization. - Higher levels give more information. - - -- Variable: xft-version - The major version number of the Xft library compiled with. - - -- Variable: xft-xlfd-font-regexp - Regular expression matching XLFD font names. - -  - File: internals.info, Node: Modern Font Support -- Xft, Prev: Modern Font Support -- fontconfig, Up: Better Rendering Support -- Modern Font Support - - 40.24.5.3 Modern Font Support - fontconfig - .......................................... - - IIRC, we don't really provide any `Xft' APIs at the LISP level yet. - -  - File: internals.info, Node: Future Work Discussion, Next: Old Future Work, Prev: Future Work, Up: Top - - 41 Future Work Discussion - ************************* - - This chapter includes (mostly) email discussions about particular design - issues, edited to include only relevant and useful stuff. Ideally over - time these could be condensed down to a single design document to go - into the normal Future Work section. - - * Menu: - - * Discussion -- Garbage Collection:: - * Discussion -- Glyphs:: - * Discussion -- Dialog Boxes:: - * Discussion -- Multilingual Issues:: - * Discussion -- Instantiators and Generic Property Accessors:: - * Discussion -- Switching to C++:: - * Discussion -- Windows External Widget:: - * Discussion -- Packages:: - * Discussion -- Distribution Layout:: - -  - File: internals.info, Node: Discussion -- Garbage Collection, Next: Discussion -- Glyphs, Prev: Future Work Discussion, Up: Future Work Discussion - - 41.1 Discussion - Garbage Collection - ==================================== - - * Menu: - - * Discussion -- Pure Space:: - * Discussion -- Hashtable-Based Marking and Cleanup:: - * Discussion -- The Anti-Cons:: - -  - File: internals.info, Node: Discussion -- Pure Space, Next: Discussion -- Hashtable-Based Marking and Cleanup, Prev: Discussion -- Garbage Collection, Up: Discussion -- Garbage Collection - - 41.1.1 Discussion - Pure Space - ------------------------------ - - On Tue, Oct 12, 1999 at 03:36:59AM -0700, Ben Wing wrote: - - So what am I missing here? - - In response, Olivier Galibert wrote: - - Two things: - 1. The purespace is gone - - I mean absolutely, completely and utterly removed. Fpurecopy - is a no-op now (and have been for some time). Readonly objects - are gone too. Having less checks to do in Fsetcar, Fsetcdr, - Faset and some others is probably a good thing, speedwise. I - have it removed some time ago because it does not make sense - when using a portable dumper to copy data in a special area of the - memory at dump time and I wanted to be sure that supressing the - copying from Fpurecopy wouldn't break things. - - Now, we want to get the post-dumping data sharing back, of course. - In today systems, it is quite easy: you just have to map - the file MAP_PRIVATE and avoid writing to the subset of pages - you want to keep shared. Copy-on-write does the job for you. - It has the nice side effect of completely avoiding bus errors - due to trying to write to readonly memory zones. - - Avoiding writing to the "pure" objects themselves is already - done, of course. Would lisp code have written to the purecopied - parts of the dumped data that it would have exploded long ago. So - there is nothing to do in this area. So the only remaining thing - is the markbit. Two possible strategies: - - * have Fpurecopy mark somehow the lrecords it would have copied - in the good old times. Post-dump, use this mark as a "always - marked, don't touch, don't look into, don't free" flag, the - same way CHECK_PURE was used. - - * move the markbit outside of the lrecord. - - The second solution is more appealing to me for a bunch of reasons: - * more things are shared than only what is purecopied (not - yet used functions come to mind) - - * no more "the only references to this non-purecopied object - are from purecopied objects, XEmacs will self-destruct in - ten seconds" kind of bugs. - - * removing flags goes the right way towards implementing - Jan's allocator ideas. - - * it becomes probably easier to experiment with the GC code - - 2. Finding all the dumped objects in order to unmark them sucks - - Not having to rebuild a list of all the dumped objects in - order to find them all and ensure that all are unmarked - simplifies things for me. Errr, ok, now that I really think of - it, I can rebuild this list easily, in fact. And I'm probably - going to have to manage it, since I feel like the lack of calls - to the finalizers for the dumped objects is going to someday - turn over and bite me in the face. But anyways, it makes my life - easier for now. - - So no, it's not a _necessity_. But it helps. And the - automatic sharing of all objects until you write to them - explicitely is, I think, really cool. - -  - File: internals.info, Node: Discussion -- Hashtable-Based Marking and Cleanup, Next: Discussion -- The Anti-Cons, Prev: Discussion -- Pure Space, Up: Discussion -- Garbage Collection - - 41.1.2 Discussion - Hashtable-Based Marking and Cleanup - ------------------------------------------------------- - - On 10/12/1999 5:49 PM Ben Wing wrote: - - OK, I can see the advantages. But: - - 1. There will be an inevitable loss of speed using a large hashtable. - If it's large, I say that it's just not worth it. There are - things that are so much more important than futzing around with - the garbage collector (e.g. fixing the god damn user interface), - things which if not fixed will sooner or later cause XEmacs to die - entirely. If we are causing a major slowdown in the name of some - not-so-important work that may or may not get done, we shouldn't - do it. (On the other hand, if the slowdown is negligible, I have - no problems with this.) - - 2. I think you should *expand* the concept of read-only objects so - that *any* object (especially strings and cons cells) can get - marked read-only by the C code if it wants. (Perhaps you could use - the now-unused mark bit to hold a read-only flag.) This is - important because it allows C code to directly return internal - lists (e.g. from the specifiers and various object property lists) - without having to do a copy, like is now done (and similarly, - potentially to directly accept lists from a Lisp call without - copying them for internal use, if the Lisp caller is made aware - that the list might become read-only) - if the copy weren't done - and some piece of Lisp code went and modified the list, XEmacs - might very well crash. Thus, this read-only flag would be a huge - efficiency gain in terms of the garbage collection overhead saved - as well as the speed of copying a large list. The extra checks in - `Fsetcar()', etc. for this that you mention are in fact negligible - in their speed overhead - one or two instructions - and these - functions are not used all that commonly, either. With the - changes I have proposed in Architecting XEmacs, the case of - returning an internal list will become more and more common as the - power of the user interface would be greatly increased and along - with it are lots and lots of lists of info that need to be - retrievable from Lisp. - - BTW there is a wonderful book all about garbage collection by Jones - and Lins. Ever seen it? - - http://www.amazon.com/exec/obidos/ASIN/0471941484/qid=939775572/sr=1-1/002-3092633-2509405 - -  - File: internals.info, Node: Discussion -- The Anti-Cons, Prev: Discussion -- Hashtable-Based Marking and Cleanup, Up: Discussion -- Garbage Collection - - 41.1.3 Discussion - The Anti-Cons - --------------------------------- - - From: "Ben Wing" Date: Tue, 14 May 2002 06:48:09 -0700 - - i was thinking about the proliferating types of weak hash tables - - e.g. now we have "key-car-value weak" hash tables due to a need in the - glyphs code. i realized there should be a general solution, that lets - you control exactly how the weakness of such hash tables work. - - and, assuming we implement a simple "reference" type, a simple - container whose object is a weak reference and thus gets converted to - nil (and a flag set on the reference) when the object is collected, it - would be useful for more precisely controlling the reference, too. - - it's called an "anti-cons". it behaves somewhat like a cons in that - it boxes two items, but its marking properties are very different - in - fact, backwards. normally, a cons, if marked, marks its children. in - this case, if the children of an anti-cons are marked, it marks itself! - you'd need a few different kinds of anti-cons - probably the following: - - and [marks itself if both children marked] - or [...] - left [marks itself if left is marked, and then marks the right] - right [...] - not-left - not-right - - by putting such an object inside of a weak reference - e.g. in a weak - hash table - we can set up a tree of arbitrary complexity which - implements any boolean formula of markedness over any number of - objects. this would easily handle key-car, and key-cadr, and - key-car-or-cdr, and key-((caar or cadr) and cdr) etc. etc. - - implementing this in the current xemacs framework is mostly trivial. - - michael, would such an object get in the way of your new gc? - - From: sperber@informatik.uni-tuebingen.de (Michael Sperber [Mr. - Preprocessor]) Date: Tue, 14 May 2002 16:04:01 +0200 - - You might want to look at - - http://research.microsoft.com/Users/simonpj/Papers/weak.htm - - for a pretty comprehensive survey of what you could want in terms of - weakness. Its weak pointers are very similar to your anti-cons. - However, there are some problems in doing the same in a Lisp settings, - mainly because of symbols. I intend to elaborate on this next week; - this week is full, unfortunately. - - Ben> implementing this in the current xemacs framework is mostly - Ben> trivial. - - Ben> michael, would such an object get in the way of your new gc? - - Well, our first commit will be an implementation of vanilla weak - boxes (ready within the next few days, I hope), and we'll then try to - replace most other instances of weakness with uses of those. We'll - then try to find a more general solution for the rest. (Richard - Reingruber has already done a comprehensive survey of the trouble spot. - - Can you wait until next week? I'll try to come up with a battle plan - then. - - From: sperber@informatik.uni-tuebingen.de (Michael Sperber [Mr. - Preprocessor]) Date: Tue, 28 May 2002 16:14:20 +0200 - - We've now started implementing ephemerons as a building block for the - more involved weakness-involving data structures: - - The relevant reference is - - Barry Hayes. Ephemerons: A New Finalization Mechanism. OOPSLA 1997. - 176-183 - - The idea is this: - - an ephemeron consists of a key and a value. Through the ephemeron, - the key is not reachable. The value is only reachable if both the - ephemeron is reachable and the key is reachable. If the ephemeron is - reachable and the key becomes unreachable, the value slot of the - ephemeron will be tombstoned, i.e. overwritten with NIL or something. - - This allows implementing, AFAICS, the other data structures involving - weakness, such as weak hash tables and their various mutants. - - We're also planning to come up with a more comprehensive solution for - finalization, but some design snags remain to be worked out. - -  - File: internals.info, Node: Discussion -- Glyphs, Next: Discussion -- Dialog Boxes, Prev: Discussion -- Garbage Collection, Up: Future Work Discussion - - 41.2 Discussion - Glyphs - ======================== - - Some comments (not always pretty!) by Ben: - - March 20, 2000 - - Andy, I use the tab widgets but I've been having lots of problems. - - 1] Sometimes clicking on them does nothing. - - 2] There's a design flaw: I frequently use M-C-l to switch to the - previous buffer. If I use this in conjunction with the tabs, things get - all screwed up because selecting a buffer with the tab does not bring it - to the front of the buffer list, like it should. It looks like you're - doing this to avoid having the order of the tabs change, but this is - wrong: If you don't reorder the buffer list, everything else gets - screwed up. If you want the order of the tabs not to change, you need - to decouple this order from the buffer list order. - - March 23, 2000 - - I'm very confused. The SIGIO timer is used *only* for C-g. It has - nothing to do with any other events. (sit-for 0) ought to - - (1) cause all pending non-command events to get executed, and (b) do - redisplay - - However, sit-for gets preempted by input coming in. - - What about (sit-for 0.1)? - - I suppose a solution along the lines of dispatch-non-command-events - might be OK if you've tried everything else and it doesn't work, but i'm - leery of introducing new Lisp functions to deal with specific problems. - Pretty soon we end up with a whole bevy of such ill-defined functions, - like we already have. I think instead, you should introduce the - following primitive: - - (wait-for-event redisplay &rest event-specs) - - Waits for one of the event specifications specified to happen. - Returns something about what happened. - - REDISPLAY controls the behavior of redisplay during waiting. - Something like - - * nil (never redisplay), - - * t (redisplay when it seems appropriate), etc. - - EVENT-SPECS could be - - t -- drain all non-user events, and then return - any-process -- wait till input or state change on any process - process -- wait till input or state change on process - time -- wait till such-and-such time has elapsed - 'user -- wait till user event has happened - '(user predicate) -- wait till user event matching the predicate has - happened - 'event -- wait till any event has happened - '(event predicate) -- wait till event matching the predicate has happened - - The existing functions `next-event', `next-command-event', - `accept-process-output', `sit-for', `sleep-for', etc. could all be - written in terms of this new command. You could use this command inside - of your glyph code to ensure that the events get processed that need do - in order for widget updates to happen. - - But you said something about need a magic event to invoke redisplay? - Why is that? - - April 2, 2000 - - the internal distinction between "widget" and "layout" is bogus. - there exist widgets that do drawing and do layout of their children, - e.g. group-box widgets and proper tab widgets. the only sensible - distinction is between widgets with children and those without children. - - April 5, 2000 - - andy, i'm not sure i really believe that you need to cycle the event - code to get widgets to redisplay, but in any case you should - - 1. hide the logic to do this in the c code; the lisp code should do - nothing other than call (redisplay widget) - - 2. make sure your event-cycling code processes *NO* events at all. - this includes non-user events. queue the events instead. - - in other words, dispatch-non-command-events must go, and i am - proposing a general function (redisplay OBJECT) to replace the existing - ad-hoc functions. - - April 6, 2000 - - the tab widget code should simply be able to create a whole lot of - tabs without regard to the size of the gutter, and the surrounding - layout widget (please please make layouts be proper widgets!) should - automatically map and unmap them as necessary, to fill up the available - space. perhaps this already works and what you're doing is just for - optimization? but i get the feeling this is not the case. - - April 6, 2000 - - the function make-gutter-only-dialog-frame is bogus. the use of the - gutter here to hold widgets is an implementation detail and should not - be exposed in the interface. similarly, make-search-dialog should not - have to do all the futzing that it does. creating the frame unmapped, - creating an extent and messing with the gutter: all this stuff should be - hidden. you should have a simple function make-dialog-frame that takes - a dialog specification, and that's all you need to do. - - also, these dialog boxes, and this function make-dialog-frame, should - - 1. be in `dialog.el', not gutter-items.el. - - 2. when possible, be placed in the interactive spec of standard lisp - functions rather than accessed directly from `menubar-items.el' - - 3. wrapped in calls to should-use-dialog-box-p, so the user has - control over when dialog boxes appear. - - April 7, 2000 - - hmmm ... in that case, the whitespace absolutely needs to be - specified as properties of the layout widget (e.g. :border-width and - :border-height), rather than setting an overall size. you have no idea - what the correct size should be if the user changes font size or uses - translations in a different language. - - Your modus operandi should be "hardcoded pixel sizes are *always* - bad." - - April 7, 2000 - - you mean the number of tabs adjusts, or the size of each tab adjusts - (by making the font smaller or something)? if the size of a single tab - is not related to the total space the tabs can fix into, then it should - be possible to simply specify as many tabs as exist for buffers, and - have the layout manager decide how many can fit into the available - space. this does *not* mean the layout manager will resize the tabs, - because query-geometry on the tabs should find out that the tabs don't - want to be any size other than they are. - - the point here is that you should not *have* to worry about pixel - heights and widths *anywhere* in Lisp-level code. The layout managers - should take care of everything for you. The only exceptions may be in - some text fields, which will be blank by default and you want to specify - a maximum width (which should be done in 'n' sizes, not in pixels!). - - i won't stop complaining until i see nearly every one of those - pixel-width and pixel-height parameters gone, and the remaining ones - there for a very, very good reason. - - April 7, 2000 - - Andy Piper wrote: - - > At 03:51 PM 4/6/00 -0700, Ben Wing wrote: - > >[the function make-gutter-only-dialog-frame is bogus] - > - > The problem is that some of the callbacks and such need access to the - > *created* frame, so you end up in a catch 22 unless you do what I've done. - - [Ben proposes other ways to avoid exposing all the guts, as in - `make-gutter-only-dialog-frame':] - - 1. Instead of passing in the actual glyph spec or glyph, pass in a - function of two args (the dialog frame and its parents), which when - called, creates and returns the appropriate glyph. - - 2. [Better] Provide a way for callbacks to determine where they were - invoked at. This is much more general and is what you should - really do. For example, have the code that calls the callbacks - bind some global variables such as widget-callback-current-glyph - and widget-callback-current-channel, which contain the glyph whose - callback is being invoked, and the window or frame of the glyph - (depending on where the glyph is) where the invocation actually - happened. That way, the callbacks can easily figure out the dialog - box and its parent, and not have to worry about embedding it in at - creation time. - - April 15, 2000 I don't understand when you say "the various types of - callback". Are you using the callback for various different purposes? - - Your widget callbacks should work just like any other callback: they - take two arguments, one indicating the object to which the callback was - attached (an image instance, i think), and the event that caused the - callback to be invoked. - - April 17, 2000 - - I am completely vetoing widget-callback-current-channel. How about - you create a new keyword, :new-callback, that is a function of two args, - like i specified before. - - btw if you really are calling your callback using call-interactively, - why don't you declare a function (interactive "e") and then call - event-channel on the resulting event? that should get you the same - result as widget-callback-current-channel. - - the problem with this and everything you've proposed is that there's - no way, of course, to get at the actual widget that you were invoked - from. would you propose adding widget-callback-current-widget? - -  - File: internals.info, Node: Discussion -- Dialog Boxes, Next: Discussion -- Multilingual Issues, Prev: Discussion -- Glyphs, Up: Future Work Discussion - - 41.3 Discussion - Dialog Boxes - ============================== - - From: - Ben Wing - 10/7/1999 5:57 PM - - Subject: - Re: Animated gif patch (2) - To: - Andy Piper - CC: - xemacs-review@xemacs.org, xemacs-beta@xemacs.org - - - - - The distinction between layouts and widgets makes no sense, so you should combine - the different data required. Consider a grouping widget. Is this a layout or a - widget? It draws, like a widget, but has children, like a layout. Same for a tab - widget, properly implemented. It draws, handles input, has children, and makes - choices about how to lay them out. - - ben - - From: - Ben Wing - 9/7/1999 8:50 PM - - Subject: - Re: Layouts done - To: - Andy Piper - - - - - this sounds great! where can i see the code? - - as for user-defined layouts, you must certainly have some sort of abstraction - layer for layouts, with DEFINE_LAYOUT_TYPE or something similar just like device - types and such. If not, you should certainly make one ... it would have methods - such as query-geometry and do-layout. It should be easy to create a user-defined - layout if you have such an abstraction. - - with a user-defined layout, complex built-in layouts such as grid should not be - necessary because it's so easy to write snippets of lisp. - - as for the "redisplay too much" problem, perhaps you could put a dirty flag in - each glyph indicating whether it needs to be redisplayed, recalculated, etc.? - - Andy Piper wrote: - - > You may want to check them out. I haven't done the user-defined layout - > callback - I'm not sure what sort of API this could have. Keywords I've done: - > - > :orientation - vertical or horizontal - > :justify - left, center or right - > :border - etch-in, etch-out, bevel-in, bevel -out or text (which gives you - > etch-in with a title) - > - > You can embed any glyph type in a layout. - > - > There is probably room for improvements for justify to do grid-type layouts - > as per java. - > - > The only annoying thing is that I've hacked up font-lock support to do a - > progress gauge in the gutter area. I've used a layout to set things out - > correctly. The problem is if you change one of the sub-widgets, the whole - > layout gets redisplayed because it is treated as a single glyph by redisplay. - > - > Oh, and I've done line based scrolling so that glyphs scroll off the page - > in units of the average display line height rather than the whole line at - > once. This could easily be converted to pixel scrolling but would be very - > slow I fear. - > - > andy - > -------------------------------------------------------------- - > Dr Andy Piper - > Senior Consultant Architect, BEA Systems Ltd - - - - - From: - Ben Wing - 8/10/1999 11:11 PM - - Subject: - Re: Widgets - To: - Andy Piper - - - - - I think you might have misinterpreted what i meant. I meant to say that XEmacs should - implement the *concept* of a hierarchy of nested child "widgets" or "gui items" or - whatever we want to call them -- this includes container "widgets" such as grouping - widgets (which draw a border around the children, like in Windows), tab widgets, simple - layout widgets (invisible, but lay out their children appropriately), etc, plus leaf - "widgets" (buttons, sliders, etc., also standard Emacs windows). The layout calculations - for these widgets would be handled entirely by XEmacs in a window-system-independent way. - There is no need to create a corresponding hierarchy of window-system - widgets/controls/whatever if it's not required, and certainly no need to try to use the - window-system-supplied geometry management routines. It's absolutely necessary to support - this nesting concept in XEmacs, however, or it's impossible to have easily-designable - dialog boxes. On the other hand, I think it *is* required to create much of this - hierarchy within the actual window system, at the very least for non-invisible container - widgets (tab, grouping, etc.), otherwise we will have very bogus, non-native-looking - containers like your current tab-widget implementation. It's critical for XEmacs to be - able to create dialog boxes in Windows or Motif that look just like those in any other - standard application. Otherwise people will continue to think that XEmacs is a - backwards-looking, badly implemented piece of software, which in many ways it is, - particularly in regards to its user interface. - - Perhaps we should talk on the phone? This typing is quite hard for me still. What hours - are you at work? My hours are approx. 2pm - 2am Pacific time (GMT - 7 hours currently). - - ben - - - From: - Ben Wing - 7/21/1999 2:44 AM - - Subject: - Re: Tabs 'n widgets screenshot - To: - Andy Piper - CC: - xemacs-beta@xemacs.org, wmperry@aventail.com - - - - - This is real cool, but looking at this, it's clear that it doesn't look the - way tab widgets are supposed to work. In particular, of course, they should - have the proper borders around the stuff displayed. I've attached a screen - shot of a typical Windows dialog box with a tab widget in it. The problem - lies with this "expanded gutter" concept. Tabs are *NOT* extra graphical junk - placed in the gutters of a buffer but are GUI objects with *children* inside - of them. This is the right way to do things, and you would need no extra - gutter functionality at all for this. You just need to implement the concept - of GUI objects containing other GUI objects within them. One such GUI object - needs to be a "Emacs-text" GUI object, which is an Emacs window and contains a - buffer within it. At this level, you need not be concerned with the - complexities of geometry layout. The only change that needs to be made in the - overall strategy of frames, windows, etc. is that windows need not be exactly - contiguous and tiled, as long as they are contained within a frame. Or more - specifically: Given that you could always split a window contained inside a - GUI object, we just need to expand things so that each frame has *multiple* - hierarchies of windows in it, rather than just one. A hierarchy of windows - can nest inside of another window -- e.g. I put a tab widget or a text widget - inside of a buffer. This should be easy to implement -- just change things so - there are multiple hierarchies of windows where there are one, each (except - the top-level one) being rooted inside some other window. - - Anyone willing to implement this? Andy? - - - From: - Ben Wing - 6/30/1999 3:30 PM - - Subject: - Re: Focus Help! - To: - Andy Piper - CC: - Ben Wing , martin@xemacs.org, andyp@beasys.com - - - - - It sounds like you're doing very good work. It also sounds like the approach - you have followed is the correct one. Now, it seems like there isn't really - that much work left to get dialog boxes working. What you really just need to - do is implement container widgets, that is to say, subwindows that can contain - other subwindows. For example, the tab widget works this way. (It sounds like - you have already implemented tab widgets, so I don't quite see how you've done - this without the concept of container widgets.) So you might just try adding a - framework for container widgets and then implementing very simple container - widgets. The basic container widgets are: - - 1. A vertical-layout widget, which draws nothing itself and lays out its - children one above the next. - 2. A horizontal-layout widget, which draws nothing itself and lays out its - children side-to-side. - 3. A box (or "grouping") widget, which draws a rectangle around its single child - and optionally draws some text on the top or bottom line of the rectangle. - 4. A tab widget, which displays a series of tabs horizontally at the top of its - area, and then below it places one of its children, - corresponding to the selected tab. - 5. A user widget, which draws nothing itself and does no layout at all on its - children, except that it has a "layout callback" - property, a Lisp function, so that the programmer can control the layout. - - The framework is as follows: - - 1. Every widget has at least the following properties: - a) a size, whose value can be "unspecified", which might be implemented - using the value -1. The default value should be "unspecified". - b) whether it's mapped, i.e. whether it will be displayed. (Some container - widgets, such as the tab widget, set the mapped - property themselves on their children. Others, such as the vertical and - horizontal layout widgets, don't change this property but pay attention to it, - and ignore completely all children marked as unmapped.) The default value should - be "true". - c) whether its size can be changed by another widget's layout routine. The - default value should be "true". - d) a layout procedure, which (potentially at least) determines the size of - the widget as well as the position, size and mappedness of its child widgets. - The layout procedure is inherent in the widget and is not an external property - of the widget (except in the case of the "user widget"): it is instead more like - the redisplay callback that each widget has. - 2. Every container widget contains a property which is a list of child widgets. - 3. Every child widget contains the following properties: - a) a position indicating where the child is located relative to the top - left corner of its parent. The position's value can be "unspecified", which - might be implemented using the value -1. The default value should be - "unspecified". - b) whether its position can be changed by another widget's layout routine. - The default value should be "true". - 4. All of the properties just listed (except possibly the layout procedure) can - be modified directly by the programmer, and there are no proscriptions against - doing so. However, if the programmer wants to resize, reposition, map or unmap - a widget in such a way that the layout of all the other widgets in the tree - changes appropriately, he should use a special function to change the property, - as described below. - - The redisplay mechanism pays attention to the position, size, and mappedness - properties and to the hierarchy of widgets, mapping, resizing and repositioning - the corresponding subwindows (the "real representation" of the widgets) as - necessary. It also pays attention to the hierarchy of the widgets, making sure - that container subwindows get drawn before their child subwindows. When it - encounters widgets with an unspecified size, it should not draw them, and should - issue a warning. When it encounters widgets with an unspecified position, it - should draw them at position (0, 0) and should issue a warning. - - The above framework should be fairly simple to implement and is basically - universal across all high-level windowing system toolkits. The stickyness comes - with what procedures you follow for getting the layout done. - - Andy, I understand that implementing this may seem like a daunting task. - Therefore, I propose that at first you implement the above framework but don't - implement any of the layout procedures, or any of the functions that call them: - Just make them stubs that do nothing. This way, the Lisp programmer can still - create any dialog boxes he wants, he just has to set the sizes and positions of - all the widgets explicitly, and then recompute them whenever the widget tree is - resized (once you get around to allowing this). I have a lot more to write - about exactly how the layout procedures work, but I'll send that to you later - once you're ready. - - You should also think about making a way to have widget trees as top-level - windows rather than just glyphs in a buffer. There's already the concept of - "popup" frames. You could provide an easy way to create a popup frame with no - menu, toolbars, scrollbars, modeline or minibuffer, and put a single glyph in - the displayed buffer that takes up the whole Emacs window. - - Ben - - - - - March 20, 2000 - - You wrote to me awhile ago about this and asked about documentation, and I - dictated a response but never got it sent, so here it is: - - I don't think there's any more documentation on how things work under Xt but it - should be clear. The EmacsFrame widget is the widget corresponding to the X - window that Emacs draws into and there is a handler for expose events called - from Xt which arranges for the invalidated areas to get redrawn. I think this - used to happen as part of the handler itself but now it is delayed until the - next call to redisplay. - - However, one thing that you absolutely must not do is remove the Xt support. - This would be an incredibly unfriendly thing to do as it would prevent people - from using any widget set other than Qt or GTK. Keep in mind that people run - XEmacs on all sorts of different versions of X in Unix, and Xt is the standard - and the only toolkit that probably exists on all of these systems. - - Pardon me if I've misunderstood your intentions w.r.t. this. - - As for how you would implement GTK support, it will not be very hard to convert - redisplay to draw into a GTK window instead of an Xt window. In fact redisplay - basically doesn't know about Xt at all, except in the portion that handles - updating menubars and scrollbars and stuff that's directly related to Xt. - - What you'd probably want to do is create a new set of event routines to replace - the ones in event-Xt.c. On the display side you could conceivably create a new - device type but you probably wouldn't want to do that because it would be an - externally visible change at the Lisp level. You might simply want to put a - flag on each frame indicating what sort of toolkit the frame was created under - and put conditions in the redisplay code and the code to update toolbars and - menubars and so forth to test this flag and do the appropriate thing. - - - April 12, 2000 - - This is way cool, buuuuutttttttt ............. - - what we *really* need is the GUI interface on top of it. I've taken a shot at - it with generic-print-buffer - (print-buffer is taken by lpr, which is such a total mess that it needs to be - trashed; or at least, the generic - stuff in this package needs to be taken out and properly genericized). For - the moment, generic-print-buffer - just does something like what Kirill's been posting if we're running windows, - and uses lpr otherwards. However, what we absofuckinglutely need is a Lisp - interface onto `EnumPrinters()' so that we can get the - list of printers and have a nice menu listing the available printers, and you - can check the one you want. People in the Windows world don't normally even - know the names of their local printers! - - Kirill, given what I've done in `simple.el' and `menubar-items.el', do you think - you could add the `EnumPrinters()' - support and fix up the GUI? If you don't feel comfortable with the GUI, at - least do the `EnumPrinters()'. - - But ... Kirill, I tried your formula for printing and nothing happened. - Perhaps I didn't call redisplay-frame or something? You need to fix this up - and make it work for multi-page documents. (Again, this is in - generic-print-buffer.) Nothing special, it just needs to fucking work! There - are zillions and zillions of postings every day on xemacs-nt about how to get - printing working, and none seem to refer to the built-in support. - - ben - - - April 19, 2000 - - Kirill 'Big K' Katsnelson wrote: - - > Some time ago, Ben Wing wrote... - > >kirill, the interface i created is more general, like this: - > - > [snip] - > - > >Unfortunately I haven't implemented much of this; just some of the file - > >dialog box. but i think - > >this is better than creating new mswindows-specific primitives. if you - > >are interested in working on - > >this, i'll send you the code i have. - > - > Sure. Can you just commit it for my starting point? - > - > >also, the dialogs shouldn't have anything directly to do with the printer - > >device. all they should - > >do is return a set of values. it's the caller's responsibility to - > >interpret them and set device - > >properties accordingly. this way, there's a complete separation between - > >the underlying - > >functionality and the gui. - > - > Unfortunately. I thought about doing it this way, but we then lose a lot of - > printer-specific setup in this case. The DEVMODE structure contains two - > parts: printer independent, as defined by SDK typedef DEVMODE, and - > some trailing bytes, of unknown structure, used by a driver. The driver - > only returns the extra length it wants. Such options as PCL ReT resolution - > enhancement options or PostScript negative output are not available - > through the standard part of the devmode structure, and stored in the - > driver part (printer dialogs are driver-specific). - > - > So we have total of three options: - > - Not to implement options beyond standard DEVMODE - > - Make DEVMODE a Lisp object. - > - Hide DEVMODE inside the device object. - > - > First case looks cheesy. Letting DEVMODE fall off the printer is no good - > either, since one needs both the device and the devmode to edit the - > devmode, and they must match. I am still convinced that the devmode and - > the printer should not be separated. - - hmm, i see ... this completely breaks abstraction though. it fails in various - scenarios, e.g. a program wants to initialize the dialog box with certain - non-driver-specific properties, without caring about the particular printer. - - i think you should create a new print-properties object that encapsulates all - printer properties (which can be changed using get/put), including the printer - name, and contains a DEVMODE in it. if the printer name gets changed, the - DEVMODE might change too, but the print-properties object itself stays the - same. you pass this object as a parameter to the dialog box, and it gets - changed accordingly. you can call something like set-device-print-properties to - stick everything in this structure into the device. (you could imagine a case - where someone wanted to keep multiple print configurations around ...) - - > - > - > Big K - - -- - Ben - -  - File: internals.info, Node: Discussion -- Multilingual Issues, Next: Discussion -- Instantiators and Generic Property Accessors, Prev: Discussion -- Dialog Boxes, Up: Future Work Discussion - - 41.4 Discussion - Multilingual Issues - ===================================== - - - 4/10/2000 4:13 AM - - BTW I am planning on adding some more powerful font-mapping capabilities to - XEmacs (i.e. how do we map particular characters to the proper fonts that can - display them, and how do we map the character's codes to the indices into the - font). These will replace to hackish charset-registry/charset-ccl-program stuff - we currently have, and be [a] much more powerful, [b] designed in a - window-system-independent way, [c] works with specifiers so you can control the - mapping of individual buffers, and [d] works on a character rather than charset - level, to correctly handle Unicode. One possible usage would be to declare that - all latin1 in a particular buffer to be displayed with latin2 fonts; I bet - Hrvoje would really appreciate that - - --------------------------------------------------------------------------- - - April 10, 2000 - - [info from "creation of generic macros for accessing internally formatted data"] - - Hmm, so there I just wrote a detailed design for the macros. I would be - *THRILLED* and overjoyed if you went ahead and implemented this mechanism, or - parts of it. - - I've just finished arranging for a new transcriptionist, and soon I should be - able to send off and get back my dictation of my (a) exposing streams to lisp, - and (b) allowing for proper lisp-created coding systems, which define their - reading, writing, and detecting methods in lisp. - - - BTW How's it going wrt your Unicode and decode-priority stuff? - - And ... you sent me mail asking what it was you had promised me, and listed - only one thing, which was - profiling of vm and certain other operations you found showed tremendous - slowdown with Japanese characters. The other main thing I want from you is - - -- Your priorities, as an actual Japanese user and XEmacs developer, - concerning what MULE work should be done, how it should be done, in what - order, etc. - - I'm sure there's something else, but it's been awhile since I took my sleeping - dose and my brain can barely function anymore. Just let me know how you're - going to proceed with the above macro changes. - - BTW there's some nice Perl scripts written by Martin and fixed by me to make - global-search-and-replace - much, much easier. I've attached them. The first one is a shell script that - works like - - gr foo bar *.[ch] - - and replaces foo with bar in all of the files. For each modified file, a - backup is created in the backup/ directory, which is created as necessary. - This shell script is a fairly trivial front end onto global-replace2, which is - a perl script that takes one argument (a Perl expression such as s/foo/bar/g) - and a list of files obtained by reading the stdin, and does the same global - replacement. This means that the regexp syntax used here has to be perl-style - rather than standard emacs/grep style. - - ben - - --------------------------------------------------------------------- - - - From: - Ben Wing - 12/23/1999 3:34 AM - - Subject: - Re: check process state before accessing coding_stream (fix PR#1061) - To: - "Stephen J. Turnbull" - CC: - XEmacs Developers - - - - - Thankfully, nearly all of this horridity you bring up is irrelevant. In - XEmacs, "gettext" does not refer to any standard API, but is merely a stand-in - for a translation routine (presumably written by us). We may as well call it - something else. We define our own concept of "current language". We also - allow for a function that needs a different version for each language, which - handles all cases where simple translation isn't sufficient, e.g. when you - have to pluralize some noun given to you or insert the correct form of the - definite article. No weird hacks needed. No interaction problems with other - pieces of software. - - What I wrote "awhile ago" is (unfortunately) not anywhere public currently, - but it's on my list to put it on the web site. "There you go again" is - usually not true; most of what I quote was indeed put out publicly at some - point, but I'll try to be more explicit about this in the future. - - ben - - "Stephen J. Turnbull" wrote: - - > >>>>> "Ben" == Ben Wing writes: - > - > Ben> "Stephen J. Turnbull" wrote: - > - > >> What I have in mind is not just gettext-izing everything in the - > >> XEmacs core sources. I currently believe that to be - > >> unacceptable - > - > Ben> I don't quite understand. Could you elaborate and give some - > Ben> examples? - > - > Examples? Hmm. - > - > First, there's the surface of Jan's y-or-n-p example. You have to - > coordinate the translation of the message string and the response - > prompt. This is handled by y-or-n-p itself (I see that we already do - > have gettext for Emacs Lisp, that's nice to know). - > - > Except that it's not really handled by y-or-n-p. There's no reason to - > suppose that somebody writing a Lisp package would necessarily use the - > XEmacs domain (in fact, due to the way gettext binds text domains---if - > I understand that correctly---we don't want that to be the case, - > because it means that every time a Lisp package is updated the whole - > XEmacs catalog must also be updated). So which domain gets used for - > the message string? - > - > In the current implementation, it is the domain of y-or-n-p. So - > packages with their own domain won't get y-or-n-p prompts correctly - > translated. But that means that the package should do its own - > translation. But now you're applying gettext to the same string - > twice; you just have to pray the that translator upstream doesn't - > collide with an English string that's in the XEmacs domain. (The - > gettext docs mention the similar problem of English words with - > multiple meanings that must map to different words in the target - > language; this can be disambiguated by various trickeries in forming - > the strings ... but only if you "own" them, which in the multi-domain, - > interated gettext example you do not.) AFAICT this means that you - > must never pass untranslated strings across public APIs, but this may - > or may not be reasonable, and certainly is inconvenient. - > - > Next, we have to translate the possible answer strings to match the - > language being passed by the user. This is presumably OK here, - > because it's done by y-or-n-p. But what if y-or-n-p returned a string - > rather than a boolean? Then we would need to coordinate the - > presentation of the prompt (done by y-or-n-p) and the translation of - > the possible answer strings (done by the caller). This can in fact be - > done using dgettext with the XEmacs domain, but you must know that - > y-or-n-p is in the XEmacs domain. This is not necessarily going to be - > obvious, and it might very well be that sets of related packages might - > have the same domain, so you wouldn't necessarily know which domain is - > appropriate by looking at the requires. - > - > And what happens if one domain does supply translations for a language - > and the other does not? AFAIK, gettext has no way to find out if this - > is the case. But you might very will prefer a global fallback to - > English if substantial phrases are drawn from both domains, while you - > might prefer string-by-string fallback if the main text is translated - > and only a few words are left to fallback to English. - > - > Aside from confusing users, this puts a great burden on programmers. - > Programmers need to know about the status of the domains of packages - > they use as well as the XEmacs domain; they need to program - > defensively against the possibility that some package they use will - > become gettext-ized, or the translation projects will be out of synch - > (some teams will do the calling package first, others will do the - > caller package first). - > - > I don't think anybody will use gettext in these circumstances. At - > least not after they get the first bug report that "XEmacs is stuck in - > an infinite y-or-n-p loop and I can't get out." - > - > Ben> I wrote this awhile ago: - > - > "There you go again." Not anywhere I could see it! (At least, it - > doesn't look familiar and grepping the archives doesn't turn it up.) - > - > OK, you win. Subscribe me to xemacs-review. Or whatever seems - > appropriate. - > - > -- - > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN - > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 - > _________________ _________________ _________________ _________________ - > What are those straight lines for? "XEmacs rules." - - -- - In order to save my hands, I am cutting back on my responses, especially - to XEmacs-related mail. You _will_ get a response, but please be patient. - If you need an immediate response and it is not apparent in your message, - please say so. Thanks for your understanding. - - - - -------------------------------------------------------------------- - - - From: - Ben Wing - 12/21/1999 2:22 AM - - Subject: - Re: check process state before accessing coding_stream (fix PR#1061) - To: - "Stephen J. Turnbull" - CC: - XEmacs Developers - - - - - - "Stephen J. Turnbull" wrote: - - > >>>>> "Ben" == Ben Wing writes: - > - > Ben> Implementing message translation is not that hard. - > - > What I have in mind is not just gettext-izing everything in the XEmacs - > core sources. I currently believe that to be unacceptable (see Jan's - > message for the pitfalls in I18N; it's worse for M17N). I think - > really solving this problem needs a specifier-like fallback mechanism - > (this would solve Jan's example because you could query the - > text-specifier presenting the question for the affirmative and - > negative responses, and the catalog-building mechanism would have - > checks to make sure they were properly set, perhaps a locale - > (language) argument), and gettext is just not sufficient for that. - - I don't quite understand. Could you elaborate and give some examples? - - > - > - > At a minimum, we need to implement gettext for Lisp packages. - > (Currently, gettext is only implemented for C AFAIK.) But this could - > potentially cuase more trouble than it's worth. - > - > Ben> A lot depends on priority: How important do you think this - > Ben> issue is to your average Japanese/Chinese/etc. user? - > - > Which average Japanese (etc) user? The English-skilled (relatively) - > programmer in the free software movement, or my not-at-all-competent - > undergrad students who I would love to have using an Emacs? This is a - > really important ease-of-use issue. - > - > Realistically, for Japanese, it's low priority. The Japanese team in - > the GNU Translation Project is doing very little AFAIK, so even if the - > capability were there, I doubt the message catalog would soon be done. - > - > But I think that many non-English speakers would find it very - > attractive, and for many languages there are well-organized and - > productive translation teams. I suspect that if the I18N facility - > were well-designed, many Western European languages would have full - > catalogs within a year (granted, they are the ones where it's least - > needed :-( ). - > - > Personally, I think doing it well is hard, and of little benefit to - > _current_ core XEmacs constituency. I think doing a good job, with - > catalogs, would be very attractive to many non-English-speaking - > _potential_ users. - > - > Ben> How does it compare to some of the other important Mule - > Ben> issues that Martin and I are (trying to work) on? - > - > I don't know what you guys are _trying_ to work on. Everything in the - > I18N section of "Architecting XEmacs" is red-flagged. OTOH, it's - > clear from your posts that you are overburdened, so I can't read - > priority into the fact that you've responded to specific issues in the - > past. - - I wrote this awhile ago: - - - > - > Ben> The big question is, would you be willing to help do the - > Ben> actual implementation, to "be my hands"? - > - > Sure, subject to the usual caveat that I'd need to be convinced it's - > worth doing and a secondary caveat that I am not an experienced coder. - - If you'll implement it, I'll design it. It's more a case of will on your part - than anything else. I can give you instructions sufficient enough to match - your level of expertise. - - ben - - > - > - > -- - > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN - > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 - > _________________ _________________ _________________ _________________ - > What are those straight lines for? "XEmacs rules." - - -- - In order to save my hands, I am cutting back on my responses, especially - to XEmacs-related mail. You _will_ get a response, but please be patient. - If you need an immediate response and it is not apparent in your message, - please say so. Thanks for your understanding. - - - - ----------------------------------------------------------------------------- - - Dec 20, 1999 - - - Implementing message translation is not that hard. I've already done a lot of - preliminary work in places such as `make-msgfile.lex' in lib-src/. Finishing up - the work is not that big a task; I already know exactly how it should be - done. Perhaps I'll write up detailed design instructions for this, as I'm - doing for other things. A lot depends on priority: How important do you think - this issue is to your average Japanese/Chinese/etc. user? How does it compare - to some of the other important Mule issues that Martin and I are (trying to - work) on? If I did the design document, would you be willing to do the - necessary bit of C hackery to implement the document? If the design document - is not specific enough for you, I can give you an "implementation document" - which will definitely be specific enough: i.e. I'll show you exactly where the - code needs to be modified, and how. The big question is, would you be willing - to help do the actual implementation, to "be my hands"? - - --------------------------------------------------------------------------- - - From: - Ben Wing - 12/14/1999 11:00 PM - - Subject: - Re: Mule UI disaster: displaying character tables - To: - Hrvoje Niksic - CC: - XEmacs vs Mule - - - - - What I mean is, please put my name in the header, as well as xemacs-mule. - That way I'll see it in my personal box. - - I agree that Mule has problems, but: - - Brokenness can be fixed. - Slowness can be fixed. - Limitations can be fixed. - - The design limitation you mention below, for example, is not really very - hard to change. - - Keep in mind that I pretty much rewrote Mule from scratch, and did it - *all* in 6-7 months. In comparison with that, the changes below are - pretty minor, and each could be done by a good (and able-bodied!) - programmer familiar with the Mule code in less than a week -- to the - XEmacs code, at least. The problem is, everyone who could do this work is - instead spending their time complaining about Mule problems instead of - doing things. - - I'll gladly help out anyone who wants to do Mule coding by explaining all - the details; I'll even write a "Mule internals manual", if that will - help. I can also make international phone calls -- they're cheap here in - the US due to the long distance wars. But so far no one has asked me for - help or shown any willingness to do any work on Mule. - - Perhaps people are daunted by the seeming vastness of the problems. But I - wager that if I had another 6 months to work on nothing but Mule, it would - be nearly perfect. The basic design of the XEmacs C code is good; - incremental changes, without over-much concern for compatibility, could - make huge strides in a short amount of time (as was the case the whole - time I worked on it, esp. towards the end -- it didn't even *compile* for - 4 months!). A "total rewrite" would be an incredible waste of time. - - Again, I'm completely willing to provide help, documentation, design - improvement suggestions (ala Architecting XEmacs -- which seems to have - been completely ignored, alas), etc. - - ben - - Hrvoje Niksic wrote: - - > Ben Wing writes: - > - > > I'm the one who did most of the Mule work in XEmacs, so if you have - > > any questions about the core, please address them to me directly. I - > > can probably give you a very clear and detailed answer. - > - > Thanks. I think it still makes sense to ask here, so that other - > developer have a chance to chime in. - > - > > However, I need some explanation. What's misdesigned that you're - > > complaining about? And what's the coding-system disaster? - > - > It's been spoken of a lot. Basically: - > - > * Unlike XEmacs/no-Mule, XEmacs/Mule doesn't preserve binary files in - > Latin 2 locales by default. This is annoying for users who are used - > to XEmacs/no-Mule. - > - > * XEmacs/Mule is much slower than XEmacs, and not only because of - > character/byte conversions. It seems that font lookups etc. are - > slower. - > - > * The "coding-system disaster" refers to inherent limitations of the - > coding-system model. If I understand things correctly, - > coding-systems convert streams of bytes to streams of Emchars. It - > does not appear to be possible to create a "gzip" coding system for - > handling gzipped file. Even EOL conversions look kludgish: - > - > iso-2022-8 - > iso-2022-8-dos - > iso-2022-8-mac - > iso-2022-8-unix - > iso-2022-8bit-ss2 - > iso-2022-8bit-ss2-dos - > iso-2022-8bit-ss2-mac - > iso-2022-8bit-ss2-unix - > iso-2022-int-1 - > iso-2022-int-1-dos - > iso-2022-int-1-mac - > iso-2022-int-1-unix - > - > Ideally, it should be possible to specify a stream of - > coding-systems, where only the last one converts to actual Emchars. - > - > There are more problems I don't remember right now. Many many usage - > problems become apparent when I stand and look over the shoulders of - > an XEmacs users who tries to use Mule. - - -- - In order to save my hands, I am cutting back on my responses, especially - to XEmacs-related mail. You _will_ get a response, but please be patient. - - If you need an immediate response and it is not apparent in your message, - please say so. Thanks for your understanding. - - - - ----------------------------------------------------------------------- - - - - - From: - Ben Wing - 12/14/1999 12:20 AM - - Subject: - Re: Mule UI disaster: displaying character tables - To: - "Stephen J. Turnbull" - CC: - XEmacs vs Mule - - - - - I think you should go ahead with your proposal, and assume it will get - implemented. I don't think Martin is really suggesting that API changes not - be allowed, but just that they proceed in a somewhat orderly fashion; and in - any case, I imagine I have final say in cases of Mule-related conflicts. - - ben - - "Stephen J. Turnbull" wrote: - - > >>>>> "Hrvoje" == Hrvoje Niksic writes: - > - > Hrvoje> So next I tried the "Mule" menu. That's right, boys and - > Hrvoje> girls, I've never looked at it before. - > - > For quite a while, it didn't work at all, led to crashes and other - > warm/fuzzy things. IIRC there used to be a top level menu item - > pointing to information about the current language environment but it - > got removed. - > - > Hrvoje> Wow. Seeing shift_jis, iso-2022 variants and (above all - > Hrvoje> things) big5 makes me really warm and fuzzy. - > - > We've been through this recently---you were there. We know what to do - > about it, basically (Ben liked my proposal, and it would fix this - > silliness as well as the binary file breakage). But given that Ben - > and Martin seem to have different ideas about where to go with Mule - > (Ben seemed to be supporting API and implementation revisions, Martin - > evidently wants to keep the current Mule), working on that proposal is - > possibly a waste of time. I've got other stuff on my plate and I'll - > get back to it one of these days (not tomorrow but sooner than Real - > Soon Now). - > - > Hrvoje> The items it presents (leading to further submenus) are: - > - > Hrvoje> 94 character set - > Hrvoje> 94 x 94 character set - > Hrvoje> 96 character set - > - > This _is_ bad UI, now that you point it out. But it is quite natural - > for a coding system lawyer (as all Japanese users have to be), I never - > noticed it before. Easy enough to fix ("raise my karma"). - > - > Hrvoje> But I do bear some Mule scars, so I happily select "96 - > Hrvoje> character sets", then ISO8859-2. And I get this: - > - > [Table omitted] - > - > Hrvoje> So me wonders: what the hell is this? - > - > Huh? That is the standard table that you see over and over again in - > references. I'll believe you if you say you've never seen one before, - > but every Japanese users' manual has dozens of pages of those, using - > exactly that format. - > - > The presentation in the range 00--7F is not unreasonable for Latin 2; - > ISO-8859 is a version of ISO-2022, so the high bit should not be - > interpreted as "+ x80" (technically speaking), it should be - > interpreted as a character set shift. - > - > Of course, this doesn't make sense to anybody but a character set - > lawyer, and so should be changed. Especially since the header refers - > to ISO-8859-2 which everybody these days thinks of as _one, 8-bit_ - > character set, not two 7-bit ones. - > - > As for the "Japanese" in the table, that's just a really stupid - > "optimization": those happen to be line-drawing characters available - > in JIS X 0208, to make pretty borders. Substitute "-", "+", and "|" - > in appropriate places to make ugly but portable borders. - > - > Hrvoje> Mule is just broken. Warn your friends. - > - > Hrvoje is on the rampage again. Warn your friends ;-) - > - > -- - > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN - > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 - > _________________ _________________ _________________ _________________ - > What are those straight lines for? "XEmacs rules." - - -- - In order to save my hands, I am cutting back on my responses, especially - to XEmacs-related mail. You _will_ get a response, but please be patient. - If you need an immediate response and it is not apparent in your message, - please say so. Thanks for your understanding. - - - - --------------------------------------------------------------------------- - - From: - Ben Wing - 12/14/1999 10:28 PM - - Subject: - Re: Autodetect proposal; specifer questions/suggestions - To: - "Stephen J. Turnbull" - - - - - I've always thought the specifier API is too complicated (and too - "write-only"), but I went back at one point well after I designed it and I - couldn't figure out an obvious way to simplify it that still kept reasonable - functionality. Perhaps that's what Custom did, and why it turned out bad. - - Inefficiency is a stupid reason not to use them. They seem efficient enough - for redisplay. Changing them might be inefficient, but Emacs Lisp is in - general, right? - - Can you propose an API or functionality change that will make them more used? - - - - "Stephen J. Turnbull" wrote: - - > >>>>> "Ben" == Ben Wing writes: - > - > Ben> I think you should go ahead with your proposal, and assume it - > Ben> will get implemented. - > - > OK. "yas baas" ;-) - > - > On something totally different. I'm really bothered by the fact that - > specifiers are so little used (eg, Custom reimplements them badly), - > and the fact that every package seems to define its own set of faces - > (or whatever), rather than use the specifier mechanism to inherit from - > existing ones, or add new specifications to existing ones. API problem? - > - > Also, faces (maybe specifiers in general?) should have an autoload - > mechanism, and a `-faces.el' (or `-specifiers.el') - > convention. There are a number of faces in (eg) Custom that I like to - > use, but I have to load Custom to get them. And Custom should be able - > to somehow see all the faces in various packages available, even when - > they are not loaded. - > - > I've seen claims that specifiers aren't very efficient. - > - > Opinions? - > - > -- - > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN - > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 - > _________________ _________________ _________________ _________________ - > What are those straight lines for? "XEmacs rules." - - -- - In order to save my hands, I am cutting back on my responses, especially - to XEmacs-related mail. You _will_ get a response, but please be patient. - If you need an immediate response and it is not apparent in your message, - please say so. Thanks for your understanding. - - - ----------------------------------------------------------------------------- - From: - Ben Wing - 11/18/1999 9:02 PM - - Subject: - Re: Char-related crashes (hopefully) fixed - To: - "Stephen J. Turnbull" - CC: - XEmacs Beta List - - - - - OK, in summation: - - 1. C-q is a user-level function and should do whatever makes the most sense. - 2. int-char is a low-level primitive and should never depend on high-level - settings like language environment. - 3. Everything you can do with int-char can and should be done with make-char - -- representation-independent, much less likelihood of bugs, etc. Therefore - int-char should be removed. - 4. Note that CLTL2 also removes int-char. - 5. Your statement - - > In one-byte buffers (either Olivier's 1/2/4 extension or `xemacs -font - > *-iso8859-2') it implicitly will have dependence whatever you say. - - is confusing internal and external representations. - - ben - - "Stephen J. Turnbull" wrote: - - > Can somebody give a bunch of examples where using integers as - > characters is useful? For that matter, where they are actually used? - > Ben said "backward compatibility," but I haven't seen this used, and I - > don't really know how to grep for it. I have grepped for int-char, - > int-to-char, char-int, and char-to-int and they're pretty rare in the - > core and package code (2/3 of it) that I have. - > - > The only one that I ever use is the C-q hack for inserting characters - > by code value at the keyboard, and that could arguably (and in - > Japanese invariably is) delegated to an input method which would know - > about language environment (and return a true character). - > - > For iterating over a character set in "natural" order, only ASCII - > satisfies the requirement of having one, and even that's shaky. AFAIK - > the Swedes and the Norwegians, or is it the Danes, disagree on - > ordering the _letters_ in ISO-8859-1 character set. This really - > should be table-driven, and will have to be for everything except - > ASCII and ISO-8859-1 if we go to a Unicode internal representation. - > - > We already have primitives for efficient case conversion and the like. - > - > The only example I can think of offhand where you would really really - > want the facility is to iterate over a code space where you don't know - > which points are legal characters. Eg, to print out tables of fonts. - > Pretty specialized. And this can be done through make-char, anyway. - > - > According to CLtL1, the main portable use for char-int is for hashing. - > But that doesn't square with the kind of usage we've been talking - > about (in loops and the like). - > - > What else am I missing? - > - > Ben's desiderata have some problems. - > - > >>>>> "Ben" == Ben Wing writes: - > - > Ben> Either int-char should be the mirror opposite of char-int - > Ben> (i.e. accept all legal char integers), or it should be - > Ben> removed entirely. - > - > OK. I agree with this. - > - > Ben> int-char should *never* have any dependence on the language - > Ben> environment. - > - > In one-byte buffers (either Olivier's 1/2/4 extension or `xemacs -font - > *-iso8859-2') it implicitly will have dependence whatever you say. - > Even without Mule, people can always use external encoders to change - > raw ISO-8859-2 to ISO-2022 (not that anybody sane ever would, OK, - > Hrvoje?). Then the two files will be interpreted differently in a - > Latin-1 locale Mule; the ISO-8859-2 file will be recognized as - > ISO-8859-1, and the ISO-2022 file will be internally interpreted as - > ISO-8859-2. - > - > The point is that people normally assume that int-char should accept - > their "natural" integer to character map. For Americans, that's - > ASCII, for Germans, that's ISO-8859-1, for Croatians, that's - > ISO-8859-2. And it works "correctly" in a no-mule XEmacs with `-font - > *-iso8859-2'! Japanese usually use ku-ten or JIS, and there's a - > "natural" map from byte-sized integer pairs to shorts, but it's full - > of holes. So language environments don't agree on what a legal char - > integer is, and where they do (eg, ISO-8859-1 and ISO-8859-2), they - > don't agree on the map. To satisfy your dictum (with which I agree, - > but I take to mean we should get rid of these functions) we can take - > the intersection where they agree - > - > ==> legal char integers == ASCII - > - > which is what I prefer, or pick something arbitrary and efficient - > - > ==> char-int returns the internal representation - > - > which I really hate, or something else. Suggestions? - > - > Ben> I don't think C-q should either. If Hrvoje wants to insert - > Ben> Latin-2 characters by number, then make C-u C-q work so that - > Ben> it also prompts for a character set, with a default chosen - > Ben> from the language environment. - > - > And restrict this to ASCII? Or assume Latin-1 in GR if there is no - > prefix argument? - > - > This is a useful feature. C-q currently inserts Latin-2 characters - > for Hrvoje in no-mule XEmacs (stretching the point only a little); I - > think it should continue to do so in Mule. This really is an input - > method issue, not a keyboard issue. In XEmacs, inserting an integer - > into a buffer has no meaning. Users insert characters. So this is a - > completely different issue from the programming API, and should not be - > considered analogous. - > - > Maybe we could have C-q insert according to the Unicode standard, and - > treat C-u C-q as part of the input method. But I think most users - > would prefer to have C-q insert according to their locale-standard - > tables, and select Unicode explicitly using the C-u C-q idiom. In - > fact (again this points to the input method idea), Japanese users - > would probably like to have the alternatives of using kuten (pairs - > from 1--94 x 1--94) or JIS (pairs from 0x21--0x7E x 0x21--0x7E) as - > options since both indexing systems are common in tables. - > - > -- - > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN - > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 - > __________________________________________________________________________ - > __________________________________________________________________________ - > What are those two straight lines for? "Free software rules." - - -- - ben - - -- - In order to save my hands, I am cutting back on my responses, especially to - XEmacs-related mail. You - _will_ get a response, but please be patient. If you need an immediate - response and it’s not apparent in - your message, please say so. Thanks for your understanding. - - - - ----------------------------------------------------------------------------- - - From: - Ben Wing - 11/16/1999 11:03 PM - - Subject: - Re: Char-related crashes (hopefully) fixed - To: - Yoshiki Hayashi - CC: - Hrvoje Niksic , - XEmacs Beta List - - - - - Either int-char should be the mirror opposite of char-int (i.e. accept all - legal char integers), or it should be removed entirely. - - int-char should *never* have any dependence on the language environment. - - I don't think C-q should either. If Hrvoje wants to insert Latin-2 - characters by number, then make C-u C-q work so that it also prompts for a - character set, with a default chosen from the language environment. - - ben - - Yoshiki Hayashi wrote: - - > Hrvoje Niksic writes: - > - > > As Ben said, now that we've fixed the actual bugs, we can think about - > > changing the behaviour for int-char conversions for 21.2. - > - > Following are proposed which integers should be accepted - > where characters are expected: - > - > 1) Don't allow anything - > 2) Accept 0-127 - > 3) Accept 0-256 - > 4) Accept everything - > - > Other things proposed are: - > - > a) When doing C-q, treat 128-256 as Latin-2 in Latin 2 - > language environment. - > - > So far, most of the proposal is intended to apply to every - > int-char conversions, I'd like to make some functions to - > accept. - > - > My plan is: - > Accept only 0-256 in every place except int-to-char. - > int-to-char accepts every valid integers. - > Make new function which does int-to-char conversion - > correctly according to the language environment. - > - > This way, most of the code which does (insert (1+ ?a)) or - > something continues working. Now internal representation is - > changed a little bit, so disabling > 256 characters will - > warn those who are dealing with internal representation - > directly, which is bad. Still, you can do - > (let ((i 1442)) - > (while (i < 2000) - > (insert (int-to-char i)) - > (setq i (+1 i)))) - > to achieve old behaviour. - > - > For C-q, I'm not for changing it's original definition, - > since it might confuse people who are expecting Latin-1 in - > other language environment and typing just 1 integer doesn't - > make sense for multibyte world. It's cleaner to make new - > function, which does make-char according to the charset of - > language-info-alist so that people who use that often can - > bind it to C-q or some other keys. - > - > -- - > Yoshiki Hayashi - - -- - ben - - -- - In order to save my hands, I am cutting back on my responses, especially to - XEmacs-related mail. You - _will_ get a response, but please be patient. If you need an immediate - response and it’s not apparent in - your message, please say so. Thanks for your understanding. --- 6214,6217 ---- diff -c 'xemacs-21.5.25/info/internals.info-5' 'xemacs-21.5.26/info/internals.info-5' Index: ./info/internals.info-5 *** ./info/internals.info-5 Sun Feb 26 22:31:24 2006 --- ./info/internals.info-5 Sat Apr 1 04:05:23 2006 *************** *** 46,51 **** --- 46,2265 ---- Foundation instead of in the original English.  + File: internals.info, Node: Better Rendering Support -- Current Status, Next: Better Rendering Support -- Configuration with the Interim Patches, Prev: Better Rendering Support -- Implementation, Up: Future Work -- Better Rendering Support + + 40.24.3 Better Rendering Support - Current Status + ------------------------------------------------- + + Stephen has a branch containing his stuff in XEmacs CVS. The branch + point tag is `sjt-xft-bp', roughly corresponding to XEmacs 21.5.18, and + branch tag is `sjt-xft'. + + 40.24.3.1 Bugs Reported in sjt-xft + .................................. + + `ChangeLogs' + A lot of these, especially for Eric and Matthias's work, are + missing. Mea culpa. + + `Options->Font' + `Options->Font Size' + These menus don't work. All fonts are greyed out. All sizes are + available, but many (most?) faces don't change size, in particular, + `default' does not. + + `Antialiased text bleeding outside of reported extent' + On my PowerBook G4 Titanium 15" screen, X.org server v6.8.1, + dimensions: 1280x833 pixels (433x282 millimeters), + resolution: 75x75 dots per inch, depth of root window: 24 + planes (yes, those dimensions are broken), with font "Bitstream + Vera Sans Mono-16:dpi=75" antialiased text may bleed out of the + extent reported by XftTextExtents and other such facilities. This + is most obvious with the underscore character in that font. The + bottom of the underscore is antialiased, and insertions or + deletions in the same line before the underscore leave a series of + "phantom" underlines. Except that it doesn't happen on the very + first such insertion or deletion after a window refresh. A + similar effect sometimes occurs with deletions at the end of the + line (no, I can't define "sometimes"). See also comments in + `redisplay-x.c', functions `x_output_string' and + `x_output_display_block'. (Mostly duplicated here.) + + I think this is probably an Xft bug, but I'm not sure. + +  + File: internals.info, Node: Better Rendering Support -- Configuration with the Interim Patches, Next: Better Rendering Support -- Modern Font Support, Prev: Better Rendering Support -- Current Status, Up: Future Work -- Better Rendering Support + + 40.24.4 Better Rendering Support - Configuration with the Interim Patches + ------------------------------------------------------------------------- + + For Stephen's `sjt-xft' branch, you should keep the following in mind + when configuring: + + * Although the menus don't work, it is possible to specify fonts for + _faces_ using `set-face-font' (and other specifier-changing + functions). + + There currently is no explicit way to specify that a particular + font be used only for a given language. However, since many fonts + support only a limited repertoire such as ISO 8859/1, you can use + the precedence of specifications for a given specifier locale to + get something of this effect for non-Latin character sets. This + will normally work rather poorly for multiple Latin character + sets, however, because the repertoires tend to have large amounts + of overlap. Support for specifying font by _language_ as well as + by character set is planned. + + Because fonts supporting other languages tend to support English as + well, if you want to use one font for English and another for the + other language, you must use the `append' method when adding font + specifications for the _other_ language. + + However, this leaves you with a problem if you want to change the + other language's font: you have to remove the existing + specification so it won't shadow the new one when you append. + + I use `define-specifier-tag' like this: + + (define-specifier-tag 'lang-ja) + ;; No, I don't try to do real work with this font! But it makes it + ;; obvious that I got the requested font. :-) + (set-face-font 'default "AirCut-14") + (set-face-font 'default "Kochi Mincho-14" nil '(lang-ja) 'append) + ;; Oops, too sober. Try something to match AirCut. + (set-face-font 'default "Mikachan-14" + nil '(lang-ja) 'remove-tag-set-append) + + * The only way to configure widget fonts at the present time is to + use X resources (or hack the source and rebuild). Currently + supported widgets are + * menubars + + * tab controls + + Here are the resources I use. *Warning:* _This interface will + change._ The tab control and menubar have separate Font and + XftFont resources, and use the X resource manager to instantiate a + FontStruct from the Font resource. There is no converter facility + for XftFont yet, and creating one that handles both FontStruct and + XftFont depending on XEmacs's configuration and the font name + seems error-prone at best. Probably we will should to a simple + string representation for this resource, and convert to a face in + XEmacs rather than a font in Xt/Xft. + XEmacs*Tabs.xftFont: Bitstream Vera Sans-16 + XEmacs*menubar*xftFont: Bitstream Vera Sans-16 + XEmacs.modeline.attributeFont: Bitstream Charter-16 + XEmacs.default.attributeFont: Bitstream Vera Sans Mono-16 + I highly recommend use of a proportional font in the modeline + because it allows a lot more text to fit there. (Previously the + font sizes were quite varied, and there was a comment that this + weirdness gave good balance. This isn't true on my main platform, + Mac OS X, and needs to be rechecked on Linux, where it was + observed.) + +  + File: internals.info, Node: Better Rendering Support -- Modern Font Support, Prev: Better Rendering Support -- Configuration with the Interim Patches, Up: Future Work -- Better Rendering Support + + 40.24.5 Better Rendering Support - Modern Font Support + ------------------------------------------------------ + + *NB: This subtree eventually needs to be moved to the Lispref.* + + This chapter describes integration of the `Xft' font support library + into XEmacs. This library is a layer over the separate `FreeType' + rendering engine and `fontconfig' font query and selection libraries. + `FreeType' provides rendering facilities for modern, good-looking + TrueType fonts with hinting and antialiasing, while `fontconfig' + provides a coherent interface to font query and selection which is + independent of the rendering engine, although currently it is only used + in `Xft' to interface to `FreeType'. + + From the user's point of view, `fontconfig' provides a naming + convention which is _precise_, _accurate_, and _convenient_. Precision + means that all properties available in the programming API can be + individually specified. Accuracy means that the truename of the font + is exactly the list of all properties specified by the font. Thus, the + anomolies that occur with XLFDs on many servers (including modern Linux + distributions with XFree86 or X.org servers) cannot occur. Convenience + is subjective, of course. However, `fontconfig' provides a + configuration system which (1) explicitly specifies the defaults and + substitutions that will be made in processing user queries, and (2) + allows the user to specify search configuration, abbreviations, + substitutions, and defaults that override the system's, in the same + format as used by system files. Further, a "standard minimal + configuration" is defined that ensures that at least _serif_, + _sans-serif_, and _monospace_ fonts are available on all `fontconfig' + systems. + + * Menu: + + * Modern Font Support -- Font Concepts:: GUI devices, fonts, glyphs, rendering. + * Modern Font Support -- fontconfig:: Querying and selecting fonts. + * Modern Font Support -- Xft:: Rendering fonts on X11. + +  + File: internals.info, Node: Modern Font Support -- Font Concepts, Next: Modern Font Support -- fontconfig, Up: Better Rendering Support -- Modern Font Support + + 40.24.5.1 Modern Font Support - Font Concepts + ............................................. + + In modern systems, displays are invariably "raster graphic devices", + which present an abstract interface of "pixel array" where each "pixel + value" is a color, and each pixel is individually mutable, and + (usually) readable. In XEmacs, such devices are collectively called + "GUI devices", as opposed to "TTY devices" which are character stream + devices but may support control sequences for setting the color of + individual characters, and the insertion position in a rectangular + array. Here we are concerned only with control of GUI devices but use + TTY devices as a standard for comparison. + + A "font" is an indexed collection of "glyphs", which are + specifications of character shapes. On a TTY device, these shapes are + entirely abstract, and the index is the identity function. Typically + fonts are embedded in TTY devices, the user has no control over the font + from within the application, and where choice is available, there is + limited selection, and no extensibility. Simple, functional, and ... + ugly. + + On GUI devices, the situation is different in every respect. Glyphs + may be provided by the device, the application, or the user. Additional + glyphs may be added at will at any of those levels. Arbitrary index + functions allow the same glyph to be used to display characters in + different languages or using application-specific codes. Glyphs have + concrete APIs, allowing fine control of rendering parameters, even + user-specified shapes. To provide convenient, consistent handling of + collections of glyphs, we need a well-defined font API. + + We can separate the necessary properties into two types: properties + which are common to all glyphs in the collection or a property of the + collection itself, and those which are glyph-specific. Henceforth, the + former are called "font properties" and the latter "glyph properties". + + Font properties include identification like the font "family", + font-wide design parameters like "slant" and "weight", font "metrics" + like "size" (nominal height) and "average width" used for approximate + layout (such as sizing a popup dialog), and properties like the + "default glyph" that are associated with the font for convenient use by + APIs, but aren't really an intrinsic property of the font as a + collection of glyphs. There may also be a "kerning table" (used to + improve spacing of adjacent glyphs). + + Glyph properties include the "index", glyph metrics such as + "ascent", "descent", "width", "offset" (the offset to the normal + position of the next glyph), "italic correction" (used to improve + spacing when slanted and unslanted glyphs are juxtaposed). Most + important, of course, is the glyph's shape, which is provided in a + format specific to a rendering engine. Common formats include bitmaps + (X11 BDF), Postcript programs (Type 1), and collections of spline curves + (TrueType). When the shape is not itself a bitmap, it must be + "rendered" to a pixmap, either a region on the display or a separate + object which is copied to the display. In that case, the shape may + include "multiple masters" or "hints" to allow context-specific + rendering which improves the appearance of the glyph on the display. + + Note that this use of "glyph" is mostly independent of the XEmacs + LISP glyph API. *Note Glyphs::. It is possible to extract a single + glyph from a font and encapsulate it in Lisp_Glyph object, but the LISP + glyph API allows access to only a very few glyph properties, none of + them related to the rendering process. + + XEmacs LISP does provide an API for selecting and querying fonts, in + the form of a fairly complete set of wrappers for `fontconfig' (*note + Modern Font Support -- fontconfig::). It also provides some control of + rendering of text via wrappers for `Xft' APIs (*note Modern Font + Support -- Xft::), but this API is quite incomplete. Also, since the + font selection and query facilities of `Xft' are provided by + `fontconfig', there is some confusion in the API. For example, use of + antialiasing to improve the appearance of rendered glyphs can be + enabled or disabled. The API for this is to set the `fontconfig' font + property `antialias' on the font. However, from the point of view of + `fontconfig' this is merely a hint that the rendering engine may or may + not respect. This property cannot be used to select only fonts + suitable for being antialiased, for example. And `rgba' (subpixel + geometry) and `dpi' (pixel density) are conceptually properties of the + display, not of either the font. They function as hints to the + rendering process. + + As a final confusing touch, `Xft' also provides some access to the + `XRender' extension provided by some modern X servers. This is mostly + limited to colors, but rectangle APIs are also provided. These are (of + course) completely independent of fonts, but `Xft' is designed for + client-side font rendering, and thus uses the `XRender' extension + heavily. + +  + File: internals.info, Node: Modern Font Support -- fontconfig, Next: Modern Font Support -- Xft, Prev: Modern Font Support -- Font Concepts, Up: Better Rendering Support -- Modern Font Support + + 40.24.5.2 Modern Font Support - fontconfig + .......................................... + + _Implementation notes_: The functions which initialize the library and + handle memory management (_e.g._, `FcInit' and `FcPatternDestroy') are + intentionally not wrapped (in the latter case, `fc-pattern-destroy' was + provided, but this was ill-considered and will be removed; LISP code + should *never* call this function). Thinking about some of the + auxiliary constructs used by `fontconfig' is in transition. The + `FcObjectSet' API has been internalized; it is exposed to LISP as a + list of strings. The `FcFontSet' API is still in use, but it also will + be internalized, probably as a list (alternatively, vector) of + `Lisp_fc_pattern' objects. Changing the representation of `fontconfig' + objects (property names) from LISP strings to keywords is under + consideration. + + If `Xft' (including `fontconfig') support is integrated into the + XEmacs build, XEmacs provides the symbol `xft' at initialization. + + XEmacs provides the following functions wrapping the `fontconfig' + library API. + + -- Function: fc-fontset-p object + Returns t if OBJECT is of type fc-fontset, nil otherwise. _This + API is likely to be removed in the near future._ + + -- Function: fc-fontset-count fcfontset + Counts the number of fc pattern objects stored in the fc fontset + object FCFONTSET. _This API is likely to be removed in the near + future._ + + -- Function: fc-fontset-ref fcfontset i + Return the fc pattern object at index I in fc fontset object + FCFONTSET. Return nil if the index exceeds the bounds of + FCFONTSET. _This API is likely to be removed in the near future._ + + -- Function: fc-fontset-destroy fcfontset + Explicitly deallocate FCFONTSET. _Do not call this function from + LISP code. You will crash. This API will be removed in the near + future._ + + -- Function: fc-pattern-p object + Returns t if OBJECT is of type fc-pattern, nil otherwise. + + -- Function: fc-pattern-create + Return a fresh and empty fc-pattern object. + + -- Function: fc-name-parse name + Parse string NAME as a fontconfig font name and return its + representation as a fc pattern object. + + -- Function: fc-name-unparse pattern + Unparse pattern object PATTERN to a string. + + `Xft''s similar function is actually a different API. We provide + both for now. (They probably invoke the same code from `fontconfig' + internally, but the `fontconfig' implementation is more conveniently + called from C.) + + -- Function: xft-name-unparse pattern + Unparse pattern object PATTERN to a string (using the `Xft' API). + + -- Function: fc-pattern-duplicate pattern + Make a copy of pattern object PATTERN and return it. + + -- Function: fc-pattern-add pattern property value + Add attributes to the pattern object PATTERN. PROPERTY is a + string naming the attribute to add, VALUE the value for this + attribute. + + VALUE may be a string, integer, float, or symbol, in which case + the value will be added as an FcChar8[], int, double, or FcBool + respectively. + + -- Function: fc-pattern-del pattern, property + Remove attribute PROPERTY from pattern object PATTERN. + + This is the generic interface to `FcPatternGet'. We don't support + the losing symbol-for-property interface. However, it might be a very + good idea to use keywords for property names in LISP. + + -- Function: fc-pattern-get pattern property &optional id type + From PATTERN, extract PROPERTY for the ID'th member, of type TYPE. + + PATTERN is an `Xft' (`fontconfig') pattern object. PROPERTY is a + string naming a `fontconfig' font property. Optional ID is a + nonnegative integer indexing the list of values for PROPERTY + stored in PATTERN, defaulting to 0 (the first value). Optional + TYPE is a symbol, one of 'string, 'boolean, 'integer, 'float, + 'double, 'matrix, 'charset, or 'void, corresponding to the FcValue + types. ('float is an alias for 'double). + + Symbols with names of the form `fc-result-DESCRIPTION' are + returned when the desired value is not available. These are + + fc-result-type-mismatch the value found has an unexpected type + fc-result-no-match there is no such attribute + fc-result-no-id there is no value for the requested ID + + The Lisp types returned will conform to TYPE: + + string string + boolean `t' or `nil' + integer integer + double (float) float + matrix not implemented + charset not implemented + void not implemented + + The types of the following standard properties are predefined by + fontconfig. The symbol 'fc-result-type-mismatch will be returned if the + object exists but TYPE does not match the predefined type. It is best + not to specify a type for predefined properties, as a mistake here + ensures error returns on the correct type. + + Each standard property has a convenience accessor defined in + `fontconfig.el', named in the form `fc-pattern-get-PROPERTY'. The + convenience functions are preferred to `fc-pattern-get' since a typo in + the string naming a property will result in a silent null return, while + a typo in a function name will usually result in a compiler or runtime + \"not fboundp\" error. You may use `defsubst' to define convenience + functions for non-standard properties. + + family String Font family name + style String Font style. Overrides weight and slant + slant Int Italic, oblique or roman + weight Int Light, medium, demibold, bold or black + size Double Point size + aspect Double Stretches glyphs horizontally before hinting + pixelsize Double Pixel size + spacing Int Proportional, monospace or charcell + foundry String Font foundry name + antialias Bool Whether glyphs can be antialiased + hinting Bool Whether the rasterizer should use hinting + verticallayout Bool Use vertical layout + autohint Bool Use autohinter instead of normal hinter + globaladvance Bool Use font global advance data + file String The filename holding the font + index Int The index of the font within the file + ftface FT_Face Use the specified FreeType face object + rasterizer String Which rasterizer is in use + outline Bool Whether the glyphs are outlines + scalable Bool Whether glyphs can be scaled + scale Double Scale factor for point->pixel conversions + dpi Double Target dots per inch + rgba Int unknown, rgb, bgr, vrgb, vbgr, none - subpixel geometry + minspace Bool Eliminate leading from line spacing + charset CharSet Unicode chars encoded by the font + lang String List of RFC-3066-style languages this font supports + + The FT_Face, Matrix, CharSet types are unimplemented, so the + corresponding properties are not accessible from Lisp at this time. If + the value of a property returned has type FT_Face, FcCharSet, or + FcMatrix, `fc-result-type-mismatch' is returned. + + The following properties which were standard in `Xft' v.1 are + obsolete in `Xft' v.2: `encoding', `charwidth', `charheight', `core', + and `render'. + + -- Function: fc-pattern-destroy pattern + Explicitly deallocate pattern object PATTERN. _Do not call this + function from LISP code. You will crash. This API will be removed + in the near future._ + + -- Function: fc-font-match device pattern + Return the font on DEVICE that most closely matches PATTERN. + + PATTERN is a `fontconfig' pattern object. DEVICE is an X11 + device. Returns a `fontconfig' pattern object representing the + closest match to the given pattern, or an error code. Possible + error codes are `fc-result-no-match' and `fc-result-no-id'. + + -- Function: fc-list-fonts-pattern-objects device pattern properties + List the fonts on DEVICE that match PATTERN for PROPERTIES. + DEVICE is an X11 device. PATTERN is a `fontconfig' pattern to be + matched. PROPERTIES is the list of property names (strings) that + should be included in each returned pattern. The result is a + `fontconfig' fontset object containing the set of unique matching + patterns. + + The PROPERTIES argument does not affect the matching. So, for + example, + + (mapcar #'fc-name-unparse + (let ((xfl (fc-list-fonts-pattern-objects nil + (fc-name-parse "FreeMono") '("style"))) + (i 0) + (fl nil)) + (while (< i (fc-fontset-count xfl)) + (push (fc-fontset-ref xfl i) fl) + (setq i (1+ i))) + fl)) + + will return something like `(":style=Bold" ":style=Medium" + ":style=Oblique" ":style=BoldOblique")' if you have the FreeFont + package installed. Note that the sets of objects in the target pattern + and the returned patterns don't even intersect. + + In using `fc-list-fonts-pattern-objects', be careful that only + intrinsic properties of fonts be included in the pattern. Those + properties included in the pattern must be matched, or the candidate + font will be eliminated from the list. When a font leaves a property + unspecified, it is considered to be a mismatch for any pattern with that + property specified. Thus, inclusion of extraneous properties will + result in the list being empty. Note that for scalable fonts (at + least), `size' is not an intrinsic property! Thus a specification such + as `"Bitstream Vera Sans-12"' will return an empty list regardless of + whether the font is available or not--probably not what you (as + programmer or user) want. + + The list is unsorted. In particular, the pattern + `":style=italic,oblique"' will not return italic fonts first, then + oblique ones. The fonts will be returned in some arbitrary order. + + _Implementation notes_: Fontset objects are slated for removal from + the API. In the future `fc-list-fonts-pattern-objects' will return a + list. The DEVICE argument is unused, ignored, and may be removed if + it's not needed to match other font-listing APIs. This name will be + changed to correspond to Ben's new nomenclature, probably simply + `fc-font-list'. + + -- Function: fc-font-sort device pattern trim + Return a fontset object listing all fonts sorted by proximity to + PATTERN. DEVICE is an X11 device. PATTERN is a fontconfig + pattern to be matched. Optional argument TRIM, if non-nil, means + to trim trailing fonts that do not contribute new characters to + the union repertoire. + + _Implementation notes_: Fontset objects are slated for removal from + the API. In the future `fc-font-sort' will return a list (or perhaps a + vector) of FcPatterns. The DEVICE argument is unused, ignored, and may + be removed if it's not needed to match other font-listing APIs. + + -- Function: fc-font-real-pattern fontname xdevice + Temporarily open font FONTNAME (a string) on device XDEVICE and + return the actual fc pattern matched by the Fc library. _This + function doesn't make much sense and will be removed from the API._ + + -- Function: xlfd-font-name-p fontname + Check whether string FONTNAME is a XLFD font name. + + -- Variable: xft-debug-level + Level of debugging messages to issue to stderr for XFT. A + nonnegative integer. Set to 0 to suppress all warnings. Default + is 1 to ensure a minimum of debugging output at initialization. + Higher levels give more information. + + -- Variable: xft-version + The major version number of the Xft library compiled with. + + -- Variable: xft-xlfd-font-regexp + Regular expression matching XLFD font names. + +  + File: internals.info, Node: Modern Font Support -- Xft, Prev: Modern Font Support -- fontconfig, Up: Better Rendering Support -- Modern Font Support + + 40.24.5.3 Modern Font Support - fontconfig + .......................................... + + IIRC, we don't really provide any `Xft' APIs at the LISP level yet. + +  + File: internals.info, Node: Future Work Discussion, Next: Old Future Work, Prev: Future Work, Up: Top + + 41 Future Work Discussion + ************************* + + This chapter includes (mostly) email discussions about particular design + issues, edited to include only relevant and useful stuff. Ideally over + time these could be condensed down to a single design document to go + into the normal Future Work section. + + * Menu: + + * Discussion -- Garbage Collection:: + * Discussion -- Glyphs:: + * Discussion -- Dialog Boxes:: + * Discussion -- Multilingual Issues:: + * Discussion -- Instantiators and Generic Property Accessors:: + * Discussion -- Switching to C++:: + * Discussion -- Windows External Widget:: + * Discussion -- Packages:: + * Discussion -- Distribution Layout:: + +  + File: internals.info, Node: Discussion -- Garbage Collection, Next: Discussion -- Glyphs, Prev: Future Work Discussion, Up: Future Work Discussion + + 41.1 Discussion - Garbage Collection + ==================================== + + * Menu: + + * Discussion -- Pure Space:: + * Discussion -- Hashtable-Based Marking and Cleanup:: + * Discussion -- The Anti-Cons:: + +  + File: internals.info, Node: Discussion -- Pure Space, Next: Discussion -- Hashtable-Based Marking and Cleanup, Prev: Discussion -- Garbage Collection, Up: Discussion -- Garbage Collection + + 41.1.1 Discussion - Pure Space + ------------------------------ + + On Tue, Oct 12, 1999 at 03:36:59AM -0700, Ben Wing wrote: + + So what am I missing here? + + In response, Olivier Galibert wrote: + + Two things: + 1. The purespace is gone + + I mean absolutely, completely and utterly removed. Fpurecopy + is a no-op now (and have been for some time). Readonly objects + are gone too. Having less checks to do in Fsetcar, Fsetcdr, + Faset and some others is probably a good thing, speedwise. I + have it removed some time ago because it does not make sense + when using a portable dumper to copy data in a special area of the + memory at dump time and I wanted to be sure that supressing the + copying from Fpurecopy wouldn't break things. + + Now, we want to get the post-dumping data sharing back, of course. + In today systems, it is quite easy: you just have to map + the file MAP_PRIVATE and avoid writing to the subset of pages + you want to keep shared. Copy-on-write does the job for you. + It has the nice side effect of completely avoiding bus errors + due to trying to write to readonly memory zones. + + Avoiding writing to the "pure" objects themselves is already + done, of course. Would lisp code have written to the purecopied + parts of the dumped data that it would have exploded long ago. So + there is nothing to do in this area. So the only remaining thing + is the markbit. Two possible strategies: + + * have Fpurecopy mark somehow the lrecords it would have copied + in the good old times. Post-dump, use this mark as a "always + marked, don't touch, don't look into, don't free" flag, the + same way CHECK_PURE was used. + + * move the markbit outside of the lrecord. + + The second solution is more appealing to me for a bunch of reasons: + * more things are shared than only what is purecopied (not + yet used functions come to mind) + + * no more "the only references to this non-purecopied object + are from purecopied objects, XEmacs will self-destruct in + ten seconds" kind of bugs. + + * removing flags goes the right way towards implementing + Jan's allocator ideas. + + * it becomes probably easier to experiment with the GC code + + 2. Finding all the dumped objects in order to unmark them sucks + + Not having to rebuild a list of all the dumped objects in + order to find them all and ensure that all are unmarked + simplifies things for me. Errr, ok, now that I really think of + it, I can rebuild this list easily, in fact. And I'm probably + going to have to manage it, since I feel like the lack of calls + to the finalizers for the dumped objects is going to someday + turn over and bite me in the face. But anyways, it makes my life + easier for now. + + So no, it's not a _necessity_. But it helps. And the + automatic sharing of all objects until you write to them + explicitely is, I think, really cool. + +  + File: internals.info, Node: Discussion -- Hashtable-Based Marking and Cleanup, Next: Discussion -- The Anti-Cons, Prev: Discussion -- Pure Space, Up: Discussion -- Garbage Collection + + 41.1.2 Discussion - Hashtable-Based Marking and Cleanup + ------------------------------------------------------- + + On 10/12/1999 5:49 PM Ben Wing wrote: + + OK, I can see the advantages. But: + + 1. There will be an inevitable loss of speed using a large hashtable. + If it's large, I say that it's just not worth it. There are + things that are so much more important than futzing around with + the garbage collector (e.g. fixing the god damn user interface), + things which if not fixed will sooner or later cause XEmacs to die + entirely. If we are causing a major slowdown in the name of some + not-so-important work that may or may not get done, we shouldn't + do it. (On the other hand, if the slowdown is negligible, I have + no problems with this.) + + 2. I think you should *expand* the concept of read-only objects so + that *any* object (especially strings and cons cells) can get + marked read-only by the C code if it wants. (Perhaps you could use + the now-unused mark bit to hold a read-only flag.) This is + important because it allows C code to directly return internal + lists (e.g. from the specifiers and various object property lists) + without having to do a copy, like is now done (and similarly, + potentially to directly accept lists from a Lisp call without + copying them for internal use, if the Lisp caller is made aware + that the list might become read-only) - if the copy weren't done + and some piece of Lisp code went and modified the list, XEmacs + might very well crash. Thus, this read-only flag would be a huge + efficiency gain in terms of the garbage collection overhead saved + as well as the speed of copying a large list. The extra checks in + `Fsetcar()', etc. for this that you mention are in fact negligible + in their speed overhead - one or two instructions - and these + functions are not used all that commonly, either. With the + changes I have proposed in Architecting XEmacs, the case of + returning an internal list will become more and more common as the + power of the user interface would be greatly increased and along + with it are lots and lots of lists of info that need to be + retrievable from Lisp. + + BTW there is a wonderful book all about garbage collection by Jones + and Lins. Ever seen it? + + http://www.amazon.com/exec/obidos/ASIN/0471941484/qid=939775572/sr=1-1/002-3092633-2509405 + +  + File: internals.info, Node: Discussion -- The Anti-Cons, Prev: Discussion -- Hashtable-Based Marking and Cleanup, Up: Discussion -- Garbage Collection + + 41.1.3 Discussion - The Anti-Cons + --------------------------------- + + From: "Ben Wing" Date: Tue, 14 May 2002 06:48:09 -0700 + + i was thinking about the proliferating types of weak hash tables - + e.g. now we have "key-car-value weak" hash tables due to a need in the + glyphs code. i realized there should be a general solution, that lets + you control exactly how the weakness of such hash tables work. + + and, assuming we implement a simple "reference" type, a simple + container whose object is a weak reference and thus gets converted to + nil (and a flag set on the reference) when the object is collected, it + would be useful for more precisely controlling the reference, too. + + it's called an "anti-cons". it behaves somewhat like a cons in that + it boxes two items, but its marking properties are very different - in + fact, backwards. normally, a cons, if marked, marks its children. in + this case, if the children of an anti-cons are marked, it marks itself! + you'd need a few different kinds of anti-cons - probably the following: + + and [marks itself if both children marked] + or [...] + left [marks itself if left is marked, and then marks the right] + right [...] + not-left + not-right + + by putting such an object inside of a weak reference - e.g. in a weak + hash table - we can set up a tree of arbitrary complexity which + implements any boolean formula of markedness over any number of + objects. this would easily handle key-car, and key-cadr, and + key-car-or-cdr, and key-((caar or cadr) and cdr) etc. etc. + + implementing this in the current xemacs framework is mostly trivial. + + michael, would such an object get in the way of your new gc? + + From: sperber@informatik.uni-tuebingen.de (Michael Sperber [Mr. + Preprocessor]) Date: Tue, 14 May 2002 16:04:01 +0200 + + You might want to look at + + http://research.microsoft.com/Users/simonpj/Papers/weak.htm + + for a pretty comprehensive survey of what you could want in terms of + weakness. Its weak pointers are very similar to your anti-cons. + However, there are some problems in doing the same in a Lisp settings, + mainly because of symbols. I intend to elaborate on this next week; + this week is full, unfortunately. + + Ben> implementing this in the current xemacs framework is mostly + Ben> trivial. + + Ben> michael, would such an object get in the way of your new gc? + + Well, our first commit will be an implementation of vanilla weak + boxes (ready within the next few days, I hope), and we'll then try to + replace most other instances of weakness with uses of those. We'll + then try to find a more general solution for the rest. (Richard + Reingruber has already done a comprehensive survey of the trouble spot. + + Can you wait until next week? I'll try to come up with a battle plan + then. + + From: sperber@informatik.uni-tuebingen.de (Michael Sperber [Mr. + Preprocessor]) Date: Tue, 28 May 2002 16:14:20 +0200 + + We've now started implementing ephemerons as a building block for the + more involved weakness-involving data structures: + + The relevant reference is + + Barry Hayes. Ephemerons: A New Finalization Mechanism. OOPSLA 1997. + 176-183 + + The idea is this: + + an ephemeron consists of a key and a value. Through the ephemeron, + the key is not reachable. The value is only reachable if both the + ephemeron is reachable and the key is reachable. If the ephemeron is + reachable and the key becomes unreachable, the value slot of the + ephemeron will be tombstoned, i.e. overwritten with NIL or something. + + This allows implementing, AFAICS, the other data structures involving + weakness, such as weak hash tables and their various mutants. + + We're also planning to come up with a more comprehensive solution for + finalization, but some design snags remain to be worked out. + +  + File: internals.info, Node: Discussion -- Glyphs, Next: Discussion -- Dialog Boxes, Prev: Discussion -- Garbage Collection, Up: Future Work Discussion + + 41.2 Discussion - Glyphs + ======================== + + Some comments (not always pretty!) by Ben: + + March 20, 2000 + + Andy, I use the tab widgets but I've been having lots of problems. + + 1] Sometimes clicking on them does nothing. + + 2] There's a design flaw: I frequently use M-C-l to switch to the + previous buffer. If I use this in conjunction with the tabs, things get + all screwed up because selecting a buffer with the tab does not bring it + to the front of the buffer list, like it should. It looks like you're + doing this to avoid having the order of the tabs change, but this is + wrong: If you don't reorder the buffer list, everything else gets + screwed up. If you want the order of the tabs not to change, you need + to decouple this order from the buffer list order. + + March 23, 2000 + + I'm very confused. The SIGIO timer is used *only* for C-g. It has + nothing to do with any other events. (sit-for 0) ought to + + (1) cause all pending non-command events to get executed, and (b) do + redisplay + + However, sit-for gets preempted by input coming in. + + What about (sit-for 0.1)? + + I suppose a solution along the lines of dispatch-non-command-events + might be OK if you've tried everything else and it doesn't work, but i'm + leery of introducing new Lisp functions to deal with specific problems. + Pretty soon we end up with a whole bevy of such ill-defined functions, + like we already have. I think instead, you should introduce the + following primitive: + + (wait-for-event redisplay &rest event-specs) + + Waits for one of the event specifications specified to happen. + Returns something about what happened. + + REDISPLAY controls the behavior of redisplay during waiting. + Something like + + * nil (never redisplay), + + * t (redisplay when it seems appropriate), etc. + + EVENT-SPECS could be + + t -- drain all non-user events, and then return + any-process -- wait till input or state change on any process + process -- wait till input or state change on process + time -- wait till such-and-such time has elapsed + 'user -- wait till user event has happened + '(user predicate) -- wait till user event matching the predicate has + happened + 'event -- wait till any event has happened + '(event predicate) -- wait till event matching the predicate has happened + + The existing functions `next-event', `next-command-event', + `accept-process-output', `sit-for', `sleep-for', etc. could all be + written in terms of this new command. You could use this command inside + of your glyph code to ensure that the events get processed that need do + in order for widget updates to happen. + + But you said something about need a magic event to invoke redisplay? + Why is that? + + April 2, 2000 + + the internal distinction between "widget" and "layout" is bogus. + there exist widgets that do drawing and do layout of their children, + e.g. group-box widgets and proper tab widgets. the only sensible + distinction is between widgets with children and those without children. + + April 5, 2000 + + andy, i'm not sure i really believe that you need to cycle the event + code to get widgets to redisplay, but in any case you should + + 1. hide the logic to do this in the c code; the lisp code should do + nothing other than call (redisplay widget) + + 2. make sure your event-cycling code processes *NO* events at all. + this includes non-user events. queue the events instead. + + in other words, dispatch-non-command-events must go, and i am + proposing a general function (redisplay OBJECT) to replace the existing + ad-hoc functions. + + April 6, 2000 + + the tab widget code should simply be able to create a whole lot of + tabs without regard to the size of the gutter, and the surrounding + layout widget (please please make layouts be proper widgets!) should + automatically map and unmap them as necessary, to fill up the available + space. perhaps this already works and what you're doing is just for + optimization? but i get the feeling this is not the case. + + April 6, 2000 + + the function make-gutter-only-dialog-frame is bogus. the use of the + gutter here to hold widgets is an implementation detail and should not + be exposed in the interface. similarly, make-search-dialog should not + have to do all the futzing that it does. creating the frame unmapped, + creating an extent and messing with the gutter: all this stuff should be + hidden. you should have a simple function make-dialog-frame that takes + a dialog specification, and that's all you need to do. + + also, these dialog boxes, and this function make-dialog-frame, should + + 1. be in `dialog.el', not gutter-items.el. + + 2. when possible, be placed in the interactive spec of standard lisp + functions rather than accessed directly from `menubar-items.el' + + 3. wrapped in calls to should-use-dialog-box-p, so the user has + control over when dialog boxes appear. + + April 7, 2000 + + hmmm ... in that case, the whitespace absolutely needs to be + specified as properties of the layout widget (e.g. :border-width and + :border-height), rather than setting an overall size. you have no idea + what the correct size should be if the user changes font size or uses + translations in a different language. + + Your modus operandi should be "hardcoded pixel sizes are *always* + bad." + + April 7, 2000 + + you mean the number of tabs adjusts, or the size of each tab adjusts + (by making the font smaller or something)? if the size of a single tab + is not related to the total space the tabs can fix into, then it should + be possible to simply specify as many tabs as exist for buffers, and + have the layout manager decide how many can fit into the available + space. this does *not* mean the layout manager will resize the tabs, + because query-geometry on the tabs should find out that the tabs don't + want to be any size other than they are. + + the point here is that you should not *have* to worry about pixel + heights and widths *anywhere* in Lisp-level code. The layout managers + should take care of everything for you. The only exceptions may be in + some text fields, which will be blank by default and you want to specify + a maximum width (which should be done in 'n' sizes, not in pixels!). + + i won't stop complaining until i see nearly every one of those + pixel-width and pixel-height parameters gone, and the remaining ones + there for a very, very good reason. + + April 7, 2000 + + Andy Piper wrote: + + > At 03:51 PM 4/6/00 -0700, Ben Wing wrote: + > >[the function make-gutter-only-dialog-frame is bogus] + > + > The problem is that some of the callbacks and such need access to the + > *created* frame, so you end up in a catch 22 unless you do what I've done. + + [Ben proposes other ways to avoid exposing all the guts, as in + `make-gutter-only-dialog-frame':] + + 1. Instead of passing in the actual glyph spec or glyph, pass in a + function of two args (the dialog frame and its parents), which when + called, creates and returns the appropriate glyph. + + 2. [Better] Provide a way for callbacks to determine where they were + invoked at. This is much more general and is what you should + really do. For example, have the code that calls the callbacks + bind some global variables such as widget-callback-current-glyph + and widget-callback-current-channel, which contain the glyph whose + callback is being invoked, and the window or frame of the glyph + (depending on where the glyph is) where the invocation actually + happened. That way, the callbacks can easily figure out the dialog + box and its parent, and not have to worry about embedding it in at + creation time. + + April 15, 2000 I don't understand when you say "the various types of + callback". Are you using the callback for various different purposes? + + Your widget callbacks should work just like any other callback: they + take two arguments, one indicating the object to which the callback was + attached (an image instance, i think), and the event that caused the + callback to be invoked. + + April 17, 2000 + + I am completely vetoing widget-callback-current-channel. How about + you create a new keyword, :new-callback, that is a function of two args, + like i specified before. + + btw if you really are calling your callback using call-interactively, + why don't you declare a function (interactive "e") and then call + event-channel on the resulting event? that should get you the same + result as widget-callback-current-channel. + + the problem with this and everything you've proposed is that there's + no way, of course, to get at the actual widget that you were invoked + from. would you propose adding widget-callback-current-widget? + +  + File: internals.info, Node: Discussion -- Dialog Boxes, Next: Discussion -- Multilingual Issues, Prev: Discussion -- Glyphs, Up: Future Work Discussion + + 41.3 Discussion - Dialog Boxes + ============================== + + From: + Ben Wing + 10/7/1999 5:57 PM + + Subject: + Re: Animated gif patch (2) + To: + Andy Piper + CC: + xemacs-review@xemacs.org, xemacs-beta@xemacs.org + + + + + The distinction between layouts and widgets makes no sense, so you should combine + the different data required. Consider a grouping widget. Is this a layout or a + widget? It draws, like a widget, but has children, like a layout. Same for a tab + widget, properly implemented. It draws, handles input, has children, and makes + choices about how to lay them out. + + ben + + From: + Ben Wing + 9/7/1999 8:50 PM + + Subject: + Re: Layouts done + To: + Andy Piper + + + + + this sounds great! where can i see the code? + + as for user-defined layouts, you must certainly have some sort of abstraction + layer for layouts, with DEFINE_LAYOUT_TYPE or something similar just like device + types and such. If not, you should certainly make one ... it would have methods + such as query-geometry and do-layout. It should be easy to create a user-defined + layout if you have such an abstraction. + + with a user-defined layout, complex built-in layouts such as grid should not be + necessary because it's so easy to write snippets of lisp. + + as for the "redisplay too much" problem, perhaps you could put a dirty flag in + each glyph indicating whether it needs to be redisplayed, recalculated, etc.? + + Andy Piper wrote: + + > You may want to check them out. I haven't done the user-defined layout + > callback - I'm not sure what sort of API this could have. Keywords I've done: + > + > :orientation - vertical or horizontal + > :justify - left, center or right + > :border - etch-in, etch-out, bevel-in, bevel -out or text (which gives you + > etch-in with a title) + > + > You can embed any glyph type in a layout. + > + > There is probably room for improvements for justify to do grid-type layouts + > as per java. + > + > The only annoying thing is that I've hacked up font-lock support to do a + > progress gauge in the gutter area. I've used a layout to set things out + > correctly. The problem is if you change one of the sub-widgets, the whole + > layout gets redisplayed because it is treated as a single glyph by redisplay. + > + > Oh, and I've done line based scrolling so that glyphs scroll off the page + > in units of the average display line height rather than the whole line at + > once. This could easily be converted to pixel scrolling but would be very + > slow I fear. + > + > andy + > -------------------------------------------------------------- + > Dr Andy Piper + > Senior Consultant Architect, BEA Systems Ltd + + + + + From: + Ben Wing + 8/10/1999 11:11 PM + + Subject: + Re: Widgets + To: + Andy Piper + + + + + I think you might have misinterpreted what i meant. I meant to say that XEmacs should + implement the *concept* of a hierarchy of nested child "widgets" or "gui items" or + whatever we want to call them -- this includes container "widgets" such as grouping + widgets (which draw a border around the children, like in Windows), tab widgets, simple + layout widgets (invisible, but lay out their children appropriately), etc, plus leaf + "widgets" (buttons, sliders, etc., also standard Emacs windows). The layout calculations + for these widgets would be handled entirely by XEmacs in a window-system-independent way. + There is no need to create a corresponding hierarchy of window-system + widgets/controls/whatever if it's not required, and certainly no need to try to use the + window-system-supplied geometry management routines. It's absolutely necessary to support + this nesting concept in XEmacs, however, or it's impossible to have easily-designable + dialog boxes. On the other hand, I think it *is* required to create much of this + hierarchy within the actual window system, at the very least for non-invisible container + widgets (tab, grouping, etc.), otherwise we will have very bogus, non-native-looking + containers like your current tab-widget implementation. It's critical for XEmacs to be + able to create dialog boxes in Windows or Motif that look just like those in any other + standard application. Otherwise people will continue to think that XEmacs is a + backwards-looking, badly implemented piece of software, which in many ways it is, + particularly in regards to its user interface. + + Perhaps we should talk on the phone? This typing is quite hard for me still. What hours + are you at work? My hours are approx. 2pm - 2am Pacific time (GMT - 7 hours currently). + + ben + + + From: + Ben Wing + 7/21/1999 2:44 AM + + Subject: + Re: Tabs 'n widgets screenshot + To: + Andy Piper + CC: + xemacs-beta@xemacs.org, wmperry@aventail.com + + + + + This is real cool, but looking at this, it's clear that it doesn't look the + way tab widgets are supposed to work. In particular, of course, they should + have the proper borders around the stuff displayed. I've attached a screen + shot of a typical Windows dialog box with a tab widget in it. The problem + lies with this "expanded gutter" concept. Tabs are *NOT* extra graphical junk + placed in the gutters of a buffer but are GUI objects with *children* inside + of them. This is the right way to do things, and you would need no extra + gutter functionality at all for this. You just need to implement the concept + of GUI objects containing other GUI objects within them. One such GUI object + needs to be a "Emacs-text" GUI object, which is an Emacs window and contains a + buffer within it. At this level, you need not be concerned with the + complexities of geometry layout. The only change that needs to be made in the + overall strategy of frames, windows, etc. is that windows need not be exactly + contiguous and tiled, as long as they are contained within a frame. Or more + specifically: Given that you could always split a window contained inside a + GUI object, we just need to expand things so that each frame has *multiple* + hierarchies of windows in it, rather than just one. A hierarchy of windows + can nest inside of another window -- e.g. I put a tab widget or a text widget + inside of a buffer. This should be easy to implement -- just change things so + there are multiple hierarchies of windows where there are one, each (except + the top-level one) being rooted inside some other window. + + Anyone willing to implement this? Andy? + + + From: + Ben Wing + 6/30/1999 3:30 PM + + Subject: + Re: Focus Help! + To: + Andy Piper + CC: + Ben Wing , martin@xemacs.org, andyp@beasys.com + + + + + It sounds like you're doing very good work. It also sounds like the approach + you have followed is the correct one. Now, it seems like there isn't really + that much work left to get dialog boxes working. What you really just need to + do is implement container widgets, that is to say, subwindows that can contain + other subwindows. For example, the tab widget works this way. (It sounds like + you have already implemented tab widgets, so I don't quite see how you've done + this without the concept of container widgets.) So you might just try adding a + framework for container widgets and then implementing very simple container + widgets. The basic container widgets are: + + 1. A vertical-layout widget, which draws nothing itself and lays out its + children one above the next. + 2. A horizontal-layout widget, which draws nothing itself and lays out its + children side-to-side. + 3. A box (or "grouping") widget, which draws a rectangle around its single child + and optionally draws some text on the top or bottom line of the rectangle. + 4. A tab widget, which displays a series of tabs horizontally at the top of its + area, and then below it places one of its children, + corresponding to the selected tab. + 5. A user widget, which draws nothing itself and does no layout at all on its + children, except that it has a "layout callback" + property, a Lisp function, so that the programmer can control the layout. + + The framework is as follows: + + 1. Every widget has at least the following properties: + a) a size, whose value can be "unspecified", which might be implemented + using the value -1. The default value should be "unspecified". + b) whether it's mapped, i.e. whether it will be displayed. (Some container + widgets, such as the tab widget, set the mapped + property themselves on their children. Others, such as the vertical and + horizontal layout widgets, don't change this property but pay attention to it, + and ignore completely all children marked as unmapped.) The default value should + be "true". + c) whether its size can be changed by another widget's layout routine. The + default value should be "true". + d) a layout procedure, which (potentially at least) determines the size of + the widget as well as the position, size and mappedness of its child widgets. + The layout procedure is inherent in the widget and is not an external property + of the widget (except in the case of the "user widget"): it is instead more like + the redisplay callback that each widget has. + 2. Every container widget contains a property which is a list of child widgets. + 3. Every child widget contains the following properties: + a) a position indicating where the child is located relative to the top + left corner of its parent. The position's value can be "unspecified", which + might be implemented using the value -1. The default value should be + "unspecified". + b) whether its position can be changed by another widget's layout routine. + The default value should be "true". + 4. All of the properties just listed (except possibly the layout procedure) can + be modified directly by the programmer, and there are no proscriptions against + doing so. However, if the programmer wants to resize, reposition, map or unmap + a widget in such a way that the layout of all the other widgets in the tree + changes appropriately, he should use a special function to change the property, + as described below. + + The redisplay mechanism pays attention to the position, size, and mappedness + properties and to the hierarchy of widgets, mapping, resizing and repositioning + the corresponding subwindows (the "real representation" of the widgets) as + necessary. It also pays attention to the hierarchy of the widgets, making sure + that container subwindows get drawn before their child subwindows. When it + encounters widgets with an unspecified size, it should not draw them, and should + issue a warning. When it encounters widgets with an unspecified position, it + should draw them at position (0, 0) and should issue a warning. + + The above framework should be fairly simple to implement and is basically + universal across all high-level windowing system toolkits. The stickyness comes + with what procedures you follow for getting the layout done. + + Andy, I understand that implementing this may seem like a daunting task. + Therefore, I propose that at first you implement the above framework but don't + implement any of the layout procedures, or any of the functions that call them: + Just make them stubs that do nothing. This way, the Lisp programmer can still + create any dialog boxes he wants, he just has to set the sizes and positions of + all the widgets explicitly, and then recompute them whenever the widget tree is + resized (once you get around to allowing this). I have a lot more to write + about exactly how the layout procedures work, but I'll send that to you later + once you're ready. + + You should also think about making a way to have widget trees as top-level + windows rather than just glyphs in a buffer. There's already the concept of + "popup" frames. You could provide an easy way to create a popup frame with no + menu, toolbars, scrollbars, modeline or minibuffer, and put a single glyph in + the displayed buffer that takes up the whole Emacs window. + + Ben + + + + + March 20, 2000 + + You wrote to me awhile ago about this and asked about documentation, and I + dictated a response but never got it sent, so here it is: + + I don't think there's any more documentation on how things work under Xt but it + should be clear. The EmacsFrame widget is the widget corresponding to the X + window that Emacs draws into and there is a handler for expose events called + from Xt which arranges for the invalidated areas to get redrawn. I think this + used to happen as part of the handler itself but now it is delayed until the + next call to redisplay. + + However, one thing that you absolutely must not do is remove the Xt support. + This would be an incredibly unfriendly thing to do as it would prevent people + from using any widget set other than Qt or GTK. Keep in mind that people run + XEmacs on all sorts of different versions of X in Unix, and Xt is the standard + and the only toolkit that probably exists on all of these systems. + + Pardon me if I've misunderstood your intentions w.r.t. this. + + As for how you would implement GTK support, it will not be very hard to convert + redisplay to draw into a GTK window instead of an Xt window. In fact redisplay + basically doesn't know about Xt at all, except in the portion that handles + updating menubars and scrollbars and stuff that's directly related to Xt. + + What you'd probably want to do is create a new set of event routines to replace + the ones in event-Xt.c. On the display side you could conceivably create a new + device type but you probably wouldn't want to do that because it would be an + externally visible change at the Lisp level. You might simply want to put a + flag on each frame indicating what sort of toolkit the frame was created under + and put conditions in the redisplay code and the code to update toolbars and + menubars and so forth to test this flag and do the appropriate thing. + + + April 12, 2000 + + This is way cool, buuuuutttttttt ............. + + what we *really* need is the GUI interface on top of it. I've taken a shot at + it with generic-print-buffer + (print-buffer is taken by lpr, which is such a total mess that it needs to be + trashed; or at least, the generic + stuff in this package needs to be taken out and properly genericized). For + the moment, generic-print-buffer + just does something like what Kirill's been posting if we're running windows, + and uses lpr otherwards. However, what we absofuckinglutely need is a Lisp + interface onto `EnumPrinters()' so that we can get the + list of printers and have a nice menu listing the available printers, and you + can check the one you want. People in the Windows world don't normally even + know the names of their local printers! + + Kirill, given what I've done in `simple.el' and `menubar-items.el', do you think + you could add the `EnumPrinters()' + support and fix up the GUI? If you don't feel comfortable with the GUI, at + least do the `EnumPrinters()'. + + But ... Kirill, I tried your formula for printing and nothing happened. + Perhaps I didn't call redisplay-frame or something? You need to fix this up + and make it work for multi-page documents. (Again, this is in + generic-print-buffer.) Nothing special, it just needs to fucking work! There + are zillions and zillions of postings every day on xemacs-nt about how to get + printing working, and none seem to refer to the built-in support. + + ben + + + April 19, 2000 + + Kirill 'Big K' Katsnelson wrote: + + > Some time ago, Ben Wing wrote... + > >kirill, the interface i created is more general, like this: + > + > [snip] + > + > >Unfortunately I haven't implemented much of this; just some of the file + > >dialog box. but i think + > >this is better than creating new mswindows-specific primitives. if you + > >are interested in working on + > >this, i'll send you the code i have. + > + > Sure. Can you just commit it for my starting point? + > + > >also, the dialogs shouldn't have anything directly to do with the printer + > >device. all they should + > >do is return a set of values. it's the caller's responsibility to + > >interpret them and set device + > >properties accordingly. this way, there's a complete separation between + > >the underlying + > >functionality and the gui. + > + > Unfortunately. I thought about doing it this way, but we then lose a lot of + > printer-specific setup in this case. The DEVMODE structure contains two + > parts: printer independent, as defined by SDK typedef DEVMODE, and + > some trailing bytes, of unknown structure, used by a driver. The driver + > only returns the extra length it wants. Such options as PCL ReT resolution + > enhancement options or PostScript negative output are not available + > through the standard part of the devmode structure, and stored in the + > driver part (printer dialogs are driver-specific). + > + > So we have total of three options: + > - Not to implement options beyond standard DEVMODE + > - Make DEVMODE a Lisp object. + > - Hide DEVMODE inside the device object. + > + > First case looks cheesy. Letting DEVMODE fall off the printer is no good + > either, since one needs both the device and the devmode to edit the + > devmode, and they must match. I am still convinced that the devmode and + > the printer should not be separated. + + hmm, i see ... this completely breaks abstraction though. it fails in various + scenarios, e.g. a program wants to initialize the dialog box with certain + non-driver-specific properties, without caring about the particular printer. + + i think you should create a new print-properties object that encapsulates all + printer properties (which can be changed using get/put), including the printer + name, and contains a DEVMODE in it. if the printer name gets changed, the + DEVMODE might change too, but the print-properties object itself stays the + same. you pass this object as a parameter to the dialog box, and it gets + changed accordingly. you can call something like set-device-print-properties to + stick everything in this structure into the device. (you could imagine a case + where someone wanted to keep multiple print configurations around ...) + + > + > + > Big K + + -- + Ben + +  + File: internals.info, Node: Discussion -- Multilingual Issues, Next: Discussion -- Instantiators and Generic Property Accessors, Prev: Discussion -- Dialog Boxes, Up: Future Work Discussion + + 41.4 Discussion - Multilingual Issues + ===================================== + + + 4/10/2000 4:13 AM + + BTW I am planning on adding some more powerful font-mapping capabilities to + XEmacs (i.e. how do we map particular characters to the proper fonts that can + display them, and how do we map the character's codes to the indices into the + font). These will replace to hackish charset-registry/charset-ccl-program stuff + we currently have, and be [a] much more powerful, [b] designed in a + window-system-independent way, [c] works with specifiers so you can control the + mapping of individual buffers, and [d] works on a character rather than charset + level, to correctly handle Unicode. One possible usage would be to declare that + all latin1 in a particular buffer to be displayed with latin2 fonts; I bet + Hrvoje would really appreciate that + + --------------------------------------------------------------------------- + + April 10, 2000 + + [info from "creation of generic macros for accessing internally formatted data"] + + Hmm, so there I just wrote a detailed design for the macros. I would be + *THRILLED* and overjoyed if you went ahead and implemented this mechanism, or + parts of it. + + I've just finished arranging for a new transcriptionist, and soon I should be + able to send off and get back my dictation of my (a) exposing streams to lisp, + and (b) allowing for proper lisp-created coding systems, which define their + reading, writing, and detecting methods in lisp. + + + BTW How's it going wrt your Unicode and decode-priority stuff? + + And ... you sent me mail asking what it was you had promised me, and listed + only one thing, which was + profiling of vm and certain other operations you found showed tremendous + slowdown with Japanese characters. The other main thing I want from you is + + -- Your priorities, as an actual Japanese user and XEmacs developer, + concerning what MULE work should be done, how it should be done, in what + order, etc. + + I'm sure there's something else, but it's been awhile since I took my sleeping + dose and my brain can barely function anymore. Just let me know how you're + going to proceed with the above macro changes. + + BTW there's some nice Perl scripts written by Martin and fixed by me to make + global-search-and-replace + much, much easier. I've attached them. The first one is a shell script that + works like + + gr foo bar *.[ch] + + and replaces foo with bar in all of the files. For each modified file, a + backup is created in the backup/ directory, which is created as necessary. + This shell script is a fairly trivial front end onto global-replace2, which is + a perl script that takes one argument (a Perl expression such as s/foo/bar/g) + and a list of files obtained by reading the stdin, and does the same global + replacement. This means that the regexp syntax used here has to be perl-style + rather than standard emacs/grep style. + + ben + + --------------------------------------------------------------------- + + + From: + Ben Wing + 12/23/1999 3:34 AM + + Subject: + Re: check process state before accessing coding_stream (fix PR#1061) + To: + "Stephen J. Turnbull" + CC: + XEmacs Developers + + + + + Thankfully, nearly all of this horridity you bring up is irrelevant. In + XEmacs, "gettext" does not refer to any standard API, but is merely a stand-in + for a translation routine (presumably written by us). We may as well call it + something else. We define our own concept of "current language". We also + allow for a function that needs a different version for each language, which + handles all cases where simple translation isn't sufficient, e.g. when you + have to pluralize some noun given to you or insert the correct form of the + definite article. No weird hacks needed. No interaction problems with other + pieces of software. + + What I wrote "awhile ago" is (unfortunately) not anywhere public currently, + but it's on my list to put it on the web site. "There you go again" is + usually not true; most of what I quote was indeed put out publicly at some + point, but I'll try to be more explicit about this in the future. + + ben + + "Stephen J. Turnbull" wrote: + + > >>>>> "Ben" == Ben Wing writes: + > + > Ben> "Stephen J. Turnbull" wrote: + > + > >> What I have in mind is not just gettext-izing everything in the + > >> XEmacs core sources. I currently believe that to be + > >> unacceptable + > + > Ben> I don't quite understand. Could you elaborate and give some + > Ben> examples? + > + > Examples? Hmm. + > + > First, there's the surface of Jan's y-or-n-p example. You have to + > coordinate the translation of the message string and the response + > prompt. This is handled by y-or-n-p itself (I see that we already do + > have gettext for Emacs Lisp, that's nice to know). + > + > Except that it's not really handled by y-or-n-p. There's no reason to + > suppose that somebody writing a Lisp package would necessarily use the + > XEmacs domain (in fact, due to the way gettext binds text domains---if + > I understand that correctly---we don't want that to be the case, + > because it means that every time a Lisp package is updated the whole + > XEmacs catalog must also be updated). So which domain gets used for + > the message string? + > + > In the current implementation, it is the domain of y-or-n-p. So + > packages with their own domain won't get y-or-n-p prompts correctly + > translated. But that means that the package should do its own + > translation. But now you're applying gettext to the same string + > twice; you just have to pray the that translator upstream doesn't + > collide with an English string that's in the XEmacs domain. (The + > gettext docs mention the similar problem of English words with + > multiple meanings that must map to different words in the target + > language; this can be disambiguated by various trickeries in forming + > the strings ... but only if you "own" them, which in the multi-domain, + > interated gettext example you do not.) AFAICT this means that you + > must never pass untranslated strings across public APIs, but this may + > or may not be reasonable, and certainly is inconvenient. + > + > Next, we have to translate the possible answer strings to match the + > language being passed by the user. This is presumably OK here, + > because it's done by y-or-n-p. But what if y-or-n-p returned a string + > rather than a boolean? Then we would need to coordinate the + > presentation of the prompt (done by y-or-n-p) and the translation of + > the possible answer strings (done by the caller). This can in fact be + > done using dgettext with the XEmacs domain, but you must know that + > y-or-n-p is in the XEmacs domain. This is not necessarily going to be + > obvious, and it might very well be that sets of related packages might + > have the same domain, so you wouldn't necessarily know which domain is + > appropriate by looking at the requires. + > + > And what happens if one domain does supply translations for a language + > and the other does not? AFAIK, gettext has no way to find out if this + > is the case. But you might very will prefer a global fallback to + > English if substantial phrases are drawn from both domains, while you + > might prefer string-by-string fallback if the main text is translated + > and only a few words are left to fallback to English. + > + > Aside from confusing users, this puts a great burden on programmers. + > Programmers need to know about the status of the domains of packages + > they use as well as the XEmacs domain; they need to program + > defensively against the possibility that some package they use will + > become gettext-ized, or the translation projects will be out of synch + > (some teams will do the calling package first, others will do the + > caller package first). + > + > I don't think anybody will use gettext in these circumstances. At + > least not after they get the first bug report that "XEmacs is stuck in + > an infinite y-or-n-p loop and I can't get out." + > + > Ben> I wrote this awhile ago: + > + > "There you go again." Not anywhere I could see it! (At least, it + > doesn't look familiar and grepping the archives doesn't turn it up.) + > + > OK, you win. Subscribe me to xemacs-review. Or whatever seems + > appropriate. + > + > -- + > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN + > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 + > _________________ _________________ _________________ _________________ + > What are those straight lines for? "XEmacs rules." + + -- + In order to save my hands, I am cutting back on my responses, especially + to XEmacs-related mail. You _will_ get a response, but please be patient. + If you need an immediate response and it is not apparent in your message, + please say so. Thanks for your understanding. + + + + -------------------------------------------------------------------- + + + From: + Ben Wing + 12/21/1999 2:22 AM + + Subject: + Re: check process state before accessing coding_stream (fix PR#1061) + To: + "Stephen J. Turnbull" + CC: + XEmacs Developers + + + + + + "Stephen J. Turnbull" wrote: + + > >>>>> "Ben" == Ben Wing writes: + > + > Ben> Implementing message translation is not that hard. + > + > What I have in mind is not just gettext-izing everything in the XEmacs + > core sources. I currently believe that to be unacceptable (see Jan's + > message for the pitfalls in I18N; it's worse for M17N). I think + > really solving this problem needs a specifier-like fallback mechanism + > (this would solve Jan's example because you could query the + > text-specifier presenting the question for the affirmative and + > negative responses, and the catalog-building mechanism would have + > checks to make sure they were properly set, perhaps a locale + > (language) argument), and gettext is just not sufficient for that. + + I don't quite understand. Could you elaborate and give some examples? + + > + > + > At a minimum, we need to implement gettext for Lisp packages. + > (Currently, gettext is only implemented for C AFAIK.) But this could + > potentially cuase more trouble than it's worth. + > + > Ben> A lot depends on priority: How important do you think this + > Ben> issue is to your average Japanese/Chinese/etc. user? + > + > Which average Japanese (etc) user? The English-skilled (relatively) + > programmer in the free software movement, or my not-at-all-competent + > undergrad students who I would love to have using an Emacs? This is a + > really important ease-of-use issue. + > + > Realistically, for Japanese, it's low priority. The Japanese team in + > the GNU Translation Project is doing very little AFAIK, so even if the + > capability were there, I doubt the message catalog would soon be done. + > + > But I think that many non-English speakers would find it very + > attractive, and for many languages there are well-organized and + > productive translation teams. I suspect that if the I18N facility + > were well-designed, many Western European languages would have full + > catalogs within a year (granted, they are the ones where it's least + > needed :-( ). + > + > Personally, I think doing it well is hard, and of little benefit to + > _current_ core XEmacs constituency. I think doing a good job, with + > catalogs, would be very attractive to many non-English-speaking + > _potential_ users. + > + > Ben> How does it compare to some of the other important Mule + > Ben> issues that Martin and I are (trying to work) on? + > + > I don't know what you guys are _trying_ to work on. Everything in the + > I18N section of "Architecting XEmacs" is red-flagged. OTOH, it's + > clear from your posts that you are overburdened, so I can't read + > priority into the fact that you've responded to specific issues in the + > past. + + I wrote this awhile ago: + + + > + > Ben> The big question is, would you be willing to help do the + > Ben> actual implementation, to "be my hands"? + > + > Sure, subject to the usual caveat that I'd need to be convinced it's + > worth doing and a secondary caveat that I am not an experienced coder. + + If you'll implement it, I'll design it. It's more a case of will on your part + than anything else. I can give you instructions sufficient enough to match + your level of expertise. + + ben + + > + > + > -- + > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN + > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 + > _________________ _________________ _________________ _________________ + > What are those straight lines for? "XEmacs rules." + + -- + In order to save my hands, I am cutting back on my responses, especially + to XEmacs-related mail. You _will_ get a response, but please be patient. + If you need an immediate response and it is not apparent in your message, + please say so. Thanks for your understanding. + + + + ----------------------------------------------------------------------------- + + Dec 20, 1999 + + + Implementing message translation is not that hard. I've already done a lot of + preliminary work in places such as `make-msgfile.lex' in lib-src/. Finishing up + the work is not that big a task; I already know exactly how it should be + done. Perhaps I'll write up detailed design instructions for this, as I'm + doing for other things. A lot depends on priority: How important do you think + this issue is to your average Japanese/Chinese/etc. user? How does it compare + to some of the other important Mule issues that Martin and I are (trying to + work) on? If I did the design document, would you be willing to do the + necessary bit of C hackery to implement the document? If the design document + is not specific enough for you, I can give you an "implementation document" + which will definitely be specific enough: i.e. I'll show you exactly where the + code needs to be modified, and how. The big question is, would you be willing + to help do the actual implementation, to "be my hands"? + + --------------------------------------------------------------------------- + + From: + Ben Wing + 12/14/1999 11:00 PM + + Subject: + Re: Mule UI disaster: displaying character tables + To: + Hrvoje Niksic + CC: + XEmacs vs Mule + + + + + What I mean is, please put my name in the header, as well as xemacs-mule. + That way I'll see it in my personal box. + + I agree that Mule has problems, but: + + Brokenness can be fixed. + Slowness can be fixed. + Limitations can be fixed. + + The design limitation you mention below, for example, is not really very + hard to change. + + Keep in mind that I pretty much rewrote Mule from scratch, and did it + *all* in 6-7 months. In comparison with that, the changes below are + pretty minor, and each could be done by a good (and able-bodied!) + programmer familiar with the Mule code in less than a week -- to the + XEmacs code, at least. The problem is, everyone who could do this work is + instead spending their time complaining about Mule problems instead of + doing things. + + I'll gladly help out anyone who wants to do Mule coding by explaining all + the details; I'll even write a "Mule internals manual", if that will + help. I can also make international phone calls -- they're cheap here in + the US due to the long distance wars. But so far no one has asked me for + help or shown any willingness to do any work on Mule. + + Perhaps people are daunted by the seeming vastness of the problems. But I + wager that if I had another 6 months to work on nothing but Mule, it would + be nearly perfect. The basic design of the XEmacs C code is good; + incremental changes, without over-much concern for compatibility, could + make huge strides in a short amount of time (as was the case the whole + time I worked on it, esp. towards the end -- it didn't even *compile* for + 4 months!). A "total rewrite" would be an incredible waste of time. + + Again, I'm completely willing to provide help, documentation, design + improvement suggestions (ala Architecting XEmacs -- which seems to have + been completely ignored, alas), etc. + + ben + + Hrvoje Niksic wrote: + + > Ben Wing writes: + > + > > I'm the one who did most of the Mule work in XEmacs, so if you have + > > any questions about the core, please address them to me directly. I + > > can probably give you a very clear and detailed answer. + > + > Thanks. I think it still makes sense to ask here, so that other + > developer have a chance to chime in. + > + > > However, I need some explanation. What's misdesigned that you're + > > complaining about? And what's the coding-system disaster? + > + > It's been spoken of a lot. Basically: + > + > * Unlike XEmacs/no-Mule, XEmacs/Mule doesn't preserve binary files in + > Latin 2 locales by default. This is annoying for users who are used + > to XEmacs/no-Mule. + > + > * XEmacs/Mule is much slower than XEmacs, and not only because of + > character/byte conversions. It seems that font lookups etc. are + > slower. + > + > * The "coding-system disaster" refers to inherent limitations of the + > coding-system model. If I understand things correctly, + > coding-systems convert streams of bytes to streams of Emchars. It + > does not appear to be possible to create a "gzip" coding system for + > handling gzipped file. Even EOL conversions look kludgish: + > + > iso-2022-8 + > iso-2022-8-dos + > iso-2022-8-mac + > iso-2022-8-unix + > iso-2022-8bit-ss2 + > iso-2022-8bit-ss2-dos + > iso-2022-8bit-ss2-mac + > iso-2022-8bit-ss2-unix + > iso-2022-int-1 + > iso-2022-int-1-dos + > iso-2022-int-1-mac + > iso-2022-int-1-unix + > + > Ideally, it should be possible to specify a stream of + > coding-systems, where only the last one converts to actual Emchars. + > + > There are more problems I don't remember right now. Many many usage + > problems become apparent when I stand and look over the shoulders of + > an XEmacs users who tries to use Mule. + + -- + In order to save my hands, I am cutting back on my responses, especially + to XEmacs-related mail. You _will_ get a response, but please be patient. + + If you need an immediate response and it is not apparent in your message, + please say so. Thanks for your understanding. + + + + ----------------------------------------------------------------------- + + + + + From: + Ben Wing + 12/14/1999 12:20 AM + + Subject: + Re: Mule UI disaster: displaying character tables + To: + "Stephen J. Turnbull" + CC: + XEmacs vs Mule + + + + + I think you should go ahead with your proposal, and assume it will get + implemented. I don't think Martin is really suggesting that API changes not + be allowed, but just that they proceed in a somewhat orderly fashion; and in + any case, I imagine I have final say in cases of Mule-related conflicts. + + ben + + "Stephen J. Turnbull" wrote: + + > >>>>> "Hrvoje" == Hrvoje Niksic writes: + > + > Hrvoje> So next I tried the "Mule" menu. That's right, boys and + > Hrvoje> girls, I've never looked at it before. + > + > For quite a while, it didn't work at all, led to crashes and other + > warm/fuzzy things. IIRC there used to be a top level menu item + > pointing to information about the current language environment but it + > got removed. + > + > Hrvoje> Wow. Seeing shift_jis, iso-2022 variants and (above all + > Hrvoje> things) big5 makes me really warm and fuzzy. + > + > We've been through this recently---you were there. We know what to do + > about it, basically (Ben liked my proposal, and it would fix this + > silliness as well as the binary file breakage). But given that Ben + > and Martin seem to have different ideas about where to go with Mule + > (Ben seemed to be supporting API and implementation revisions, Martin + > evidently wants to keep the current Mule), working on that proposal is + > possibly a waste of time. I've got other stuff on my plate and I'll + > get back to it one of these days (not tomorrow but sooner than Real + > Soon Now). + > + > Hrvoje> The items it presents (leading to further submenus) are: + > + > Hrvoje> 94 character set + > Hrvoje> 94 x 94 character set + > Hrvoje> 96 character set + > + > This _is_ bad UI, now that you point it out. But it is quite natural + > for a coding system lawyer (as all Japanese users have to be), I never + > noticed it before. Easy enough to fix ("raise my karma"). + > + > Hrvoje> But I do bear some Mule scars, so I happily select "96 + > Hrvoje> character sets", then ISO8859-2. And I get this: + > + > [Table omitted] + > + > Hrvoje> So me wonders: what the hell is this? + > + > Huh? That is the standard table that you see over and over again in + > references. I'll believe you if you say you've never seen one before, + > but every Japanese users' manual has dozens of pages of those, using + > exactly that format. + > + > The presentation in the range 00--7F is not unreasonable for Latin 2; + > ISO-8859 is a version of ISO-2022, so the high bit should not be + > interpreted as "+ x80" (technically speaking), it should be + > interpreted as a character set shift. + > + > Of course, this doesn't make sense to anybody but a character set + > lawyer, and so should be changed. Especially since the header refers + > to ISO-8859-2 which everybody these days thinks of as _one, 8-bit_ + > character set, not two 7-bit ones. + > + > As for the "Japanese" in the table, that's just a really stupid + > "optimization": those happen to be line-drawing characters available + > in JIS X 0208, to make pretty borders. Substitute "-", "+", and "|" + > in appropriate places to make ugly but portable borders. + > + > Hrvoje> Mule is just broken. Warn your friends. + > + > Hrvoje is on the rampage again. Warn your friends ;-) + > + > -- + > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN + > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 + > _________________ _________________ _________________ _________________ + > What are those straight lines for? "XEmacs rules." + + -- + In order to save my hands, I am cutting back on my responses, especially + to XEmacs-related mail. You _will_ get a response, but please be patient. + If you need an immediate response and it is not apparent in your message, + please say so. Thanks for your understanding. + + + + --------------------------------------------------------------------------- + + From: + Ben Wing + 12/14/1999 10:28 PM + + Subject: + Re: Autodetect proposal; specifer questions/suggestions + To: + "Stephen J. Turnbull" + + + + + I've always thought the specifier API is too complicated (and too + "write-only"), but I went back at one point well after I designed it and I + couldn't figure out an obvious way to simplify it that still kept reasonable + functionality. Perhaps that's what Custom did, and why it turned out bad. + + Inefficiency is a stupid reason not to use them. They seem efficient enough + for redisplay. Changing them might be inefficient, but Emacs Lisp is in + general, right? + + Can you propose an API or functionality change that will make them more used? + + + + "Stephen J. Turnbull" wrote: + + > >>>>> "Ben" == Ben Wing writes: + > + > Ben> I think you should go ahead with your proposal, and assume it + > Ben> will get implemented. + > + > OK. "yas baas" ;-) + > + > On something totally different. I'm really bothered by the fact that + > specifiers are so little used (eg, Custom reimplements them badly), + > and the fact that every package seems to define its own set of faces + > (or whatever), rather than use the specifier mechanism to inherit from + > existing ones, or add new specifications to existing ones. API problem? + > + > Also, faces (maybe specifiers in general?) should have an autoload + > mechanism, and a `-faces.el' (or `-specifiers.el') + > convention. There are a number of faces in (eg) Custom that I like to + > use, but I have to load Custom to get them. And Custom should be able + > to somehow see all the faces in various packages available, even when + > they are not loaded. + > + > I've seen claims that specifiers aren't very efficient. + > + > Opinions? + > + > -- + > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN + > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 + > _________________ _________________ _________________ _________________ + > What are those straight lines for? "XEmacs rules." + + -- + In order to save my hands, I am cutting back on my responses, especially + to XEmacs-related mail. You _will_ get a response, but please be patient. + If you need an immediate response and it is not apparent in your message, + please say so. Thanks for your understanding. + + + ----------------------------------------------------------------------------- + From: + Ben Wing + 11/18/1999 9:02 PM + + Subject: + Re: Char-related crashes (hopefully) fixed + To: + "Stephen J. Turnbull" + CC: + XEmacs Beta List + + + + + OK, in summation: + + 1. C-q is a user-level function and should do whatever makes the most sense. + 2. int-char is a low-level primitive and should never depend on high-level + settings like language environment. + 3. Everything you can do with int-char can and should be done with make-char + -- representation-independent, much less likelihood of bugs, etc. Therefore + int-char should be removed. + 4. Note that CLTL2 also removes int-char. + 5. Your statement + + > In one-byte buffers (either Olivier's 1/2/4 extension or `xemacs -font + > *-iso8859-2') it implicitly will have dependence whatever you say. + + is confusing internal and external representations. + + ben + + "Stephen J. Turnbull" wrote: + + > Can somebody give a bunch of examples where using integers as + > characters is useful? For that matter, where they are actually used? + > Ben said "backward compatibility," but I haven't seen this used, and I + > don't really know how to grep for it. I have grepped for int-char, + > int-to-char, char-int, and char-to-int and they're pretty rare in the + > core and package code (2/3 of it) that I have. + > + > The only one that I ever use is the C-q hack for inserting characters + > by code value at the keyboard, and that could arguably (and in + > Japanese invariably is) delegated to an input method which would know + > about language environment (and return a true character). + > + > For iterating over a character set in "natural" order, only ASCII + > satisfies the requirement of having one, and even that's shaky. AFAIK + > the Swedes and the Norwegians, or is it the Danes, disagree on + > ordering the _letters_ in ISO-8859-1 character set. This really + > should be table-driven, and will have to be for everything except + > ASCII and ISO-8859-1 if we go to a Unicode internal representation. + > + > We already have primitives for efficient case conversion and the like. + > + > The only example I can think of offhand where you would really really + > want the facility is to iterate over a code space where you don't know + > which points are legal characters. Eg, to print out tables of fonts. + > Pretty specialized. And this can be done through make-char, anyway. + > + > According to CLtL1, the main portable use for char-int is for hashing. + > But that doesn't square with the kind of usage we've been talking + > about (in loops and the like). + > + > What else am I missing? + > + > Ben's desiderata have some problems. + > + > >>>>> "Ben" == Ben Wing writes: + > + > Ben> Either int-char should be the mirror opposite of char-int + > Ben> (i.e. accept all legal char integers), or it should be + > Ben> removed entirely. + > + > OK. I agree with this. + > + > Ben> int-char should *never* have any dependence on the language + > Ben> environment. + > + > In one-byte buffers (either Olivier's 1/2/4 extension or `xemacs -font + > *-iso8859-2') it implicitly will have dependence whatever you say. + > Even without Mule, people can always use external encoders to change + > raw ISO-8859-2 to ISO-2022 (not that anybody sane ever would, OK, + > Hrvoje?). Then the two files will be interpreted differently in a + > Latin-1 locale Mule; the ISO-8859-2 file will be recognized as + > ISO-8859-1, and the ISO-2022 file will be internally interpreted as + > ISO-8859-2. + > + > The point is that people normally assume that int-char should accept + > their "natural" integer to character map. For Americans, that's + > ASCII, for Germans, that's ISO-8859-1, for Croatians, that's + > ISO-8859-2. And it works "correctly" in a no-mule XEmacs with `-font + > *-iso8859-2'! Japanese usually use ku-ten or JIS, and there's a + > "natural" map from byte-sized integer pairs to shorts, but it's full + > of holes. So language environments don't agree on what a legal char + > integer is, and where they do (eg, ISO-8859-1 and ISO-8859-2), they + > don't agree on the map. To satisfy your dictum (with which I agree, + > but I take to mean we should get rid of these functions) we can take + > the intersection where they agree + > + > ==> legal char integers == ASCII + > + > which is what I prefer, or pick something arbitrary and efficient + > + > ==> char-int returns the internal representation + > + > which I really hate, or something else. Suggestions? + > + > Ben> I don't think C-q should either. If Hrvoje wants to insert + > Ben> Latin-2 characters by number, then make C-u C-q work so that + > Ben> it also prompts for a character set, with a default chosen + > Ben> from the language environment. + > + > And restrict this to ASCII? Or assume Latin-1 in GR if there is no + > prefix argument? + > + > This is a useful feature. C-q currently inserts Latin-2 characters + > for Hrvoje in no-mule XEmacs (stretching the point only a little); I + > think it should continue to do so in Mule. This really is an input + > method issue, not a keyboard issue. In XEmacs, inserting an integer + > into a buffer has no meaning. Users insert characters. So this is a + > completely different issue from the programming API, and should not be + > considered analogous. + > + > Maybe we could have C-q insert according to the Unicode standard, and + > treat C-u C-q as part of the input method. But I think most users + > would prefer to have C-q insert according to their locale-standard + > tables, and select Unicode explicitly using the C-u C-q idiom. In + > fact (again this points to the input method idea), Japanese users + > would probably like to have the alternatives of using kuten (pairs + > from 1--94 x 1--94) or JIS (pairs from 0x21--0x7E x 0x21--0x7E) as + > options since both indexing systems are common in tables. + > + > -- + > University of Tsukuba Tennodai 1-1-1 Tsukuba 305-8573 JAPAN + > Institute of Policy and Planning Sciences Tel/fax: +81 (298) 53-5091 + > __________________________________________________________________________ + > __________________________________________________________________________ + > What are those two straight lines for? "Free software rules." + + -- + ben + + -- + In order to save my hands, I am cutting back on my responses, especially to + XEmacs-related mail. You + _will_ get a response, but please be patient. If you need an immediate + response and it’s not apparent in + your message, please say so. Thanks for your understanding. + + + + ----------------------------------------------------------------------------- + + From: + Ben Wing + 11/16/1999 11:03 PM + + Subject: + Re: Char-related crashes (hopefully) fixed + To: + Yoshiki Hayashi + CC: + Hrvoje Niksic , + XEmacs Beta List + + + + + Either int-char should be the mirror opposite of char-int (i.e. accept all + legal char integers), or it should be removed entirely. + + int-char should *never* have any dependence on the language environment. + + I don't think C-q should either. If Hrvoje wants to insert Latin-2 + characters by number, then make C-u C-q work so that it also prompts for a + character set, with a default chosen from the language environment. + + ben + + Yoshiki Hayashi wrote: + + > Hrvoje Niksic writes: + > + > > As Ben said, now that we've fixed the actual bugs, we can think about + > > changing the behaviour for int-char conversions for 21.2. + > + > Following are proposed which integers should be accepted + > where characters are expected: + > + > 1) Don't allow anything + > 2) Accept 0-127 + > 3) Accept 0-256 + > 4) Accept everything + > + > Other things proposed are: + > + > a) When doing C-q, treat 128-256 as Latin-2 in Latin 2 + > language environment. + > + > So far, most of the proposal is intended to apply to every + > int-char conversions, I'd like to make some functions to + > accept. + > + > My plan is: + > Accept only 0-256 in every place except int-to-char. + > int-to-char accepts every valid integers. + > Make new function which does int-to-char conversion + > correctly according to the language environment. + > + > This way, most of the code which does (insert (1+ ?a)) or + > something continues working. Now internal representation is + > changed a little bit, so disabling > 256 characters will + > warn those who are dealing with internal representation + > directly, which is bad. Still, you can do + > (let ((i 1442)) + > (while (i < 2000) + > (insert (int-to-char i)) + > (setq i (+1 i)))) + > to achieve old behaviour. + > + > For C-q, I'm not for changing it's original definition, + > since it might confuse people who are expecting Latin-1 in + > other language environment and typing just 1 integer doesn't + > make sense for multibyte world. It's cleaner to make new + > function, which does make-char according to the charset of + > language-info-alist so that people who use that often can + > bind it to C-q or some other keys. + > + > -- + > Yoshiki Hayashi + + -- + ben + + -- + In order to save my hands, I am cutting back on my responses, especially to + XEmacs-related mail. You + _will_ get a response, but please be patient. If you need an immediate + response and it’s not apparent in + your message, please say so. Thanks for your understanding. + +  File: internals.info, Node: Discussion -- Instantiators and Generic Property Accessors, Next: Discussion -- Switching to C++, Prev: Discussion -- Multilingual Issues, Up: Future Work Discussion 41.5 Discussion - Instantiators and Generic Property Accessors *************** *** 2001,2009 **** (line 6) * allocation, introduction to: Introduction to Allocation. (line 6) ! * allocation, low-level <1>: Low-Level Allocation. (line 6) ! * allocation, low-level: Low-level allocation. (line 6) * Amdahl Corporation: XEmacs. (line 6) * Andreessen, Marc: XEmacs. (line 6) --- 4215,4223 ---- (line 6) * allocation, introduction to: Introduction to Allocation. (line 6) ! * allocation, low-level <1>: Low-level allocation. (line 6) ! * allocation, low-level: Low-Level Allocation. (line 6) * Amdahl Corporation: XEmacs. (line 6) * Andreessen, Marc: XEmacs. (line 6) *************** *** 2038,2045 **** * basic internal-format APIs: Basic internal-format APIs. (line 6) * basic types: Basic Types. (line 6) ! * Baur, Steve <1>: XEmacs. (line 6) ! * Baur, Steve: GNU Emacs 19. (line 71) * Benson, Eric: Lucid Emacs. (line 28) * better initialization file scheme, future work: Future Work -- Better Initialization File Scheme. (line 6) --- 4252,4259 ---- * basic internal-format APIs: Basic internal-format APIs. (line 6) * basic types: Basic Types. (line 6) ! * Baur, Steve <1>: GNU Emacs 19. (line 71) ! * Baur, Steve: XEmacs. (line 51) * Benson, Eric: Lucid Emacs. (line 28) * better initialization file scheme, future work: Future Work -- Better Initialization File Scheme. (line 6) *************** *** 2067,2073 **** (line 6) * bridge, playing: XEmacs from the Outside. (line 34) ! * Buchholz, Martin: XEmacs. (line 51) * buffer lists: Buffer Lists. (line 6) * buffer object, the: The Buffer Object. (line 6) * buffer positions <1>: Byte/Character Types; Buffer Positions; Other Typedefs. --- 4281,4287 ---- (line 6) * bridge, playing: XEmacs from the Outside. (line 34) ! * Buchholz, Martin: XEmacs. (line 6) * buffer lists: Buffer Lists. (line 6) * buffer object, the: The Buffer Object. (line 6) * buffer positions <1>: Byte/Character Types; Buffer Positions; Other Typedefs. *************** *** 2326,2333 **** (line 6) * Energize: Lucid Emacs. (line 6) * Epoch <1>: Lucid Emacs. (line 6) ! * Epoch <2>: XEmacs. (line 6) ! * Epoch: Epoch. (line 6) * error checking: Debugging and Testing. (line 15) * error trapping: Error Trapping. (line 6) --- 4540,4547 ---- (line 6) * Energize: Lucid Emacs. (line 6) * Epoch <1>: Lucid Emacs. (line 6) ! * Epoch <2>: Epoch. (line 6) ! * Epoch: XEmacs. (line 6) * error checking: Debugging and Testing. (line 15) * error trapping: Error Trapping. (line 6) *************** *** 2369,2377 **** (line 6) * extent mathematics: Mathematics of Extent Ordering. (line 6) ! * extent ordering <1>: Mathematics of Extent Ordering. (line 6) - * extent ordering: Extent Ordering. (line 6) * extents: Extents. (line 6) * extents, display order: Mathematics of Extent Ordering. (line 6) --- 4583,4591 ---- (line 6) * extent mathematics: Mathematics of Extent Ordering. (line 6) ! * extent ordering <1>: Extent Ordering. (line 6) ! * extent ordering: Mathematics of Extent Ordering. (line 6) * extents: Extents. (line 6) * extents, display order: Mathematics of Extent Ordering. (line 6) *************** *** 2457,2464 **** * frob blocks, allocation from: Allocation from Frob Blocks. (line 6) * FSF: A History of Emacs. (line 6) ! * FSF Emacs <1>: GNU Emacs 20. (line 6) ! * FSF Emacs: GNU Emacs 19. (line 6) * function, compiled: Compiled Function. (line 6) * future work: Future Work. (line 6) * future work, abstracted mouse pointer interface: Future Work -- Abstracted Mouse Pointer Interface. --- 4671,4678 ---- * frob blocks, allocation from: Allocation from Frob Blocks. (line 6) * FSF: A History of Emacs. (line 6) ! * FSF Emacs <1>: GNU Emacs 19. (line 6) ! * FSF Emacs: GNU Emacs 20. (line 6) * function, compiled: Compiled Function. (line 6) * future work: Future Work. (line 6) * future work, abstracted mouse pointer interface: Future Work -- Abstracted Mouse Pointer Interface. *************** *** 2846,2851 **** --- 5060,5067 ---- * Mule encodings: Encodings. (line 6) * Mule encodings, internal: Internal Mule Encodings. (line 6) + * Mule Merge, The Great: The Great Mule Merge of March 2002. + (line 6) * MULE merged XEmacs appears: XEmacs. (line 41) * Mule, coding for: Coding for Mule. (line 6) * Mule-aware code, an example of: An Example of Mule-Aware Code. *************** *** 2941,2950 **** * querying fonts: Modern Font Support -- fontconfig. (line 6) * queues, event: Event Queues. (line 6) - * QUIT checking: Control-G (Quit) Checking. - (line 6) * quit checking: Control-G (Quit) Checking. (line 6) * radio buttons, checkboxes and: Checkboxes and Radio Buttons. (line 6) * random other windows i18n docs: Random other Windows I18N docs. --- 5157,5166 ---- * querying fonts: Modern Font Support -- fontconfig. (line 6) * queues, event: Event Queues. (line 6) * quit checking: Control-G (Quit) Checking. (line 6) + * QUIT checking: Control-G (Quit) Checking. + (line 6) * radio buttons, checkboxes and: Checkboxes and Radio Buttons. (line 6) * random other windows i18n docs: Random other Windows I18N docs. *************** *** 3081,3086 **** --- 5297,5304 ---- (line 6) * the golden rules of writing unicode-safe code: The golden rules of writing Unicode-safe code. (line 6) + * The Great Mule Merge: The Great Mule Merge of March 2002. + (line 6) * Thompson, Chuck: XEmacs. (line 6) * throw, catch and: Catch and Throw. (line 6) * toolbar interface changes, future work: Future Work -- Toolbar Interface Changes. *************** *** 3089,3095 **** (line 6) * TrueType fonts: Better Rendering Support -- Modern Font Support. (line 6) ! * Turnbull, Stephen: XEmacs. (line 71) * type renaming, integral: Great Integral Type Renaming. (line 6) * type renaming, text/char: Text/Char Type Renaming. --- 5307,5313 ---- (line 6) * TrueType fonts: Better Rendering Support -- Modern Font Support. (line 6) ! * Turnbull, Stephen: XEmacs. (line 57) * type renaming, integral: Great Integral Type Renaming. (line 6) * type renaming, text/char: Text/Char Type Renaming. *************** *** 3160,3166 **** (line 6) * Windows-related multilingual issues: Microsoft Windows-Related Multilingual Issues. (line 6) ! * Wing, Ben: XEmacs. (line 71) * working with lisp objects: Working with Lisp Objects. (line 6) * working with the various representations: Working With the Various Representations. --- 5378,5384 ---- (line 6) * Windows-related multilingual issues: Microsoft Windows-Related Multilingual Issues. (line 6) ! * Wing, Ben: XEmacs. (line 21) * working with lisp objects: Working with Lisp Objects. (line 6) * working with the various representations: Working With the Various Representations. diff -c 'xemacs-21.5.25/info/xemacs.info' 'xemacs-21.5.26/info/xemacs.info' Index: ./info/xemacs.info *** ./info/xemacs.info Sun Feb 26 22:31:26 2006 --- ./info/xemacs.info Sat Apr 1 04:05:30 2006 *************** *** 34,40 **** xemacs.info-1: 1350 xemacs.info-2: 301245 xemacs.info-3: 599682 ! xemacs.info-4: 898895  Tag Table: (Indirect) --- 34,40 ---- xemacs.info-1: 1350 xemacs.info-2: 301245 xemacs.info-3: 599682 ! xemacs.info-4: 898952  Tag Table: (Indirect) *************** *** 299,436 **** Node: Lisp Debug638587 Node: Lisp Interaction644023 Node: External Lisp645385 ! Node: Packages647467 ! Node: Package Terminology648475 ! Node: Installing Packages650129 ! Node: Automatically652871 ! Node: Manually657542 ! Node: Sumo659024 ! Node: Which Packages659925 ! Node: Removing Packages660733 ! Node: Building Packages661417 ! Node: Local.rules File662553 ! Node: Available Packages663049 ! Node: Abbrevs671081 ! Node: Defining Abbrevs673283 ! Node: Expanding Abbrevs675740 ! Node: Editing Abbrevs678450 ! Node: Saving Abbrevs680333 ! Node: Dynamic Abbrevs682295 ! Node: Picture683604 ! Node: Basic Picture686040 ! Node: Insert in Picture688332 ! Node: Tabs in Picture689761 ! Node: Rectangles in Picture691289 ! Node: Sending Mail693204 ! Node: Mail Format695394 ! Node: Mail Headers696751 ! Node: Mail Mode703166 ! Node: Reading Mail706786 ! Node: Calendar/Diary708494 ! Node: Calendar Motion710175 ! Node: Calendar Unit Motion711069 ! Node: Move to Beginning or End713407 ! Node: Specified Dates714565 ! Node: Scroll Calendar715468 ! Node: Mark and Region717271 ! Node: General Calendar719188 ! Node: LaTeX Calendar720810 ! Node: Holidays722831 ! Node: Sunrise/Sunset725944 ! Node: Lunar Phases728994 ! Node: Other Calendars730390 ! Node: Calendar Systems731888 ! Node: To Other Calendar735006 ! Node: From Other Calendar737026 ! Node: Mayan Calendar739337 ! Node: Diary742543 ! Node: Diary Commands744303 ! Node: Format of Diary File747637 ! Node: Date Formats750518 ! Node: Adding to Diary753103 ! Node: Special Diary Entries754745 ! Node: Calendar Customization760095 ! Node: Calendar Customizing760968 ! Node: Holiday Customizing764218 ! Node: Date Display Format770719 ! Node: Time Display Format771692 ! Node: Daylight Savings772845 ! Node: Diary Customizing776048 ! Node: Hebrew/Islamic Entries780684 ! Node: Fancy Diary Display784039 ! Node: Included Diary Files785970 ! Node: Sexp Diary Entries786966 ! Node: Appt Customizing792073 ! Node: Sorting793136 ! Node: Shell797949 ! Node: Single Shell799249 ! Node: Interactive Shell800875 ! Node: Shell Mode804651 ! Node: Terminal emulator807153 ! Node: Term Mode809473 ! Node: Paging in Term810398 ! Node: Narrowing811207 ! Node: Hardcopy813163 ! Node: Recursive Edit814142 ! Node: Dissociated Press817138 ! Node: CONX819710 ! Node: Amusements820743 ! Node: Emulation821232 ! Node: Customization823100 ! Node: Minor Modes825142 ! Node: Behaviors827938 ! Node: Variables829031 ! Node: Examining830992 ! Node: Easy Customization832464 ! Node: Customization Groups833495 ! Node: Changing an Option836425 ! Node: Face Customization842710 ! Node: Specific Customization844619 ! Node: Edit Options847241 ! Node: Locals848839 ! Node: File Variables852032 ! Node: Keyboard Macros856784 ! Node: Basic Kbd Macro858962 ! Node: Save Kbd Macro860904 ! Node: Kbd Macro Query862573 ! Node: Key Bindings864526 ! Node: Keymaps865409 ! Node: Rebinding869270 ! Node: Interactive Rebinding869981 ! Node: Programmatic Rebinding872188 ! Node: Key Bindings Using Strings874990 ! Node: Disabling876632 ! Node: Syntax878422 ! Node: Syntax Entry879310 ! Node: Syntax Change883493 ! Node: Init File885673 ! Node: Init Syntax887144 ! Node: Init Examples889506 ! Node: Terminal Init893707 ! Node: Audible Bell895455 ! Node: Faces898895 ! Node: Frame Components907542 ! Node: X Resources907996 ! Node: Geometry Resources910392 ! Node: Iconic Resources912874 ! Node: Resource List913361 ! Node: Face Resources919883 ! Node: Widgets923587 ! Node: Menubar Resources924540 ! Node: Quitting926070 ! Node: Lossage929060 ! Node: Stuck Recursive929713 ! Node: Screen Garbled930432 ! Node: Text Garbled931579 ! Node: Unasked-for Search932231 ! Node: Emergency Escape933029 ! Node: Total Frustration934821 ! Node: Bugs935465 ! Node: Glossary945061 ! Node: Manifesto976715 ! Node: Key Index1000170 ! Node: Command Index1036642 ! Node: Variable Index1099860 ! Node: Concept Index1122798  End Tag Table --- 299,436 ---- Node: Lisp Debug638587 Node: Lisp Interaction644023 Node: External Lisp645385 ! Node: Packages647524 ! Node: Package Terminology648532 ! Node: Installing Packages650186 ! Node: Automatically652928 ! Node: Manually657599 ! Node: Sumo659081 ! Node: Which Packages659982 ! Node: Removing Packages660790 ! Node: Building Packages661474 ! Node: Local.rules File662610 ! Node: Available Packages663106 ! Node: Abbrevs671138 ! Node: Defining Abbrevs673340 ! Node: Expanding Abbrevs675797 ! Node: Editing Abbrevs678507 ! Node: Saving Abbrevs680390 ! Node: Dynamic Abbrevs682352 ! Node: Picture683661 ! Node: Basic Picture686097 ! Node: Insert in Picture688389 ! Node: Tabs in Picture689818 ! Node: Rectangles in Picture691346 ! Node: Sending Mail693261 ! Node: Mail Format695451 ! Node: Mail Headers696808 ! Node: Mail Mode703223 ! Node: Reading Mail706843 ! Node: Calendar/Diary708551 ! Node: Calendar Motion710232 ! Node: Calendar Unit Motion711126 ! Node: Move to Beginning or End713464 ! Node: Specified Dates714622 ! Node: Scroll Calendar715525 ! Node: Mark and Region717328 ! Node: General Calendar719245 ! Node: LaTeX Calendar720867 ! Node: Holidays722888 ! Node: Sunrise/Sunset726001 ! Node: Lunar Phases729051 ! Node: Other Calendars730447 ! Node: Calendar Systems731945 ! Node: To Other Calendar735063 ! Node: From Other Calendar737083 ! Node: Mayan Calendar739394 ! Node: Diary742600 ! Node: Diary Commands744360 ! Node: Format of Diary File747694 ! Node: Date Formats750575 ! Node: Adding to Diary753160 ! Node: Special Diary Entries754802 ! Node: Calendar Customization760152 ! Node: Calendar Customizing761025 ! Node: Holiday Customizing764275 ! Node: Date Display Format770776 ! Node: Time Display Format771749 ! Node: Daylight Savings772902 ! Node: Diary Customizing776105 ! Node: Hebrew/Islamic Entries780741 ! Node: Fancy Diary Display784096 ! Node: Included Diary Files786027 ! Node: Sexp Diary Entries787023 ! Node: Appt Customizing792130 ! Node: Sorting793193 ! Node: Shell798006 ! Node: Single Shell799306 ! Node: Interactive Shell800932 ! Node: Shell Mode804708 ! Node: Terminal emulator807210 ! Node: Term Mode809530 ! Node: Paging in Term810455 ! Node: Narrowing811264 ! Node: Hardcopy813220 ! Node: Recursive Edit814199 ! Node: Dissociated Press817195 ! Node: CONX819767 ! Node: Amusements820800 ! Node: Emulation821289 ! Node: Customization823157 ! Node: Minor Modes825199 ! Node: Behaviors827995 ! Node: Variables829088 ! Node: Examining831049 ! Node: Easy Customization832521 ! Node: Customization Groups833552 ! Node: Changing an Option836482 ! Node: Face Customization842767 ! Node: Specific Customization844676 ! Node: Edit Options847298 ! Node: Locals848896 ! Node: File Variables852089 ! Node: Keyboard Macros856841 ! Node: Basic Kbd Macro859019 ! Node: Save Kbd Macro860961 ! Node: Kbd Macro Query862630 ! Node: Key Bindings864583 ! Node: Keymaps865466 ! Node: Rebinding869327 ! Node: Interactive Rebinding870038 ! Node: Programmatic Rebinding872245 ! Node: Key Bindings Using Strings875047 ! Node: Disabling876689 ! Node: Syntax878479 ! Node: Syntax Entry879367 ! Node: Syntax Change883550 ! Node: Init File885730 ! Node: Init Syntax887201 ! Node: Init Examples889563 ! Node: Terminal Init893764 ! Node: Audible Bell895512 ! Node: Faces898952 ! Node: Frame Components907599 ! Node: X Resources908053 ! Node: Geometry Resources910449 ! Node: Iconic Resources912931 ! Node: Resource List913418 ! Node: Face Resources919940 ! Node: Widgets923644 ! Node: Menubar Resources924597 ! Node: Quitting926127 ! Node: Lossage929117 ! Node: Stuck Recursive929770 ! Node: Screen Garbled930489 ! Node: Text Garbled931636 ! Node: Unasked-for Search932288 ! Node: Emergency Escape933086 ! Node: Total Frustration934878 ! Node: Bugs935522 ! Node: Glossary945118 ! Node: Manifesto976772 ! Node: Key Index1000227 ! Node: Command Index1036699 ! Node: Variable Index1099917 ! Node: Concept Index1122855  End Tag Table diff -c 'xemacs-21.5.25/info/xemacs.info-3' 'xemacs-21.5.26/info/xemacs.info-3' Index: ./info/xemacs.info-3 *** ./info/xemacs.info-3 Sun Feb 26 22:31:26 2006 --- ./info/xemacs.info-3 Sat Apr 1 04:05:30 2006 *************** *** 1096,1110 **** directly from the Emacs buffers in which you edit the Lisp programs to the inferior Lisp process. ! To run an inferior Lisp process, type `M-x run-lisp'. This runs the ! program named `lisp', the same program you would run by typing `lisp' ! as a shell command, with both input and output going through an Emacs ! buffer named `*lisp*'. In other words, any "terminal output" from Lisp ! will go into the buffer, advancing point, and any "terminal input" for ! Lisp comes from text in the buffer. To give input to Lisp, go to the ! end of the buffer and type the input, terminated by . The ! `*lisp*' buffer is in Inferior Lisp mode, which has all the special ! characteristics of Lisp mode and Shell mode (*note Shell Mode::). Use Lisp mode to run the source files of programs in external Lisps. You can select this mode with `M-x lisp-mode'. It is used automatically --- 1096,1111 ---- directly from the Emacs buffers in which you edit the Lisp programs to the inferior Lisp process. ! To run an inferior Lisp process, type `M-x run-lisp'. (You need to ! the `os-utils' package installed for this.) This runs the program named ! `lisp', the same program you would run by typing `lisp' as a shell ! command, with both input and output going through an Emacs buffer named ! `*lisp*'. In other words, any "terminal output" from Lisp will go into ! the buffer, advancing point, and any "terminal input" for Lisp comes ! from text in the buffer. To give input to Lisp, go to the end of the ! buffer and type the input, terminated by . The `*lisp*' buffer is ! in Inferior Lisp mode, which has all the special characteristics of ! Lisp mode and Shell mode (*note Shell Mode::). Use Lisp mode to run the source files of programs in external Lisps. You can select this mode with `M-x lisp-mode'. It is used automatically diff -c 'xemacs-21.5.25/info/xemacs.info-4' 'xemacs-21.5.26/info/xemacs.info-4' Index: ./info/xemacs.info-4 *** ./info/xemacs.info-4 Sun Feb 26 22:31:26 2006 --- ./info/xemacs.info-4 Sat Apr 1 04:05:30 2006 *************** *** 2519,2525 **** * C-M-v <1>: Other Window. (line 40) * C-M-v: Minibuffer Edit. (line 33) * C-M-w: Appending Kills. (line 33) ! * C-M-x <1>: External Lisp. (line 27) * C-M-x: Lisp Eval. (line 52) * C-n: Moving Point. (line 15) * C-n (Calendar mode): Calendar Unit Motion. --- 2519,2525 ---- * C-M-v <1>: Other Window. (line 40) * C-M-v: Minibuffer Edit. (line 33) * C-M-w: Appending Kills. (line 33) ! * C-M-x <1>: External Lisp. (line 28) * C-M-x: Lisp Eval. (line 52) * C-n: Moving Point. (line 15) * C-n (Calendar mode): Calendar Unit Motion. *************** *** 3312,3319 **** * lisp-complete-symbol: Lisp Completion. (line 9) * lisp-indent-line: Basic Indent. (line 12) * lisp-interaction-mode: Lisp Interaction. (line 22) ! * lisp-mode: External Lisp. (line 22) ! * lisp-send-defun: External Lisp. (line 27) * list-abbrevs: Editing Abbrevs. (line 12) * list-bookmarks: Bookmarks. (line 25) * list-buffers: List Buffers. (line 9) --- 3312,3319 ---- * lisp-complete-symbol: Lisp Completion. (line 9) * lisp-indent-line: Basic Indent. (line 12) * lisp-interaction-mode: Lisp Interaction. (line 22) ! * lisp-mode: External Lisp. (line 23) ! * lisp-send-defun: External Lisp. (line 28) * list-abbrevs: Editing Abbrevs. (line 12) * list-bookmarks: Bookmarks. (line 25) * list-buffers: List Buffers. (line 9) diff -c 'xemacs-21.5.25/lib-src/ChangeLog' 'xemacs-21.5.26/lib-src/ChangeLog' Index: ./lib-src/ChangeLog *** ./lib-src/ChangeLog Sun Feb 26 22:14:12 2006 --- ./lib-src/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,7 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 414,420 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 418,425 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/lisp/ChangeLog' 'xemacs-21.5.26/lisp/ChangeLog' Index: ./lisp/ChangeLog *** ./lisp/ChangeLog Sun Feb 26 22:14:12 2006 --- ./lisp/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,58 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + + 2006-03-31 Marcus Crestani + + * diagnose.el (show-mc-alloc-memory-usage): Rename buffer to + "mc-alloc memory usage" to avoid name clash with + show-memory-usage. + + 2006-03-26 Marcus Crestani + + * diagnose.el (show-gc-stats): Adjust format string, remove + explicitly-freed statistics (the need to explicitly free went away + with the asynchronous finalization patch). + + 2006-03-20 Malcolm Purvis + + * next-error.el: Rename functions that clash with the next-error + family in compile.el + * occur.el (occur-next-error): Use new names + * occur.el (multi-occur): Fix compiler warnings. + + 2006-03-15 Jerry James + + * newcomment.el (uncomment-region): Remove old code that breaks + uncomment-region on C files. Thanks to Christian Podlasly for the + report. + + 2006-03-15 Jerry James + + * register.el (describe-register-1): Use set-text-properties + instead of the nonexistent remove-list-of-text-properties. + + 2006-03-14 Jerry James + + * wid-edit.el (widget-move-and-invoke): New function, used by Gnus. + + 2006-02-26 Vin Shelton + + * setup-paths.el (paths-emacs-data-root-p): Add search for package + root. + (paths-find-invocation-roots): Add root-p parameter to test + plausibility of the roots. + + 2006-03-12 Marcus Crestani + + * diagnose.el (show-memory-usage): Fix regexp. + + 2006-02-26 Mike Sperber + + * lisp-mode.el (lisp-send-defun): Remove this function; the + definition here didn't do anything---once upon a time, it may have + gotten overwritten by some code that has evaporated since then. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 4975,4981 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 5030,5037 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/lisp/auto-autoloads.el' 'xemacs-21.5.26/lisp/auto-autoloads.el' Index: ./lisp/auto-autoloads.el *** ./lisp/auto-autoloads.el Sun Feb 26 22:25:35 2006 --- ./lisp/auto-autoloads.el Sat Apr 1 03:58:01 2006 *************** *** 2068,2077 **** ;;;*** ! ;;;### (autoloads (next-error) "next-error" "lisp/next-error.el") ! (autoload 'next-error "next-error" "\ ! Visit next `next-error' message and corresponding source code. If all the error messages parsed so far have been processed already, the message buffer is checked for new ones. --- 2068,2077 ---- ;;;*** ! ;;;### (autoloads (next-error-framework-next-error) "next-error" "lisp/next-error.el") ! (autoload 'next-error-framework-next-error "next-error" "\ ! Visit next `next-error-framework-next-error' message and corresponding source code. If all the error messages parsed so far have been processed already, the message buffer is checked for new ones. *************** *** 2083,2099 **** The RESET argument specifies that we should restart from the beginning. ! \\[next-error] normally uses the most recently started compilation, grep, or occur buffer. It can also operate on any buffer with output from the \\[compile], \\[grep] commands, or, more generally, on any buffer in Compilation mode or with Compilation Minor mode enabled, or any buffer in which `next-error-function' is bound to an appropriate function. To specify use of a particular buffer for error messages, type ! \\[next-error] in that buffer when it is the only one displayed in the current frame. ! Once \\[next-error] has chosen the buffer for error messages, it runs `next-error-hook' with `run-hooks', and stays with that buffer until you use it in some other buffer which uses Compilation mode or Compilation Minor mode. --- 2083,2099 ---- The RESET argument specifies that we should restart from the beginning. ! \\[next-error-framework-next-error] normally uses the most recently started compilation, grep, or occur buffer. It can also operate on any buffer with output from the \\[compile], \\[grep] commands, or, more generally, on any buffer in Compilation mode or with Compilation Minor mode enabled, or any buffer in which `next-error-function' is bound to an appropriate function. To specify use of a particular buffer for error messages, type ! \\[next-error-framework-next-error] in that buffer when it is the only one displayed in the current frame. ! Once \\[next-error-framework-next-error] has chosen the buffer for error messages, it runs `next-error-hook' with `run-hooks', and stays with that buffer until you use it in some other buffer which uses Compilation mode or Compilation Minor mode. *************** *** 2143,2149 **** (autoload 'multi-occur "occur" "\ Show all lines in buffers BUFS containing a match for REGEXP. This function acts on multiple buffers; otherwise, it is exactly like ! `occur'." nil nil) (autoload 'multi-occur-by-filename-regexp "occur" "\ Show all lines matching REGEXP in buffers named by BUFREGEXP. --- 2143,2149 ---- (autoload 'multi-occur "occur" "\ Show all lines in buffers BUFS containing a match for REGEXP. This function acts on multiple buffers; otherwise, it is exactly like ! `occur'." t nil) (autoload 'multi-occur-by-filename-regexp "occur" "\ Show all lines matching REGEXP in buffers named by BUFREGEXP. diff -c 'xemacs-21.5.25/lisp/custom-load.el' 'xemacs-21.5.26/lisp/custom-load.el' Index: ./lisp/custom-load.el *** ./lisp/custom-load.el Sun Feb 26 22:30:59 2006 --- ./lisp/custom-load.el Sat Apr 1 04:04:53 2006 *************** *** 2,8 **** ;;; Code: ! ;old-cus-dep-hash: #s(hash-table test equal size 205 data ("/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/files.el" ((confirm-kill-emacs . "files") (list-directory-verbose-switches . "files") (list-directory-brief-switches . "files") (save-some-buffers-query-display-buffer . "files") (backup-directory-alist . "files") (make-backup-file-name-function . "files") (change-major-mode-with-file-name . "files") (find-file-suppress-same-file-warnings . "files") (find-file-wildcards . "files") (find-file-not-true-dirname-list . "files") (enable-local-eval . "files") (enable-local-variables . "files") (find-directory-functions . "files") (find-file-run-dired . "files") (save-abbrevs . "files") (auto-save-file-name-transforms . "files") (auto-save-visited-file-name . "files") (auto-save-default . "files") (require-final-newline . "files") (kept-new-versions . "files") (kept-old-versions . "files") (delete-old-versions . "files") (version-control . "files") (file-precious-flag . "files") (revert-without-query . "files") (buffer-offer-save . "files") (backup-by-copying-when-privileged-mismatch . "files") (backup-by-copying-when-mismatch . "files") (backup-by-copying-when-linked . "files") (backup-by-copying . "files") (make-backup-files . "files") (directory-abbrev-alist . "files") (delete-auto-save-files . "files") (find-file . "files") (backup . "files") (files . "files")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-select.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/itimer.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/undo-stack.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/msw-select.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/frame.el" ((temp-buffer-max-height . "frame") (temp-buffer-shrink-to-fit . "frame") (get-frame-for-buffer-default-to-current . "frame") (get-frame-for-buffer-default-instance-limit . "frame") (get-frame-for-buffer-default-frame-name . "frame") (auto-lower-frame . "frame") (auto-raise-frame . "frame") (special-display-frame-plist . "frame") (pop-up-frame-plist . "frame") (minibuffer-frame-plist . "frame") (initial-frame-plist . "frame") (frames . "frame")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-ffi.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gui.el" ((dialog-frame-plist . "gui")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/dumped-lisp.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/make-docfile.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/derived.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/behavior-defs.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/printer.el" ((printer-page-footer . "printer") (printer-page-header . "printer") (printer-name . "printer") (printing . "printer")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/bytecomp-runtime.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-widgets.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mouse.el" ((mouse-track-conservative-activate-strokes . "mouse") (mouse-track-activate-strokes . "mouse") (mouse-track-scroll-delay . "mouse") (mouse-track-multi-click-time . "mouse") (mouse-highlight-text . "mouse") (mouse-yank-at-point . "mouse") (mouse-track-rectangle-p . "mouse") (mouse . "mouse")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/text-props.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/about.el" ((about-link-face . "about") (about-headline-face . "about")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/fontl-hooks.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-scrollbar.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/info.el" ((Info-no-description-string . "info") (Info-button1-follows-hyperlink . "info") (Info-annotations-path . "info") (Info-footnote-tag . "info") (Info-suffix-list . "info") (info-xref . "info") (info-node . "info") (Info-save-auto-generated-dir . "info") (Info-auto-generate-directory . "info") (Info-additional-search-directory-list . "info") (Info-fontify . "info") (Info-auto-advance . "info") (Info-restoring-point . "info") (Info-enable-active-nodes . "info") (Info-enable-edit . "info") (Info-novice . "info") (Info-inhibit-toolbar . "info") (info-faces . "info") (info . "info")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/iso8859-1.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/find-paths.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/auto-save.el" ((auto-save-offer-delete . "auto-save") (auto-save-hash-p . "auto-save") (auto-save-directory . "auto-save") (auto-save . "auto-save")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/view-less.el" ((view-mode-line-string . "view-less")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/msw-init.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/help.el" ((describe-function-show-arglist . "help") (view-lossage-message-count . "help") (view-lossage-key-count . "help") (mode-for-temp-buffer . "help") (mode-for-help . "help") (help-max-help-buffers . "help") (help-selects-help-window . "help") (help-appearance . "help") (help . "help")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/version.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-extra.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/dialog-items.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/coding.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/replace.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/simple.el" ((display-warning-suppressed-classes . "simple") (display-warning-minimum-level . "simple") (log-warning-minimum-level . "simple") (undisplay-echo-area-function . "simple") (redisplay-echo-area-function . "simple") (log-message-ignore-labels . "simple") (log-message-ignore-regexps . "simple") (log-message-max-size . "simple") (mail-user-agent . "simple") (blink-matching-paren-dont-ignore-comments . "simple") (blink-matching-delay . "simple") (blink-matching-paren-distance . "simple") (blink-matching-paren-on-screen . "simple") (blink-matching-paren . "simple") (column-number-mode . "simple") (line-number-mode . "simple") (auto-fill-inhibit-regexp . "simple") (fill-prefix . "simple") (kill-word-into-kill-ring . "simple") (line-move-ignore-invisible . "simple") (goal-column . "simple") (track-eol . "simple") (block-movement-size . "simple") (motion-keys-for-shifted-motion . "simple") (unshifted-motion-keys-deselect-region . "simple") (shifted-motion-keys-select-region . "simple") (next-line-add-newlines . "simple") (signal-error-on-buffer-boundary . "simple") (global-mark-ring-max . "simple") (mark-ring-max . "simple") (mark-ring-unrecorded-commands . "simple") (kill-ring-max . "simple") (interprogram-paste-function . "simple") (interprogram-cut-function . "simple") (kill-hooks . "simple") (kill-whole-line . "simple") (backward-delete-function . "simple") (delete-key-deletes-forward . "simple") (search-caps-disable-folding . "simple") (warnings . "simple") (log-message . "simple") (paren-matching . "simple") (fill-comments . "simple") (killing . "simple") (editing-basics . "simple")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/lisp-mnt.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/startup.el" ((user-mail-address . "startup") (mail-host-address . "startup")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-select.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/register.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cl-macs.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/tty-init.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/glade.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/package-info.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cus-dep.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/easy-mmode.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-mouse.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/ldap.el" ((ldap-coding-system . "ldap") (ldap-default-attribute-decoder . "ldap") (ldap-ignore-attribute-codings . "ldap") (ldap-verbose . "ldap") (ldap-host-parameters-alist . "ldap") (ldap-default-base . "ldap") (ldap-default-port . "ldap") (ldap-default-host . "ldap") (ldap . "ldap")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gnome-widgets.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/misc.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/loaddefs.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/msw-glyphs.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/raw-process.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/fontconfig.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/glyphs.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-font-menu.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/setup-paths.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-mouse.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/isearch-mode.el" ((isearch-highlight-all-matches . "isearch-mode") (isearch-mode-line-string . "isearch-mode") (search-ring-update . "isearch-mode") (regexp-search-ring-max . "isearch-mode") (search-ring-max . "isearch-mode") (isearch-hide-immediately . "isearch-mode") (search-invisible . "isearch-mode") (search-highlight . "isearch-mode") (search-whitespace-regexp . "isearch-mode") (search-nonincremental-instead . "isearch-mode") (search-slow-speed . "isearch-mode") (search-slow-window-lines . "isearch-mode") (search-exit-option . "isearch-mode") (isearch . "isearch-mode")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/hyper-apropos.el" ((hyper-apropos-warning . "hyper-apropos") (hyper-apropos-heading . "hyper-apropos") (hyper-apropos-section-heading . "hyper-apropos") (hyper-apropos-major-heading . "hyper-apropos") (hyper-apropos-hyperlink . "hyper-apropos") (hyper-apropos-documentation . "hyper-apropos") (hyper-apropos-faces . "hyper-apropos") (hyper-apropos-prettyprint-long-values . "hyper-apropos") (hyper-apropos-shrink-window . "hyper-apropos") (hyper-apropos-programming-apropos . "hyper-apropos") (hyper-apropos-show-brief-docs . "hyper-apropos") (hyper-apropos . "hyper-apropos")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/help-macro.el" ((three-step-help . "help-macro")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gpm.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/menubar-items.el" ((list-all-buffers-function . "menubar-items") (buffers-menu-grouping-function . "menubar-items") (buffers-menu-sort-function . "menubar-items") (buffers-menu-format-buffer-line-function . "menubar-items") (buffers-menu-omit-function . "menubar-items") (buffers-menu-switch-to-buffer-function . "menubar-items") (buffers-menu-submenus-for-groups-p . "menubar-items") (complex-buffers-menu-p . "menubar-items") (buffers-menu-max-size . "menubar-items") (buffers-menu . "menubar-items")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/loadup-el.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-misc.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/paths.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/itimer-autosave.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/lib-complete.el" ((find-library-source-path . "lib-complete")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/keymap.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/disp-table.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/check-features.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/finder.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/lisp-mode.el" ((eval-interactive-verbose . "lisp-mode") (lisp . "lisp-mode")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/occur.el" ((list-matching-lines-buffer-name-face . "occur") (list-matching-lines-face . "occur") (list-matching-lines-default-context-lines . "occur") (match . "occur") (occur-hook . "occur") (occur-mode-hook . "occur")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/wid-edit.el" ((widget-documentation-link-type . "wid-edit") (widget-documentation-link-p . "wid-edit") (widget-documentation-link-regexp . "wid-edit") (widget-documentation-links . "wid-edit") (widget-editable-list-gui . "wid-edit") (widget-choice-toggle . "wid-edit") (widget-link-suffix . "wid-edit") (widget-link-prefix . "wid-edit") (widget-push-button-suffix . "wid-edit") (widget-push-button-prefix . "wid-edit") (widget-push-button-gui . "wid-edit") (widget-complete-field . "wid-edit") (widget-button-pressed-face . "wid-edit") (widget-button-suffix . "wid-edit") (widget-button-prefix . "wid-edit") (widget-button . "wid-edit") (widget-image-file-name-suffixes . "wid-edit") (widget-glyph-enable . "wid-edit") (widget-glyph-directory . "wid-edit") (widget-inactive-face . "wid-edit") (widget-field-use-before-change . "wid-edit") (widget-field-add-space . "wid-edit") (widget-menu-minibuffer-flag . "wid-edit") (widget-menu-max-shortcuts . "wid-edit") (widget-menu-max-size . "wid-edit") (widget-field-face . "wid-edit") (widget-mouse-face . "wid-edit") (widget-button-face . "wid-edit") (widget-documentation-face . "wid-edit") (widget-faces . "wid-edit") (widget-documentation . "wid-edit") (widgets . "wid-edit")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/widget.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-package.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/generic-widgets.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-faces.el" ((try-oblique-before-italic-fonts . "x-faces")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/etags.el" ((tag-mark-stack-max . "etags") (tags-exuberant-ctags-optimization-p . "etags") (tags-check-parent-directories-for-tag-files . "etags") (tags-search-nuke-uninteresting-buffers . "etags") (make-tags-files-invisible . "etags") (tags-auto-read-changed-tag-files . "etags") (tag-table-alist . "etags") (tags-always-exact . "etags") (tags-build-completion-table . "etags") (etags . "etags")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cl.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cmdloop.el" ((teach-extended-commands-timeout . "cmdloop") (teach-extended-commands-p . "cmdloop") (errors-deactivate-region . "cmdloop")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-font-menu.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/select.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/callers-of-rpt.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/userlock.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/indent.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/package-get.el" ((package-get-require-signed-base-updates . "package-get") (package-get-always-update . "package-get") (package-get-base-filename . "package-get") (package-get-remove-copy . "package-get") (package-get-site-release-download-sites . "package-get") (package-get-pre-release-download-sites . "package-get") (package-get-download-sites . "package-get") (package-get-remote . "package-get") (package-get-install-to-user-init-directory . "package-get") (package-get-package-index-file-location . "package-get") (package-get-dir . "package-get") (package-get . "package-get") (package-tools . "package-get")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gutter-items.el" ((progress-feedback-style . "gutter-items") (progress-feedback-use-echo-area . "gutter-items") (buffers-tab-max-buffer-line-length . "gutter-items") (buffers-tab-format-buffer-line-function . "gutter-items") (buffers-tab-grouping-regexp . "gutter-items") (buffers-tab-face . "gutter-items") (buffers-tab-sort-function . "gutter-items") (buffers-tab-filter-functions . "gutter-items") (buffers-tab-omit-list . "gutter-items") (buffers-tab-omit-function . "gutter-items") (buffers-tab-switch-to-buffer-function . "gutter-items") (buffers-tab-max-size . "gutter-items") (gutter-buffers-tab-enabled . "gutter-items") (gutter-buffers-tab-visible-p . "gutter-items")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/objects.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/update-elc-2.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/blessmail.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/disass.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/package-ui.el" ((pui-info-buffer . "package-ui") (pui-uninstalled-package-face . "package-ui") (pui-outdated-package-face . "package-ui") (pui-deleted-package-face . "package-ui") (pui-selected-package-face . "package-ui") (pui-up-to-date-package-face . "package-ui") (pui-list-verbose . "package-ui") (pui-package-install-dest-dir . "package-ui") (pui . "package-ui")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/symbol-syntax.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/dialog.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/wid-browse.el" ((widget-browse-mode-hook . "wid-browse") (widget-browse . "wid-browse")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/newcomment.el" ((comment-auto-fill-only-comments . "newcomment") (comment-multi-line . "newcomment") (comment-padding . "newcomment") (comment-style . "newcomment") (comment-column . "newcomment") (comment-fill-column . "newcomment") (comment . "newcomment")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/sound.el" ((default-sound-directory-list . "sound") (sound-extension-list . "sound") (default-sound-directory . "sound") (sound-load-list . "sound") (sound-default-alist . "sound") (sound . "sound")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/dump-paths.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/console.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/code-files.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/window.el" ((split-window-keep-point . "window")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cus-load.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/win32-native.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/loadhist.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cl-extra.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/paragraphs.el" ((paragraph-ignore-fill-prefix . "paragraphs") (page-delimiter . "paragraphs") (sentence-end . "paragraphs") (sentence-end-without-period . "paragraphs") (sentence-end-double-space . "paragraphs") (paragraph-separate . "paragraphs") (paragraph-start . "paragraphs") (paragraphs . "paragraphs")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/dragdrop.el" ((dragdrop-drop-log-name . "dragdrop") (dragdrop-drop-log . "dragdrop") (dnd-debug . "dragdrop") (experimental-dragdrop-drop-functions . "dragdrop") (dragdrop-autoload-tm-view . "dragdrop") (dragdrop-drop-at-point . "dragdrop") (drag-n-drop . "dragdrop")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/extents.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/subr.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-win-sun.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/dialog-gtk.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/code-process.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cl-compat.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/alist.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/device.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/byte-optimize.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-marshal.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/minibuf.el" ((force-dialog-box-use . "minibuf") (minibuffer-smart-completion-tracking-behavior . "minibuf") (minibuffer-history-minimum-string-length . "minibuf") (minibuffer-electric-file-name-behavior . "minibuf") (use-dialog-box . "minibuf") (minibuffer-max-depth . "minibuf") (enable-recursive-minibuffers . "minibuf") (completion-auto-help . "minibuf") (minibuffer-confirm-incomplete . "minibuf") (minibuffer-history-uniquify . "minibuf") (insert-default-directory . "minibuf") (minibuffer . "minibuf")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-compose.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gdk.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mode-motion.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/obsolete.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/scrollbar.el" ((scrollbars-visible-p . "scrollbar")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/unicode.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/faces.el" ((init-face-from-resources . "faces") (frame-background-mode . "faces") (face-frob-from-locale-first . "faces") (faces . "faces")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/msw-mouse.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/hash-table.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/widgets-gtk.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-iso8859-1.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/picture.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gutter.el" ((default-gutter-position . "gutter") (gutter . "gutter")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-file-dialog.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/next-error.el" ((next-error-hook . "next-error") (next-error-highlight-no-select . "next-error") (next-error-highlight . "next-error") (next-error . "next-error") (next-error . "next-error")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/process.el" ((execute . "process") (processes-basics . "process") (processes . "process")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/menubar.el" ((menu-submenu-name-format . "menubar") (menu-submenu-max-items . "menubar") (menu-max-items . "menubar") (menu . "menubar")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/list-mode.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/shadow.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/site-load.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/abbrev.el" ((defining-abbrev-turns-on-abbrev-mode . "abbrev") (only-global-abbrevs . "abbrev") (abbrev-mode . "abbrev") (abbrev . "abbrev")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/autoload.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/keydefs.el" ((keyboard . "keydefs")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/backquote.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cus-file.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-widget-accessors.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/auto-show.el" ((auto-show-show-left-margin-threshold . "auto-show") (auto-show-shift-amount . "auto-show") (auto-show-mode . "auto-show") (auto-show . "auto-show")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/easymenu.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/lisp.el" ((parens-require-spaces . "lisp") (defun-prompt-regexp . "lisp")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-init.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/auto-autoloads.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/loadup.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/rect.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gnuserv.el" ((gnuserv-make-temp-file-backup . "gnuserv") (gnuserv-temp-file-regexp . "gnuserv") (gnuserv-kill-quietly . "gnuserv") (gnuserv-shutdown-hook . "gnuserv") (gnuserv-init-hook . "gnuserv") (gnuserv-done-hook . "gnuserv") (gnuserv-visit-hook . "gnuserv") (gnuserv-program . "gnuserv") (gnuserv-view-file-function . "gnuserv") (gnuserv-find-file-function . "gnuserv") (gnuserv-done-temp-file-function . "gnuserv") (gnuserv-done-function . "gnuserv") (gnuserv-frame-plist . "gnuserv") (gnuserv-frame . "gnuserv") (gnuserv-mode-line-string . "gnuserv") (gnuserv . "gnuserv")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/buffer.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cus-face.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/code-cmds.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/font-menu.el" ((font-menu-max-number . "font-menu") (font-menu-this-frame-only-p . "font-menu") (font-menu-ignore-scaled-fonts . "font-menu")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/fill.el" ((adaptive-fill-function . "fill") (adaptive-fill-regexp . "fill") (adaptive-fill-mode . "fill") (colon-double-space . "fill") (sentence-end-double-space . "fill") (fill-individual-varying-indent . "fill") (fill . "fill")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/buff-menu.el" ((buffers-tab-max-buffer-line-length . "buff-menu") (buffers-tab-format-buffer-line-function . "buff-menu") (buffers-tab-grouping-regexp . "buff-menu") (buffers-tab-face . "buff-menu") (buffers-tab-sort-function . "buff-menu") (buffers-tab-filter-functions . "buff-menu") (buffers-tab-selection-function . "buff-menu") (buffers-tab-omit-function . "buff-menu") (buffers-tab-switch-to-buffer-function . "buff-menu") (buffers-tab-max-size . "buff-menu") (buffers-tab . "buff-menu")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/resize-minibuffer.el" ((resize-minibuffer-frame-exactly . "resize-minibuffer") (resize-minibuffer-frame-max-height . "resize-minibuffer") (resize-minibuffer-frame . "resize-minibuffer") (resize-minibuffer-window-exactly . "resize-minibuffer") (resize-minibuffer-window-max-height . "resize-minibuffer") (resize-minibuffer-mode . "resize-minibuffer") (resize-minibuffer . "resize-minibuffer")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/diagnose.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-iso8859-1.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/font.el" ((font-blink-interval . "font")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/compat.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/bytecomp.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-faces.el" ((try-oblique-before-italic-fonts . "gtk-faces")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/msw-faces.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/packages.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-init.el" ((x . "x-init")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mwheel.el" ((mwheel-follow-mouse . "mwheel") (mwheel-scroll-amount . "mwheel")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cus-start.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/float-sup.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/build-report.el" ((build-report-file-encoding . "build-report") (build-report-prompts . "build-report") (build-report-subject . "build-report") (build-report-installation-insert-all . "build-report") (build-report-version-file . "build-report") (build-report-installation-file . "build-report") (build-report-make-output-files . "build-report") (build-report-make-output-dir . "build-report") (build-report-delete-regexp . "build-report") (build-report-keep-regexp . "build-report") (build-report-destination . "build-report") (build-report . "build-report")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-password-dialog.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/code-init.el" ((eol-detection-enabled-p . "code-init")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/events.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/post-gc.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk-glyphs.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/apropos.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/config.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/regexp-opt.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/movemail.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/page.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/map-ynp.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/modeline.el" ((modeline-new-buffer-id-format . "modeline") (defining-kbd-macro-mode-line-string . "modeline") (auto-fill-mode-line-string . "modeline") (overwrite-mode-line-string . "modeline") (abbrev-mode-line-string . "modeline") (modeline-scrolling-method . "modeline") (modeline-click-swaps-buffers . "modeline") (drag-divider-event-lag . "modeline") (modeline-3d-p . "modeline") (modeline . "modeline")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/package-net.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/custom.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/font-lock.el" ((font-lock-warning-face . "font-lock") (font-lock-preprocessor-face . "font-lock") (font-lock-reference-face . "font-lock") (font-lock-constant-face . "font-lock") (font-lock-type-face . "font-lock") (font-lock-variable-name-face . "font-lock") (font-lock-function-name-face . "font-lock") (font-lock-builtin-face . "font-lock") (font-lock-keyword-face . "font-lock") (font-lock-doc-string-face . "font-lock") (font-lock-string-face . "font-lock") (font-lock-comment-face . "font-lock") (font-lock-mode . "font-lock") (font-lock-mode-line-string . "font-lock") (font-lock-fontify-string-delimiters . "font-lock") (font-lock-maximum-size . "font-lock") (font-lock-maximum-decoration . "font-lock") (font-lock-use-fonts . "font-lock") (font-lock-use-colors . "font-lock") (font-lock-mode-disable-list . "font-lock") (font-lock-mode-enable-list . "font-lock") (font-lock-auto-fontify . "font-lock") (font-lock-message-threshold . "font-lock") (font-lock-verbose . "font-lock") (font-lock-faces . "font-lock") (font-lock . "font-lock")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/syntax.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-win-xfree86.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/toolbar-items.el" ((toolbar-news-frame-plist . "toolbar-items") (toolbar-news-use-separate-frame . "toolbar-items") (toolbar-news-reader . "toolbar-items") (toolbar-news-commands-alist . "toolbar-items") (toolbar-info-frame-plist . "toolbar-items") (toolbar-info-use-separate-frame . "toolbar-items") (toolbar-mail-reader . "toolbar-items") (toolbar-mail-commands-alist . "toolbar-items") (toolbar-ispell-function . "toolbar-items") (toolbar-replace-function . "toolbar-items") (toolbar-undo-function . "toolbar-items") (toolbar-paste-function . "toolbar-items") (toolbar-copy-function . "toolbar-items") (toolbar-cut-function . "toolbar-items") (toolbar-print-function . "toolbar-items") (toolbar-save-function . "toolbar-items") (toolbar-dired-function . "toolbar-items") (toolbar-open-function . "toolbar-items") (toolbar . "toolbar-items")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cus-edit.el" ((custom-mode-hook . "cus-edit") (custom-group-tag-face . "cus-edit") (custom-group-tag-face-1 . "cus-edit") (custom-group-tag-faces . "cus-edit") (custom-face-default-form . "cus-edit") (custom-face-tag-face . "cus-edit") (custom-variable-default-form . "cus-edit") (custom-variable-button-face . "cus-edit") (custom-variable-tag-face . "cus-edit") (custom-comment-tag-face . "cus-edit") (custom-comment-face . "cus-edit") (custom-state-face . "cus-edit") (custom-documentation-face . "cus-edit") (custom-button-face . "cus-edit") (custom-magic-show-button . "cus-edit") (custom-magic-show-hidden . "cus-edit") (custom-magic-show . "cus-edit") (custom-saved-face . "cus-edit") (custom-changed-face . "cus-edit") (custom-set-face . "cus-edit") (custom-modified-face . "cus-edit") (custom-rogue-face . "cus-edit") (custom-invalid-face . "cus-edit") (custom-magic-faces . "cus-edit") (custom-display-global-buttons . "cus-edit") (custom-novice . "cus-edit") (custom-reset-button-menu . "cus-edit") (custom-buffer-indent . "cus-edit") (custom-buffer-done-function . "cus-edit") (custom-buffer-style . "cus-edit") (custom-menu-order-groups . "cus-edit") (custom-menu-sort-alphabetically . "cus-edit") (custom-buffer-order-groups . "cus-edit") (custom-buffer-sort-alphabetically . "cus-edit") (custom-browse-only-groups . "cus-edit") (custom-browse-order-groups . "cus-edit") (custom-browse-sort-alphabetically . "cus-edit") (custom-guess-doc-alist . "cus-edit") (custom-guess-name-alist . "cus-edit") (custom-unlispify-tag-names . "cus-edit") (custom-unlispify-remove-prefixes . "cus-edit") (custom-unlispify-menu-entries . "cus-edit") (custom-save-pretty-print . "cus-edit") (mule . "cus-edit") (debug . "cus-edit") (limits . "cus-edit") (installation . "cus-edit") (display . "cus-edit") (editing-basics . "cus-edit") (undo . "cus-edit") (alloc . "cus-edit") (custom-menu . "cus-edit") (custom-buffer . "cus-edit") (custom-browse . "cus-edit") (custom-faces . "cus-edit") (customize . "cus-edit") (local . "cus-edit") (hypermedia . "cus-edit") (tex . "cus-edit") (wp . "cus-edit") (data . "cus-edit") (i18n . "cus-edit") (unix . "cus-edit") (terminals . "cus-edit") (hardware . "cus-edit") (comm . "cus-edit") (environment . "cus-edit") (maint . "cus-edit") (internal . "cus-edit") (extensions . "cus-edit") (docs . "cus-edit") (development . "cus-edit") (games . "cus-edit") (news . "cus-edit") (mail . "cus-edit") (calendar . "cus-edit") (applications . "cus-edit") (oop . "cus-edit") (tools . "cus-edit") (c . "cus-edit") (languages . "cus-edit") (programming . "cus-edit") (bib . "cus-edit") (external . "cus-edit") (outlines . "cus-edit") (emulations . "cus-edit") (matching . "cus-edit") (editing . "cus-edit") (emacs . "cus-edit")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gnome.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/x-compose.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/msw-font-menu.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/format.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/multicast.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/package-admin.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/gtk.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/behavior.el" ((enabled-behavior-list . "behavior") (behaviors . "behavior")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/toolbar.el" ((default-toolbar-position . "toolbar") (toolbar-captioned-p . "toolbar") (toolbar-visible-p . "toolbar")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/specifier.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/symbols.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/window-xemacs.el" ((split-width-threshold . "window-xemacs") (split-height-threshold . "window-xemacs") (pop-up-windows . "window-xemacs") (same-window-regexps . "window-xemacs") (same-window-buffer-names . "window-xemacs") (special-display-regexps . "window-xemacs") (special-display-buffer-names . "window-xemacs") (pop-up-frames . "window-xemacs") (window-config-stack-max . "window-xemacs") (windows . "window-xemacs")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/text-mode.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/cl-seq.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/update-elc.el" nil)) (autoload 'custom-add-loads "cus-load") (custom-add-loads 'menu '("menubar" "menubar-items")) --- 2,8 ---- ;;; Code: ! ;old-cus-dep-hash: #s(hash-table test equal size 205 data ("/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/msw-font-menu.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/easymenu.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-scrollbar.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/lib-complete.el" ((find-library-source-path . "lib-complete")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/byte-optimize.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/itimer.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/itimer-autosave.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/package-ui.el" ((pui-info-buffer . "package-ui") (pui-uninstalled-package-face . "package-ui") (pui-outdated-package-face . "package-ui") (pui-deleted-package-face . "package-ui") (pui-selected-package-face . "package-ui") (pui-up-to-date-package-face . "package-ui") (pui-list-verbose . "package-ui") (pui-package-install-dest-dir . "package-ui") (pui . "package-ui")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cus-face.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/regexp-opt.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-compose.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-glyphs.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/info.el" ((Info-no-description-string . "info") (Info-button1-follows-hyperlink . "info") (Info-annotations-path . "info") (Info-footnote-tag . "info") (Info-suffix-list . "info") (info-xref . "info") (info-node . "info") (Info-save-auto-generated-dir . "info") (Info-auto-generate-directory . "info") (Info-additional-search-directory-list . "info") (Info-fontify . "info") (Info-auto-advance . "info") (Info-restoring-point . "info") (Info-enable-active-nodes . "info") (Info-enable-edit . "info") (Info-novice . "info") (Info-inhibit-toolbar . "info") (info-faces . "info") (info . "info")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/abbrev.el" ((defining-abbrev-turns-on-abbrev-mode . "abbrev") (only-global-abbrevs . "abbrev") (abbrev-mode . "abbrev") (abbrev . "abbrev")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/glade.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/code-files.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/callers-of-rpt.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/bytecomp.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/map-ynp.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/dump-paths.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/userlock.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/packages.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/scrollbar.el" ((scrollbars-visible-p . "scrollbar")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/specifier.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/text-mode.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/raw-process.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-font-menu.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gutter-items.el" ((progress-feedback-style . "gutter-items") (progress-feedback-use-echo-area . "gutter-items") (buffers-tab-max-buffer-line-length . "gutter-items") (buffers-tab-format-buffer-line-function . "gutter-items") (buffers-tab-grouping-regexp . "gutter-items") (buffers-tab-face . "gutter-items") (buffers-tab-sort-function . "gutter-items") (buffers-tab-filter-functions . "gutter-items") (buffers-tab-omit-list . "gutter-items") (buffers-tab-omit-function . "gutter-items") (buffers-tab-switch-to-buffer-function . "gutter-items") (buffers-tab-max-size . "gutter-items") (gutter-buffers-tab-enabled . "gutter-items") (gutter-buffers-tab-visible-p . "gutter-items")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/update-elc-2.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/dialog-gtk.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/movemail.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/minibuf.el" ((force-dialog-box-use . "minibuf") (minibuffer-smart-completion-tracking-behavior . "minibuf") (minibuffer-history-minimum-string-length . "minibuf") (minibuffer-electric-file-name-behavior . "minibuf") (use-dialog-box . "minibuf") (minibuffer-max-depth . "minibuf") (enable-recursive-minibuffers . "minibuf") (completion-auto-help . "minibuf") (minibuffer-confirm-incomplete . "minibuf") (minibuffer-history-uniquify . "minibuf") (insert-default-directory . "minibuf") (minibuffer . "minibuf")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/coding.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/modeline.el" ((modeline-new-buffer-id-format . "modeline") (defining-kbd-macro-mode-line-string . "modeline") (auto-fill-mode-line-string . "modeline") (overwrite-mode-line-string . "modeline") (abbrev-mode-line-string . "modeline") (modeline-scrolling-method . "modeline") (modeline-click-swaps-buffers . "modeline") (drag-divider-event-lag . "modeline") (modeline-3d-p . "modeline") (modeline . "modeline")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/paths.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cus-load.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cl-extra.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/simple.el" ((display-warning-suppressed-classes . "simple") (display-warning-minimum-level . "simple") (log-warning-minimum-level . "simple") (undisplay-echo-area-function . "simple") (redisplay-echo-area-function . "simple") (log-message-ignore-labels . "simple") (log-message-ignore-regexps . "simple") (log-message-max-size . "simple") (mail-user-agent . "simple") (blink-matching-paren-dont-ignore-comments . "simple") (blink-matching-delay . "simple") (blink-matching-paren-distance . "simple") (blink-matching-paren-on-screen . "simple") (blink-matching-paren . "simple") (column-number-mode . "simple") (line-number-mode . "simple") (auto-fill-inhibit-regexp . "simple") (fill-prefix . "simple") (kill-word-into-kill-ring . "simple") (line-move-ignore-invisible . "simple") (goal-column . "simple") (track-eol . "simple") (block-movement-size . "simple") (motion-keys-for-shifted-motion . "simple") (unshifted-motion-keys-deselect-region . "simple") (shifted-motion-keys-select-region . "simple") (next-line-add-newlines . "simple") (signal-error-on-buffer-boundary . "simple") (global-mark-ring-max . "simple") (mark-ring-max . "simple") (mark-ring-unrecorded-commands . "simple") (kill-ring-max . "simple") (interprogram-paste-function . "simple") (interprogram-cut-function . "simple") (kill-hooks . "simple") (kill-whole-line . "simple") (backward-delete-function . "simple") (delete-key-deletes-forward . "simple") (search-caps-disable-folding . "simple") (warnings . "simple") (log-message . "simple") (paren-matching . "simple") (fill-comments . "simple") (killing . "simple") (editing-basics . "simple")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/toolbar.el" ((default-toolbar-position . "toolbar") (toolbar-captioned-p . "toolbar") (toolbar-visible-p . "toolbar")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mwheel.el" ((mwheel-follow-mouse . "mwheel") (mwheel-scroll-amount . "mwheel")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-iso8859-1.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/update-elc.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-password-dialog.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-widget-accessors.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/process.el" ((execute . "process") (processes-basics . "process") (processes . "process")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-select.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cus-edit.el" ((custom-mode-hook . "cus-edit") (custom-group-tag-face . "cus-edit") (custom-group-tag-face-1 . "cus-edit") (custom-group-tag-faces . "cus-edit") (custom-face-default-form . "cus-edit") (custom-face-tag-face . "cus-edit") (custom-variable-default-form . "cus-edit") (custom-variable-button-face . "cus-edit") (custom-variable-tag-face . "cus-edit") (custom-comment-tag-face . "cus-edit") (custom-comment-face . "cus-edit") (custom-state-face . "cus-edit") (custom-documentation-face . "cus-edit") (custom-button-face . "cus-edit") (custom-magic-show-button . "cus-edit") (custom-magic-show-hidden . "cus-edit") (custom-magic-show . "cus-edit") (custom-saved-face . "cus-edit") (custom-changed-face . "cus-edit") (custom-set-face . "cus-edit") (custom-modified-face . "cus-edit") (custom-rogue-face . "cus-edit") (custom-invalid-face . "cus-edit") (custom-magic-faces . "cus-edit") (custom-display-global-buttons . "cus-edit") (custom-novice . "cus-edit") (custom-reset-button-menu . "cus-edit") (custom-buffer-indent . "cus-edit") (custom-buffer-done-function . "cus-edit") (custom-buffer-style . "cus-edit") (custom-menu-order-groups . "cus-edit") (custom-menu-sort-alphabetically . "cus-edit") (custom-buffer-order-groups . "cus-edit") (custom-buffer-sort-alphabetically . "cus-edit") (custom-browse-only-groups . "cus-edit") (custom-browse-order-groups . "cus-edit") (custom-browse-sort-alphabetically . "cus-edit") (custom-guess-doc-alist . "cus-edit") (custom-guess-name-alist . "cus-edit") (custom-unlispify-tag-names . "cus-edit") (custom-unlispify-remove-prefixes . "cus-edit") (custom-unlispify-menu-entries . "cus-edit") (custom-save-pretty-print . "cus-edit") (mule . "cus-edit") (debug . "cus-edit") (limits . "cus-edit") (installation . "cus-edit") (display . "cus-edit") (editing-basics . "cus-edit") (undo . "cus-edit") (alloc . "cus-edit") (custom-menu . "cus-edit") (custom-buffer . "cus-edit") (custom-browse . "cus-edit") (custom-faces . "cus-edit") (customize . "cus-edit") (local . "cus-edit") (hypermedia . "cus-edit") (tex . "cus-edit") (wp . "cus-edit") (data . "cus-edit") (i18n . "cus-edit") (unix . "cus-edit") (terminals . "cus-edit") (hardware . "cus-edit") (comm . "cus-edit") (environment . "cus-edit") (maint . "cus-edit") (internal . "cus-edit") (extensions . "cus-edit") (docs . "cus-edit") (development . "cus-edit") (games . "cus-edit") (news . "cus-edit") (mail . "cus-edit") (calendar . "cus-edit") (applications . "cus-edit") (oop . "cus-edit") (tools . "cus-edit") (c . "cus-edit") (languages . "cus-edit") (programming . "cus-edit") (bib . "cus-edit") (external . "cus-edit") (outlines . "cus-edit") (emulations . "cus-edit") (matching . "cus-edit") (editing . "cus-edit") (emacs . "cus-edit")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/config.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/win32-native.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/undo-stack.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gdk.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/iso8859-1.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/glyphs.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-package.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/files.el" ((confirm-kill-emacs . "files") (list-directory-verbose-switches . "files") (list-directory-brief-switches . "files") (save-some-buffers-query-display-buffer . "files") (backup-directory-alist . "files") (make-backup-file-name-function . "files") (change-major-mode-with-file-name . "files") (find-file-suppress-same-file-warnings . "files") (find-file-wildcards . "files") (find-file-not-true-dirname-list . "files") (enable-local-eval . "files") (enable-local-variables . "files") (find-directory-functions . "files") (find-file-run-dired . "files") (save-abbrevs . "files") (auto-save-file-name-transforms . "files") (auto-save-visited-file-name . "files") (auto-save-default . "files") (require-final-newline . "files") (kept-new-versions . "files") (kept-old-versions . "files") (delete-old-versions . "files") (version-control . "files") (file-precious-flag . "files") (revert-without-query . "files") (buffer-offer-save . "files") (backup-by-copying-when-privileged-mismatch . "files") (backup-by-copying-when-mismatch . "files") (backup-by-copying-when-linked . "files") (backup-by-copying . "files") (make-backup-files . "files") (directory-abbrev-alist . "files") (delete-auto-save-files . "files") (find-file . "files") (backup . "files") (files . "files")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/custom.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/msw-select.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/behavior.el" ((enabled-behavior-list . "behavior") (behaviors . "behavior")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/keydefs.el" ((keyboard . "keydefs")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/view-less.el" ((view-mode-line-string . "view-less")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/printer.el" ((printer-page-footer . "printer") (printer-page-header . "printer") (printer-name . "printer") (printing . "printer")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/frame.el" ((temp-buffer-max-height . "frame") (temp-buffer-shrink-to-fit . "frame") (get-frame-for-buffer-default-to-current . "frame") (get-frame-for-buffer-default-instance-limit . "frame") (get-frame-for-buffer-default-frame-name . "frame") (auto-lower-frame . "frame") (auto-raise-frame . "frame") (special-display-frame-plist . "frame") (pop-up-frame-plist . "frame") (minibuffer-frame-plist . "frame") (initial-frame-plist . "frame") (frames . "frame")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-extra.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/syntax.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/code-process.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/text-props.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/lisp.el" ((parens-require-spaces . "lisp") (defun-prompt-regexp . "lisp")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gnuserv.el" ((gnuserv-make-temp-file-backup . "gnuserv") (gnuserv-temp-file-regexp . "gnuserv") (gnuserv-kill-quietly . "gnuserv") (gnuserv-shutdown-hook . "gnuserv") (gnuserv-init-hook . "gnuserv") (gnuserv-done-hook . "gnuserv") (gnuserv-visit-hook . "gnuserv") (gnuserv-program . "gnuserv") (gnuserv-view-file-function . "gnuserv") (gnuserv-find-file-function . "gnuserv") (gnuserv-done-temp-file-function . "gnuserv") (gnuserv-done-function . "gnuserv") (gnuserv-frame-plist . "gnuserv") (gnuserv-frame . "gnuserv") (gnuserv-mode-line-string . "gnuserv") (gnuserv . "gnuserv")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-misc.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/dumped-lisp.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cus-start.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/rect.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mouse.el" ((mouse-track-conservative-activate-strokes . "mouse") (mouse-track-activate-strokes . "mouse") (mouse-track-scroll-delay . "mouse") (mouse-track-multi-click-time . "mouse") (mouse-highlight-text . "mouse") (mouse-yank-at-point . "mouse") (mouse-track-rectangle-p . "mouse") (mouse . "mouse")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/keymap.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/code-init.el" ((eol-detection-enabled-p . "code-init")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/about.el" ((about-link-face . "about") (about-headline-face . "about")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/fill.el" ((adaptive-fill-function . "fill") (adaptive-fill-regexp . "fill") (adaptive-fill-mode . "fill") (colon-double-space . "fill") (sentence-end-double-space . "fill") (fill-individual-varying-indent . "fill") (fill . "fill")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-widgets.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/find-paths.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/menubar-items.el" ((list-all-buffers-function . "menubar-items") (buffers-menu-grouping-function . "menubar-items") (buffers-menu-sort-function . "menubar-items") (buffers-menu-format-buffer-line-function . "menubar-items") (buffers-menu-omit-function . "menubar-items") (buffers-menu-switch-to-buffer-function . "menubar-items") (buffers-menu-submenus-for-groups-p . "menubar-items") (complex-buffers-menu-p . "menubar-items") (buffers-menu-max-size . "menubar-items") (buffers-menu . "menubar-items")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/font.el" ((font-blink-interval . "font")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/finder.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/toolbar-items.el" ((toolbar-news-frame-plist . "toolbar-items") (toolbar-news-use-separate-frame . "toolbar-items") (toolbar-news-reader . "toolbar-items") (toolbar-news-commands-alist . "toolbar-items") (toolbar-info-frame-plist . "toolbar-items") (toolbar-info-use-separate-frame . "toolbar-items") (toolbar-mail-reader . "toolbar-items") (toolbar-mail-commands-alist . "toolbar-items") (toolbar-ispell-function . "toolbar-items") (toolbar-replace-function . "toolbar-items") (toolbar-undo-function . "toolbar-items") (toolbar-paste-function . "toolbar-items") (toolbar-copy-function . "toolbar-items") (toolbar-cut-function . "toolbar-items") (toolbar-print-function . "toolbar-items") (toolbar-save-function . "toolbar-items") (toolbar-dired-function . "toolbar-items") (toolbar-open-function . "toolbar-items") (toolbar . "toolbar-items")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/replace.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/sound.el" ((default-sound-directory-list . "sound") (sound-extension-list . "sound") (default-sound-directory . "sound") (sound-load-list . "sound") (sound-default-alist . "sound") (sound . "sound")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cl-seq.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/version.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/package-admin.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/startup.el" ((user-mail-address . "startup") (mail-host-address . "startup")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-file-dialog.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-mouse.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/widget.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/font-lock.el" ((font-lock-warning-face . "font-lock") (font-lock-preprocessor-face . "font-lock") (font-lock-reference-face . "font-lock") (font-lock-constant-face . "font-lock") (font-lock-type-face . "font-lock") (font-lock-variable-name-face . "font-lock") (font-lock-function-name-face . "font-lock") (font-lock-builtin-face . "font-lock") (font-lock-keyword-face . "font-lock") (font-lock-doc-string-face . "font-lock") (font-lock-string-face . "font-lock") (font-lock-comment-face . "font-lock") (font-lock-mode . "font-lock") (font-lock-mode-line-string . "font-lock") (font-lock-fontify-string-delimiters . "font-lock") (font-lock-maximum-size . "font-lock") (font-lock-maximum-decoration . "font-lock") (font-lock-use-fonts . "font-lock") (font-lock-use-colors . "font-lock") (font-lock-mode-disable-list . "font-lock") (font-lock-mode-enable-list . "font-lock") (font-lock-auto-fontify . "font-lock") (font-lock-message-threshold . "font-lock") (font-lock-verbose . "font-lock") (font-lock-faces . "font-lock") (font-lock . "font-lock")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-init.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-win-xfree86.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/auto-autoloads.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cus-dep.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/window-xemacs.el" ((split-width-threshold . "window-xemacs") (split-height-threshold . "window-xemacs") (pop-up-windows . "window-xemacs") (same-window-regexps . "window-xemacs") (same-window-buffer-names . "window-xemacs") (special-display-regexps . "window-xemacs") (special-display-buffer-names . "window-xemacs") (pop-up-frames . "window-xemacs") (window-config-stack-max . "window-xemacs") (windows . "window-xemacs")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/select.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-mouse.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/post-gc.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/easy-mmode.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/apropos.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/msw-init.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/diagnose.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/multicast.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/fontconfig.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/msw-glyphs.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/alist.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/generic-widgets.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/disass.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/lisp-mode.el" ((eval-interactive-verbose . "lisp-mode") (lisp . "lisp-mode")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-select.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/register.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-compose.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/dialog.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/tty-init.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/faces.el" ((init-face-from-resources . "faces") (frame-background-mode . "faces") (face-frob-from-locale-first . "faces") (faces . "faces")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/help-macro.el" ((three-step-help . "help-macro")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mode-motion.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/behavior-defs.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/widgets-gtk.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-iso8859-1.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/setup-paths.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/subr.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/window.el" ((split-window-keep-point . "window")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/bytecomp-runtime.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/loaddefs.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/disp-table.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/build-report.el" ((build-report-file-encoding . "build-report") (build-report-prompts . "build-report") (build-report-subject . "build-report") (build-report-installation-insert-all . "build-report") (build-report-version-file . "build-report") (build-report-installation-file . "build-report") (build-report-make-output-files . "build-report") (build-report-make-output-dir . "build-report") (build-report-delete-regexp . "build-report") (build-report-keep-regexp . "build-report") (build-report-destination . "build-report") (build-report . "build-report")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/symbols.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/blessmail.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/occur.el" ((list-matching-lines-buffer-name-face . "occur") (list-matching-lines-face . "occur") (list-matching-lines-default-context-lines . "occur") (match . "occur") (occur-hook . "occur") (occur-mode-hook . "occur")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cmdloop.el" ((teach-extended-commands-timeout . "cmdloop") (teach-extended-commands-p . "cmdloop") (errors-deactivate-region . "cmdloop")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/device.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/auto-save.el" ((auto-save-offer-delete . "auto-save") (auto-save-hash-p . "auto-save") (auto-save-directory . "auto-save") (auto-save . "auto-save")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-ffi.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/etags.el" ((tag-mark-stack-max . "etags") (tags-exuberant-ctags-optimization-p . "etags") (tags-check-parent-directories-for-tag-files . "etags") (tags-search-nuke-uninteresting-buffers . "etags") (make-tags-files-invisible . "etags") (tags-auto-read-changed-tag-files . "etags") (tag-table-alist . "etags") (tags-always-exact . "etags") (tags-build-completion-table . "etags") (etags . "etags")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/wid-edit.el" ((widget-documentation-link-type . "wid-edit") (widget-documentation-link-p . "wid-edit") (widget-documentation-link-regexp . "wid-edit") (widget-documentation-links . "wid-edit") (widget-editable-list-gui . "wid-edit") (widget-choice-toggle . "wid-edit") (widget-link-suffix . "wid-edit") (widget-link-prefix . "wid-edit") (widget-push-button-suffix . "wid-edit") (widget-push-button-prefix . "wid-edit") (widget-push-button-gui . "wid-edit") (widget-complete-field . "wid-edit") (widget-button-pressed-face . "wid-edit") (widget-button-suffix . "wid-edit") (widget-button-prefix . "wid-edit") (widget-button . "wid-edit") (widget-image-file-name-suffixes . "wid-edit") (widget-glyph-enable . "wid-edit") (widget-glyph-directory . "wid-edit") (widget-inactive-face . "wid-edit") (widget-field-use-before-change . "wid-edit") (widget-field-add-space . "wid-edit") (widget-menu-minibuffer-flag . "wid-edit") (widget-menu-max-shortcuts . "wid-edit") (widget-menu-max-size . "wid-edit") (widget-field-face . "wid-edit") (widget-mouse-face . "wid-edit") (widget-button-face . "wid-edit") (widget-documentation-face . "wid-edit") (widget-faces . "wid-edit") (widget-documentation . "wid-edit") (widgets . "wid-edit")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/derived.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gnome-widgets.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gutter.el" ((default-gutter-position . "gutter") (gutter . "gutter")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/shadow.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/package-get.el" ((package-get-require-signed-base-updates . "package-get") (package-get-always-update . "package-get") (package-get-base-filename . "package-get") (package-get-remove-copy . "package-get") (package-get-site-release-download-sites . "package-get") (package-get-pre-release-download-sites . "package-get") (package-get-download-sites . "package-get") (package-get-remote . "package-get") (package-get-install-to-user-init-directory . "package-get") (package-get-package-index-file-location . "package-get") (package-get-dir . "package-get") (package-get . "package-get") (package-tools . "package-get")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/hyper-apropos.el" ((hyper-apropos-warning . "hyper-apropos") (hyper-apropos-heading . "hyper-apropos") (hyper-apropos-section-heading . "hyper-apropos") (hyper-apropos-major-heading . "hyper-apropos") (hyper-apropos-hyperlink . "hyper-apropos") (hyper-apropos-documentation . "hyper-apropos") (hyper-apropos-faces . "hyper-apropos") (hyper-apropos-prettyprint-long-values . "hyper-apropos") (hyper-apropos-shrink-window . "hyper-apropos") (hyper-apropos-programming-apropos . "hyper-apropos") (hyper-apropos-show-brief-docs . "hyper-apropos") (hyper-apropos . "hyper-apropos")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gui.el" ((dialog-frame-plist . "gui")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/wid-browse.el" ((widget-browse-mode-hook . "wid-browse") (widget-browse . "wid-browse")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/console.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/newcomment.el" ((comment-auto-fill-only-comments . "newcomment") (comment-multi-line . "newcomment") (comment-padding . "newcomment") (comment-style . "newcomment") (comment-column . "newcomment") (comment-fill-column . "newcomment") (comment . "newcomment")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-win-sun.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cl-compat.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/help.el" ((describe-function-show-arglist . "help") (view-lossage-message-count . "help") (view-lossage-key-count . "help") (mode-for-temp-buffer . "help") (mode-for-help . "help") (help-max-help-buffers . "help") (help-selects-help-window . "help") (help-appearance . "help") (help . "help")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/extents.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/paragraphs.el" ((paragraph-ignore-fill-prefix . "paragraphs") (page-delimiter . "paragraphs") (sentence-end . "paragraphs") (sentence-end-without-period . "paragraphs") (sentence-end-double-space . "paragraphs") (paragraph-separate . "paragraphs") (paragraph-start . "paragraphs") (paragraphs . "paragraphs")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/msw-mouse.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/loadup.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/buffer.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cl-macs.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/make-docfile.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/package-net.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/loadup-el.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/compat.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/list-mode.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/ldap.el" ((ldap-coding-system . "ldap") (ldap-default-attribute-decoder . "ldap") (ldap-ignore-attribute-codings . "ldap") (ldap-verbose . "ldap") (ldap-host-parameters-alist . "ldap") (ldap-default-base . "ldap") (ldap-default-port . "ldap") (ldap-default-host . "ldap") (ldap . "ldap")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/unicode.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/indent.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/site-load.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gnome.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/page.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/loadhist.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/misc.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-init.el" ((x . "x-init")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/backquote.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-font-menu.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/dragdrop.el" ((dragdrop-drop-log-name . "dragdrop") (dragdrop-drop-log . "dragdrop") (dnd-debug . "dragdrop") (experimental-dragdrop-drop-functions . "dragdrop") (dragdrop-autoload-tm-view . "dragdrop") (dragdrop-drop-at-point . "dragdrop") (drag-n-drop . "dragdrop")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/lisp-mnt.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/hash-table.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/auto-show.el" ((auto-show-show-left-margin-threshold . "auto-show") (auto-show-shift-amount . "auto-show") (auto-show-mode . "auto-show") (auto-show . "auto-show")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-marshal.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/events.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/picture.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cl.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/dialog-items.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/menubar.el" ((menu-submenu-name-format . "menubar") (menu-submenu-max-items . "menubar") (menu-max-items . "menubar") (menu . "menubar")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/font-menu.el" ((font-menu-max-number . "font-menu") (font-menu-this-frame-only-p . "font-menu") (font-menu-ignore-scaled-fonts . "font-menu")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/next-error.el" ((next-error-hook . "next-error") (next-error-highlight-no-select . "next-error") (next-error-highlight . "next-error") (next-error . "next-error") (next-error . "next-error")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/code-cmds.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/buff-menu.el" ((buffers-tab-max-buffer-line-length . "buff-menu") (buffers-tab-format-buffer-line-function . "buff-menu") (buffers-tab-grouping-regexp . "buff-menu") (buffers-tab-face . "buff-menu") (buffers-tab-sort-function . "buff-menu") (buffers-tab-filter-functions . "buff-menu") (buffers-tab-selection-function . "buff-menu") (buffers-tab-omit-function . "buff-menu") (buffers-tab-switch-to-buffer-function . "buff-menu") (buffers-tab-max-size . "buff-menu") (buffers-tab . "buff-menu")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/obsolete.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/resize-minibuffer.el" ((resize-minibuffer-frame-exactly . "resize-minibuffer") (resize-minibuffer-frame-max-height . "resize-minibuffer") (resize-minibuffer-frame . "resize-minibuffer") (resize-minibuffer-window-exactly . "resize-minibuffer") (resize-minibuffer-window-max-height . "resize-minibuffer") (resize-minibuffer-mode . "resize-minibuffer") (resize-minibuffer . "resize-minibuffer")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/symbol-syntax.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/package-info.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gtk-faces.el" ((try-oblique-before-italic-fonts . "gtk-faces")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/msw-faces.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/gpm.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/x-faces.el" ((try-oblique-before-italic-fonts . "x-faces")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/format.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/float-sup.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/isearch-mode.el" ((isearch-highlight-all-matches . "isearch-mode") (isearch-mode-line-string . "isearch-mode") (search-ring-update . "isearch-mode") (regexp-search-ring-max . "isearch-mode") (search-ring-max . "isearch-mode") (isearch-hide-immediately . "isearch-mode") (search-invisible . "isearch-mode") (search-highlight . "isearch-mode") (search-whitespace-regexp . "isearch-mode") (search-nonincremental-instead . "isearch-mode") (search-slow-speed . "isearch-mode") (search-slow-window-lines . "isearch-mode") (search-exit-option . "isearch-mode") (isearch . "isearch-mode")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/autoload.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/cus-file.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/fontl-hooks.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/objects.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/check-features.el" nil)) (autoload 'custom-add-loads "cus-load") (custom-add-loads 'menu '("menubar" "menubar-items")) diff -c 'xemacs-21.5.25/lisp/diagnose.el' 'xemacs-21.5.26/lisp/diagnose.el' Index: ./lisp/diagnose.el *** ./lisp/diagnose.el Fri Nov 25 10:41:46 2005 --- ./lisp/diagnose.el Fri Mar 31 17:39:10 2006 *************** *** 142,148 **** (princ "\n") (map-plist #'(lambda (stat num) (when (string-match ! "\\(.*\\)-storage\\$" (symbol-name stat)) (incf total num) (princ (format fmt --- 142,148 ---- (princ "\n") (map-plist #'(lambda (stat num) (when (string-match ! "\\(.*\\)-storage$" (symbol-name stat)) (incf total num) (princ (format fmt *************** *** 252,258 **** (free-plhs (fourth stats)) (globals (fifth stats)) (mc-malloced-bytes (sixth stats))) ! (with-output-to-temp-buffer "*memory usage*" (flet ((print-used-plhs (text plhs) (let ((sum-n-pages 0) (sum-used-n-cells 0) --- 252,258 ---- (free-plhs (fourth stats)) (globals (fifth stats)) (mc-malloced-bytes (sixth stats))) ! (with-output-to-temp-buffer "*mc-alloc memory usage*" (flet ((print-used-plhs (text plhs) (let ((sum-n-pages 0) (sum-used-n-cells 0) *************** *** 398,407 **** (interactive) (let ((buffer "*garbage collection statistics*") (plist (gc-stats)) ! (fmt "%-9s %10s %10s %10s %10s %10s\n")) (flet ((plist-get-stat (category field) ! (or (plist-get plist (intern (concat category field))) ! "-")) (show-stats (category) (princ (format fmt category (plist-get-stat category "-total") --- 398,409 ---- (interactive) (let ((buffer "*garbage collection statistics*") (plist (gc-stats)) ! (fmt "%-9s %16s %12s %12s %12s %12s\n")) (flet ((plist-get-stat (category field) ! (let ((stat (plist-get plist (intern (concat category field))))) ! (if stat ! (format "%.0f" stat) ! "-"))) (show-stats (category) (princ (format fmt category (plist-get-stat category "-total") *************** *** 412,423 **** (with-output-to-temp-buffer buffer (save-excursion (set-buffer buffer) ! (princ (format "%s %s\n" "Current phase" (plist-get plist 'phase))) ! (princ (make-string 64 ?-)) (princ "\n") (princ (format fmt "stat" "total" "last-gc" "this-gc" "last-cycle" "this-cylce")) ! (princ (make-string 64 ?-)) (princ "\n") (show-stats "n-gc") (show-stats "n-cycles") --- 414,425 ---- (with-output-to-temp-buffer buffer (save-excursion (set-buffer buffer) ! (princ (format "%s %g\n" "Current phase" (plist-get plist 'phase))) ! (princ (make-string 78 ?-)) (princ "\n") (princ (format fmt "stat" "total" "last-gc" "this-gc" "last-cycle" "this-cylce")) ! (princ (make-string 78 ?-)) (princ "\n") (show-stats "n-gc") (show-stats "n-cycles") *************** *** 428,440 **** (show-stats "dequeued2") (show-stats "finalized") (show-stats "freed") ! (princ (make-string 64 ?-)) ! (princ "\n") ! (princ (format fmt "explicitly" ! "freed:" ! (plist-get-stat "explicitly" "-freed") ! "tried:" ! (plist-get-stat "explicitly" "-tried-freed") ! ""))) ! ! (plist-get plist 'n-gc-total))))) --- 430,433 ---- (show-stats "dequeued2") (show-stats "finalized") (show-stats "freed") ! (plist-get plist 'n-gc-total)))))) diff -c 'xemacs-21.5.25/lisp/lisp-mode.el' 'xemacs-21.5.26/lisp/lisp-mode.el' Index: ./lisp/lisp-mode.el *** ./lisp/lisp-mode.el Mon Jun 7 08:58:44 2004 --- ./lisp/lisp-mode.el Sun Feb 26 23:29:08 2006 *************** *** 340,346 **** (setq lisp-mode-map (make-sparse-keymap)) (set-keymap-name lisp-mode-map 'lisp-mode-map) (set-keymap-parents lisp-mode-map (list shared-lisp-mode-map)) - (define-key lisp-mode-map "\e\C-x" 'lisp-send-defun) ;; gag, no. use ilisp. -jwz ;; (define-key lisp-mode-map "\C-c\C-z" 'run-lisp) ) --- 340,345 ---- *************** *** 364,376 **** (lisp-mode-variables t) (set-syntax-table lisp-mode-syntax-table) (run-hooks 'lisp-mode-hook)) - - ;; This will do unless shell.el is loaded. - ;; XEmacs change - (defun lisp-send-defun () - "Send the current defun to the Lisp process made by \\[run-lisp]." - (interactive) - (error "Process lisp does not exist")) ;; XEmacs change: emacs-lisp-mode-map is a more appropriate parent. (defvar lisp-interaction-mode-map () --- 363,368 ---- diff -c 'xemacs-21.5.25/lisp/mule/custom-load.el' 'xemacs-21.5.26/lisp/mule/custom-load.el' Index: ./lisp/mule/custom-load.el *** ./lisp/mule/custom-load.el Sun Feb 26 22:31:03 2006 --- ./lisp/mule/custom-load.el Sat Apr 1 04:04:58 2006 *************** *** 2,8 **** ;;; Code: ! ;old-cus-dep-hash: #s(hash-table test equal size 43 data ("/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-coding.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/china-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/tibet-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/greek.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/viet-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-win32-init.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/thai-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-ccl.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/european.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/lao-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/ethio-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-composite.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/canna-leim.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/lao.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-cmds.el" ((current-language-environment . "mule-cmds") (input-method-highlight-flag . "mule-cmds") (input-method-verbose-flag . "mule-cmds") (default-input-method . "mule-cmds")) "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/english.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/devan-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-charset.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/japan-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-msw-init-late.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/vietnamese.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/indian.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/kinsoku.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/korea-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/thai.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-tty-init.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/ethiopic.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/japanese.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/cyril-util.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/devanagari.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-composite-stub.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/tibetan.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/cyrillic.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/arabic.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-x-init.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/auto-autoloads.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/thai-xtis.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/korean.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/mule-category.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/latin.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/misc-lang.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/chinese.el" nil "/Users/steve/Software/XEmacs/staging/xemacs-21.5.25/lisp/mule/hebrew.el" nil)) (autoload 'custom-add-loads "cus-load") (custom-add-loads 'mule '("mule-cmds")) --- 2,8 ---- ;;; Code: ! ;old-cus-dep-hash: #s(hash-table test equal size 43 data ("/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/hebrew.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/cyrillic.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/canna-leim.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/devanagari.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/lao.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/viet-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/thai.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/thai-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-composite-stub.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/english.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-category.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/arabic.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/korea-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/chinese.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-cmds.el" ((current-language-environment . "mule-cmds") (input-method-highlight-flag . "mule-cmds") (input-method-verbose-flag . "mule-cmds") (default-input-method . "mule-cmds")) "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-win32-init.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/korean.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-x-init.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/china-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/thai-xtis.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-composite.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-msw-init-late.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/tibetan.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-ccl.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/european.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/lao-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/greek.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-coding.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-charset.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/indian.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/latin.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/japan-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/devan-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/vietnamese.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/tibet-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/misc-lang.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/ethiopic.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/japanese.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/mule-tty-init.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/kinsoku.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/auto-autoloads.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/ethio-util.el" nil "/Users/steve/Software-Development/XEmacs/staging/xemacs-21.5.26/lisp/mule/cyril-util.el" nil)) (autoload 'custom-add-loads "cus-load") (custom-add-loads 'mule '("mule-cmds")) diff -c 'xemacs-21.5.25/lisp/newcomment.el' 'xemacs-21.5.26/lisp/newcomment.el' Index: ./lisp/newcomment.el *** ./lisp/newcomment.el Wed Jan 26 18:57:14 2005 --- ./lisp/newcomment.el Sat Mar 18 02:05:07 2006 *************** *** 652,677 **** (goto-char beg) (setq end (copy-marker end)) - ;; XEmacs: Add the following clause - - ;; if user didn't specify how many comments to remove, be smart - ;; and remove the minimal number that all lines have. that way, - ;; comments in a region of Elisp code that gets commented out will - ;; get put back correctly. - (if (null arg) - (let ((min-comments 999999)) - (while (not (eobp)) - (let ((this-comments 0)) - (while (looking-at (regexp-quote comment-start)) - (incf this-comments) - (forward-char (length comment-start))) - (if (and (> this-comments 0) (< this-comments min-comments)) - (setq min-comments this-comments)) - (forward-line 1))) - (if (< min-comments 999999) - (setq arg (list min-comments))) - (goto-char beg))) - (let* ((numarg (prefix-numeric-value arg)) (ccs comment-continue) (srei (comment-padright ccs 're)) --- 652,657 ---- diff -c 'xemacs-21.5.25/lisp/next-error.el' 'xemacs-21.5.26/lisp/next-error.el' Index: ./lisp/next-error.el *** ./lisp/next-error.el Mon Oct 24 19:07:26 2005 --- ./lisp/next-error.el Sat Mar 25 20:20:51 2006 *************** *** 24,29 **** --- 24,32 ---- ;; Boston, MA 02110-1301, USA. ;;; Synched up with: FSF 22.0.50.1 (CVS) + ;;; Some functions renamed with the next-error-framework prefix to avoid + ;;; clashes with the next-error code in compile.el. One day compile.el + ;;; will use this framework. (defgroup next-error nil "`next-error' support framework." *************** *** 175,182 **** (error "No next-error capable buffer found"))) ;;;###autoload ! (defun next-error (&optional arg reset) ! "Visit next `next-error' message and corresponding source code. If all the error messages parsed so far have been processed already, the message buffer is checked for new ones. --- 178,185 ---- (error "No next-error capable buffer found"))) ;;;###autoload ! (defun next-error-framework-next-error (&optional arg reset) ! "Visit next `next-error-framework-next-error' message and corresponding source code. If all the error messages parsed so far have been processed already, the message buffer is checked for new ones. *************** *** 188,204 **** The RESET argument specifies that we should restart from the beginning. ! \\[next-error] normally uses the most recently started compilation, grep, or occur buffer. It can also operate on any buffer with output from the \\[compile], \\[grep] commands, or, more generally, on any buffer in Compilation mode or with Compilation Minor mode enabled, or any buffer in which `next-error-function' is bound to an appropriate function. To specify use of a particular buffer for error messages, type ! \\[next-error] in that buffer when it is the only one displayed in the current frame. ! Once \\[next-error] has chosen the buffer for error messages, it runs `next-error-hook' with `run-hooks', and stays with that buffer until you use it in some other buffer which uses Compilation mode or Compilation Minor mode. --- 191,207 ---- The RESET argument specifies that we should restart from the beginning. ! \\[next-error-framework-next-error] normally uses the most recently started compilation, grep, or occur buffer. It can also operate on any buffer with output from the \\[compile], \\[grep] commands, or, more generally, on any buffer in Compilation mode or with Compilation Minor mode enabled, or any buffer in which `next-error-function' is bound to an appropriate function. To specify use of a particular buffer for error messages, type ! \\[next-error-framework-next-error] in that buffer when it is the only one displayed in the current frame. ! Once \\[next-error-framework-next-error] has chosen the buffer for error messages, it runs `next-error-hook' with `run-hooks', and stays with that buffer until you use it in some other buffer which uses Compilation mode or Compilation Minor mode. *************** *** 213,238 **** (funcall next-error-function (prefix-numeric-value arg) reset) (run-hooks 'next-error-hook)))) ! (defalias 'goto-next-locus 'next-error) ! (defalias 'next-match 'next-error) ! (defun previous-error (&optional n) ! "Visit previous `next-error' message and corresponding source code. Prefix arg N says how many error messages to move backwards (or forwards, if negative). This operates on the output from the \\[compile] and \\[grep] commands." (interactive "p") ! (next-error (- (or n 1)))) ! (defun first-error (&optional n) "Restart at the first error. Visit corresponding source code. With prefix arg N, visit the source code of the Nth error. This operates on the output from the \\[compile] command, for instance." (interactive "p") ! (next-error n t)) (defun next-error-no-select (&optional n) "Move point to the next error in the `next-error' buffer and highlight match. --- 216,241 ---- (funcall next-error-function (prefix-numeric-value arg) reset) (run-hooks 'next-error-hook)))) ! (defalias 'goto-next-locus 'next-error-framework-next-error) ! (defalias 'next-match 'next-error-framework-next-error) ! (defun next-error-framework-previous-error (&optional n) ! "Visit previous `next-error-framework-next-error' message and corresponding source code. Prefix arg N says how many error messages to move backwards (or forwards, if negative). This operates on the output from the \\[compile] and \\[grep] commands." (interactive "p") ! (next-error-framework-next-error (- (or n 1)))) ! (defun next-error-framework-first-error (&optional n) "Restart at the first error. Visit corresponding source code. With prefix arg N, visit the source code of the Nth error. This operates on the output from the \\[compile] command, for instance." (interactive "p") ! (next-error-framework-next-error n t)) (defun next-error-no-select (&optional n) "Move point to the next error in the `next-error' buffer and highlight match. *************** *** 242,248 **** select the source buffer." (interactive "p") (let ((next-error-highlight next-error-highlight-no-select)) ! (next-error n)) (pop-to-buffer next-error-last-buffer)) (defun previous-error-no-select (&optional n) --- 245,251 ---- select the source buffer." (interactive "p") (let ((next-error-highlight next-error-highlight-no-select)) ! (next-error-framework-next-error n)) (pop-to-buffer next-error-last-buffer)) (defun previous-error-no-select (&optional n) diff -c 'xemacs-21.5.25/lisp/occur.el' 'xemacs-21.5.26/lisp/occur.el' Index: ./lisp/occur.el *** ./lisp/occur.el Tue Nov 29 21:33:47 2005 --- ./lisp/occur.el Sat Mar 25 20:20:51 2006 *************** *** 177,183 **** (defun occur-next-error (&optional argp reset) "Move to the Nth (default 1) next match in an Occur mode buffer. ! Compatibility function for \\[next-error] invocations." (interactive "p") ;; we need to run occur-find-match from within the Occur buffer (with-current-buffer --- 177,183 ---- (defun occur-next-error (&optional argp reset) "Move to the Nth (default 1) next match in an Occur mode buffer. ! Compatibility function for \\[next-error-framework-next-error] invocations." (interactive "p") ;; we need to run occur-find-match from within the Occur buffer (with-current-buffer *************** *** 325,337 **** "Show all lines in buffers BUFS containing a match for REGEXP. This function acts on multiple buffers; otherwise, it is exactly like `occur'." - (defvar ido-ignore-item-temp-list) (interactive (cons (let* ((bufs (list (read-buffer "First buffer to search: " (current-buffer) t))) (buf nil) ! (ido-ignore-item-temp-list bufs)) (while (not (string-equal (setq buf (read-buffer (if (and-boundp 'read-buffer-function --- 325,337 ---- "Show all lines in buffers BUFS containing a match for REGEXP. This function acts on multiple buffers; otherwise, it is exactly like `occur'." (interactive (cons (let* ((bufs (list (read-buffer "First buffer to search: " (current-buffer) t))) (buf nil) ! ; (ido-ignore-item-temp-list bufs) ! ) (while (not (string-equal (setq buf (read-buffer (if (and-boundp 'read-buffer-function *************** *** 341,347 **** nil t)) "")) (add-to-list 'bufs buf) ! (setq ido-ignore-item-temp-list bufs)) (nreverse (mapcar #'get-buffer bufs))) (occur-read-primary-args))) (occur-1 regexp nlines bufs)) --- 341,348 ---- nil t)) "")) (add-to-list 'bufs buf) ! ; (setq ido-ignore-item-temp-list bufs) ! ) (nreverse (mapcar #'get-buffer bufs))) (occur-read-primary-args))) (occur-1 regexp nlines bufs)) diff -c 'xemacs-21.5.25/lisp/register.el' 'xemacs-21.5.26/lisp/register.el' Index: ./lisp/register.el *** ./lisp/register.el Mon Mar 28 21:14:02 2005 --- ./lisp/register.el Sat Mar 18 01:55:00 2006 *************** *** 231,238 **** (princ (car val)))) ((stringp val) ! (remove-list-of-text-properties 0 (length val) ! yank-excluded-properties val) (if verbose (progn (princ "the text:\n") --- 231,238 ---- (princ (car val)))) ((stringp val) ! ;; XEmacs change: we don't have remove-list-of-text-properties ! (set-text-properties 0 (length val) nil val) (if verbose (progn (princ "the text:\n") diff -c 'xemacs-21.5.25/lisp/setup-paths.el' 'xemacs-21.5.26/lisp/setup-paths.el' Index: ./lisp/setup-paths.el *** ./lisp/setup-paths.el Mon Dec 27 21:25:15 2004 --- ./lisp/setup-paths.el Tue Mar 14 09:09:03 2006 *************** *** 102,113 **** ;; in-place or windows-nt (and (paths-file-readable-directory-p (paths-construct-path (list directory "lisp"))) ! (paths-file-readable-directory-p (paths-construct-path (list directory "etc")))))) ! (defun paths-find-emacs-root (invocation-directory invocation-name) ! "Find the run-time root of XEmacs. INVOCATION-DIRECTORY is a directory containing the XEmacs executable. ! INVOCATION-NAME is the name of the executable itself." (let* ((executable-file-name (paths-chase-symlink (concat invocation-directory invocation-name))) --- 102,120 ---- ;; in-place or windows-nt (and (paths-file-readable-directory-p (paths-construct-path (list directory "lisp"))) ! (paths-file-readable-directory-p (paths-construct-path (list directory "etc")))) ! ;; searching for a package directory ! (and ! (string-match "win32" system-configuration) ! (paths-file-readable-directory-p (paths-construct-path (list directory ! "xemacs-packages")))))) ! ! (defun paths-find-invocation-roots (invocation-directory invocation-name root-p) ! "Find the list of run-time roots of XEmacs. INVOCATION-DIRECTORY is a directory containing the XEmacs executable. ! INVOCATION-NAME is the name of the executable itself ! ROOT-P is a function that tests whether a root is plausible." (let* ((executable-file-name (paths-chase-symlink (concat invocation-directory invocation-name))) *************** *** 116,125 **** (paths-construct-path '("..") executable-directory))) (maybe-root-2 (file-name-as-directory (paths-construct-path '(".." "..") executable-directory)))) ! (or (and (paths-emacs-root-p maybe-root-1) ! maybe-root-1) ! (and (paths-emacs-root-p maybe-root-2) ! maybe-root-2)))) (defun paths-find-emacs-roots (invocation-directory invocation-name --- 123,131 ---- (paths-construct-path '("..") executable-directory))) (maybe-root-2 (file-name-as-directory (paths-construct-path '(".." "..") executable-directory)))) ! ! (paths-filter root-p ! (list maybe-root-1 maybe-root-2)))) (defun paths-find-emacs-roots (invocation-directory invocation-name *************** *** 129,139 **** directories used by XEmacs at run-time, for example `exec-directory', `data-directory' and `lisp-directory'. ROOT-P is a function that tests whether a root is plausible." ! (let* ((potential-invocation-root ! (paths-find-emacs-root invocation-directory invocation-name)) ! (invocation-roots ! (and potential-invocation-root ! (list potential-invocation-root))) (potential-installation-roots (paths-uniq-append (and configure-exec-prefix-directory --- 135,144 ---- directories used by XEmacs at run-time, for example `exec-directory', `data-directory' and `lisp-directory'. ROOT-P is a function that tests whether a root is plausible." ! (let* ((invocation-roots ! (paths-find-invocation-roots invocation-directory ! invocation-name ! root-p)) (potential-installation-roots (paths-uniq-append (and configure-exec-prefix-directory diff -c 'xemacs-21.5.25/lisp/wid-edit.el' 'xemacs-21.5.26/lisp/wid-edit.el' Index: ./lisp/wid-edit.el *** ./lisp/wid-edit.el Fri Nov 5 08:05:56 2004 --- ./lisp/wid-edit.el Sat Mar 18 01:50:04 2006 *************** *** 324,329 **** --- 324,336 ---- (setq tail (cdr tail))) (nreverse result))) + (defun widget-move-and-invoke (event) + "Move to where you click, and if it is an active field, invoke it." + (interactive "e") + (mouse-set-point event) + (let ((pos (event-point event))) + (if (and pos (get-char-property pos 'button)) + (widget-button-click event)))) ;;; Widget text specifications. ;; diff -c 'xemacs-21.5.25/lwlib/ChangeLog' 'xemacs-21.5.26/lwlib/ChangeLog' Index: ./lwlib/ChangeLog *** ./lwlib/ChangeLog Sun Feb 26 22:14:12 2006 --- ./lwlib/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,7 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 361,367 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 365,372 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/man/ChangeLog' 'xemacs-21.5.26/man/ChangeLog' Index: ./man/ChangeLog *** ./man/ChangeLog Sun Feb 26 22:14:12 2006 --- ./man/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,40 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + + 2006-03-31 Stephen J. Turnbull + + Miscellaneous doc cleanup, parts 2-4: move CHANGES-msw, + TODO.ben-mule-21-5, README.ben-mule-21-5, and + README.ben-separate-stderr to Internals Manual. + + * internals/internals.texi (Ben's TODO list): + (CHANGES from 21.4-windows branch): + (Ben's README): + (Ben's separate stderr notes): + New nodes. + + (Subprocesses): Add "Ben's separate stderr notes" to menu. + (The Great Mule Merge of March 2002): Add "Ben's TODO list" and + "Ben's README" to menu. + (Interface to MS Windows): Add "CHANGES from 21.4-windows branch" + to menu. + + (Top): Update detailmenu. + + 2006-03-30 Stephen J. Turnbull + + Miscellaneous doc cleanup, part 1: move CHANGES-ben-mule to + Internals Manual. + + * internals/internals.texi (The Great Mule Merge of March 2002): + Insert CHANGES-ben-mule here, and reformat for Texinfo. + + 2006-02-26 Mike Sperber + + * xemacs/building.texi (External Lisp): Document that `run-lisp' + needs the os-utils package. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 2850,2856 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 2887,2894 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/man/internals/internals.texi' 'xemacs-21.5.26/man/internals/internals.texi' Index: ./man/internals/internals.texi *** ./man/internals/internals.texi Sun Dec 18 21:22:03 2005 --- ./man/internals/internals.texi Sat Apr 1 02:51:29 2006 *************** *** 476,481 **** --- 476,482 ---- * CCL:: * Microsoft Windows-Related Multilingual Issues:: * Modules for Internationalization:: + * The Great Mule Merge of March 2002:: Encodings *************** *** 522,527 **** --- 523,543 ---- * The format of the locale in setlocale():: * Random other Windows I18N docs:: + The Great Mule Merge of March 2002 + + * List of changed files in new Mule workspace:: + * Changes to the MULE subsystems:: + * Pervasive changes throughout XEmacs sources:: + * Changes to specific subsystems:: + * Mule changes by theme:: + * File-coding rewrite:: + * General User-Visible Changes:: + * General Lisp-Visible Changes:: + * User documentation:: + * General internal changes:: + * Ben's TODO list:: Probably obsolete. + * Ben's README:: Probably obsolete. + Consoles; Devices; Frames; Windows * Introduction to Consoles; Devices; Frames; Windows:: *************** *** 577,588 **** --- 593,609 ---- * Lstream Functions:: Functions for working with lstreams. * Lstream Methods:: Creating new lstream types. + Subprocesses + + * Ben's separate stderr notes:: Probably obsolete. + Interface to MS Windows * Different kinds of Windows environments:: * Windows Build Flags:: * Windows I18N Introduction:: * Modules for Interfacing with MS Windows:: + * CHANGES from 21.4-windows branch:: Probably obsolete. Interface to the X Window System *************** *** 10373,10378 **** --- 10394,10400 ---- * CCL:: * Microsoft Windows-Related Multilingual Issues:: * Modules for Internationalization:: + * The Great Mule Merge of March 2002:: @end menu @node Introduction to Multilingual Issues #1, Introduction to Multilingual Issues #2, Multilingual Support, Multilingual Support *************** *** 14080,14086 **** prepended with an L (causing it to be a wide string) depending on XEUNICODE_P. ! @node Modules for Internationalization, , Microsoft Windows-Related Multilingual Issues, Multilingual Support @section Modules for Internationalization @cindex modules for internationalization @cindex internationalization, modules for --- 14102,14108 ---- prepended with an L (causing it to be a wide string) depending on XEUNICODE_P. ! @node Modules for Internationalization, The Great Mule Merge of March 2002, Microsoft Windows-Related Multilingual Issues, Multilingual Support @section Modules for Internationalization @cindex modules for internationalization @cindex internationalization, modules for *************** *** 14161,14446 **** Asian-language support, and is not currently used. ! @node Consoles; Devices; Frames; Windows, The Redisplay Mechanism, Multilingual Support, Top ! @chapter Consoles; Devices; Frames; Windows ! @cindex consoles; devices; frames; windows ! @cindex devices; frames; windows, consoles; ! @cindex frames; windows, consoles; devices; ! @cindex windows, consoles; devices; frames; @menu ! * Introduction to Consoles; Devices; Frames; Windows:: ! * Point:: ! * Window Hierarchy:: ! * The Window Object:: ! * Modules for the Basic Displayable Lisp Objects:: @end menu - @node Introduction to Consoles; Devices; Frames; Windows, Point, Consoles; Devices; Frames; Windows, Consoles; Devices; Frames; Windows - @section Introduction to Consoles; Devices; Frames; Windows - @cindex consoles; devices; frames; windows, introduction to - @cindex devices; frames; windows, introduction to consoles; - @cindex frames; windows, introduction to consoles; devices; - @cindex windows, introduction to consoles; devices; frames; - - A window-system window that you see on the screen is called a - @dfn{frame} in Emacs terminology. Each frame is subdivided into one or - more non-overlapping panes, called (confusingly) @dfn{windows}. Each - window displays the text of a buffer in it. (See above on Buffers.) Note - that buffers and windows are independent entities: Two or more windows - can be displaying the same buffer (potentially in different locations), - and a buffer can be displayed in no windows. ! A single display screen that contains one or more frames is called ! a @dfn{display}. Under most circumstances, there is only one display. ! However, more than one display can exist, for example if you have ! a @dfn{multi-headed} console, i.e. one with a single keyboard but ! multiple displays. (Typically in such a situation, the various ! displays act like one large display, in that the mouse is only ! in one of them at a time, and moving the mouse off of one moves ! it into another.) In some cases, the different displays will ! have different characteristics, e.g. one color and one mono. ! XEmacs can display frames on multiple displays. It can even deal ! simultaneously with frames on multiple keyboards (called @dfn{consoles} in ! XEmacs terminology). Here is one case where this might be useful: You ! are using XEmacs on your workstation at work, and leave it running. ! Then you go home and dial in on a TTY line, and you can use the ! already-running XEmacs process to display another frame on your local ! TTY. ! Thus, there is a hierarchy console -> display -> frame -> window. ! There is a separate Lisp object type for each of these four concepts. ! Furthermore, there is logically a @dfn{selected console}, ! @dfn{selected display}, @dfn{selected frame}, and @dfn{selected window}. ! Each of these objects is distinguished in various ways, such as being the ! default object for various functions that act on objects of that type. ! Note that every containing object remembers the ``selected'' object ! among the objects that it contains: e.g. not only is there a selected ! window, but every frame remembers the last window in it that was ! selected, and changing the selected frame causes the remembered window ! within it to become the selected window. Similar relationships apply ! for consoles to devices and devices to frames. ! @node Point, Window Hierarchy, Introduction to Consoles; Devices; Frames; Windows, Consoles; Devices; Frames; Windows ! @section Point ! @cindex point ! Recall that every buffer has a current insertion position, called ! @dfn{point}. Now, two or more windows may be displaying the same buffer, ! and the text cursor in the two windows (i.e. @code{point}) can be in ! two different places. You may ask, how can that be, since each ! buffer has only one value of @code{point}? The answer is that each window ! also has a value of @code{point} that is squirreled away in it. There ! is only one selected window, and the value of ``point'' in that buffer ! corresponds to that window. When the selected window is changed ! from one window to another displaying the same buffer, the old ! value of @code{point} is stored into the old window's ``point'' and the ! value of @code{point} from the new window is retrieved and made the ! value of @code{point} in the buffer. This means that @code{window-point} ! for the selected window is potentially inaccurate, and if you ! want to retrieve the correct value of @code{point} for a window, ! you must special-case on the selected window and retrieve the ! buffer's point instead. This is related to why @code{save-window-excursion} ! does not save the selected window's value of @code{point}. - @node Window Hierarchy, The Window Object, Point, Consoles; Devices; Frames; Windows - @section Window Hierarchy - @cindex window hierarchy - @cindex hierarchy of windows ! If a frame contains multiple windows (panes), they are always created ! by splitting an existing window along the horizontal or vertical axis. ! Terminology is a bit confusing here: to @dfn{split a window ! horizontally} means to create two side-by-side windows, i.e. to make a ! @emph{vertical} cut in a window. Likewise, to @dfn{split a window ! vertically} means to create two windows, one above the other, by making ! a @emph{horizontal} cut. ! If you split a window and then split again along the same axis, you ! will end up with a number of panes all arranged along the same axis. ! The precise way in which the splits were made should not be important, ! and this is reflected internally. Internally, all windows are arranged ! in a tree, consisting of two types of windows, @dfn{combination} windows ! (which have children, and are covered completely by those children) and ! @dfn{leaf} windows, which have no children and are visible. Every ! combination window has two or more children, all arranged along the same ! axis. There are (logically) two subtypes of windows, depending on ! whether their children are horizontally or vertically arrayed. There is ! always one root window, which is either a leaf window (if the frame ! contains only one window) or a combination window (if the frame contains ! more than one window). In the latter case, the root window will have ! two or more children, either horizontally or vertically arrayed, and ! each of those children will be either a leaf window or another ! combination window. ! Here are some rules: - @enumerate @item ! Horizontal combination windows can never have children that are ! horizontal combination windows; same for vertical. @item ! Only leaf windows can be split (obviously) and this splitting does one ! of two things: (a) turns the leaf window into a combination window and ! creates two new leaf children, or (b) turns the leaf window into one of ! the two new leaves and creates the other leaf. Rule (1) dictates which ! of these two outcomes happens. @item ! Every combination window must have at least two children. @item ! Leaf windows can never become combination windows. They can be deleted, ! however. If this results in a violation of (3), the parent combination ! window also gets deleted. @item ! All functions that accept windows must be prepared to accept combination ! windows, and do something sane (e.g. signal an error if so). ! Combination windows @emph{do} escape to the Lisp level. @item ! All windows have three fields governing their contents: ! these are @dfn{hchild} (a list of horizontally-arrayed children), ! @dfn{vchild} (a list of vertically-arrayed children), and @dfn{buffer} ! (the buffer contained in a leaf window). Exactly one of ! these will be non-@code{nil}. Remember that @dfn{horizontally-arrayed} ! means ``side-by-side'' and @dfn{vertically-arrayed} means ! @dfn{one above the other}. @item ! Leaf windows also have markers in their @code{start} (the ! first buffer position displayed in the window) and @code{pointm} ! (the window's stashed value of @code{point}---see above) fields, ! while combination windows have @code{nil} in these fields. @item ! The list of children for a window is threaded through the ! @code{next} and @code{prev} fields of each child window. @item ! @strong{Deleted windows can be undeleted}. This happens as a result of ! restoring a window configuration, and is unlike frames, displays, and ! consoles, which, once deleted, can never be restored. Deleting a window ! does nothing except set a special @code{dead} bit to 1 and clear out the ! @code{next}, @code{prev}, @code{hchild}, and @code{vchild} fields, for ! GC purposes. @item ! Most frames actually have two top-level windows---one for the ! minibuffer and one (the @dfn{root}) for everything else. The modeline ! (if present) separates these two. The @code{next} field of the root ! points to the minibuffer, and the @code{prev} field of the minibuffer ! points to the root. The other @code{next} and @code{prev} fields are ! @code{nil}, and the frame points to both of these windows. ! Minibuffer-less frames have no minibuffer window, and the @code{next} ! and @code{prev} of the root window are @code{nil}. Minibuffer-only ! frames have no root window, and the @code{next} of the minibuffer window ! is @code{nil} but the @code{prev} points to itself. (#### This is an ! artifact that should be fixed.) ! @end enumerate - @node The Window Object, Modules for the Basic Displayable Lisp Objects, Window Hierarchy, Consoles; Devices; Frames; Windows - @section The Window Object - @cindex window object, the - @cindex object, the window ! Windows have the following accessible fields: ! @table @code ! @item frame ! The frame that this window is on. ! @item mini_p ! Non-@code{nil} if this window is a minibuffer window. ! @item buffer ! The buffer that the window is displaying. This may change often during ! the life of the window. ! @item dedicated ! Non-@code{nil} if this window is dedicated to its buffer. ! @item pointm ! @cindex window point internals ! This is the value of point in the current buffer when this window is ! selected; when it is not selected, it retains its previous value. ! @item start ! The position in the buffer that is the first character to be displayed ! in the window. - @item force_start - If this flag is non-@code{nil}, it says that the window has been - scrolled explicitly by the Lisp program. This affects what the next - redisplay does if point is off the screen: instead of scrolling the - window to show the text around point, it moves point to a location that - is on the screen. ! @item last_modified ! The @code{modified} field of the window's buffer, as of the last time ! a redisplay completed in this window. ! @item last_point ! The buffer's value of point, as of the last time ! a redisplay completed in this window. ! @item left ! This is the left-hand edge of the window, measured in columns. (The ! leftmost column on the screen is @w{column 0}.) ! @item top ! This is the top edge of the window, measured in lines. (The top line on ! the screen is @w{line 0}.) ! @item height ! The height of the window, measured in lines. ! @item width ! The width of the window, measured in columns. ! @item next ! This is the window that is the next in the chain of siblings. It is ! @code{nil} in a window that is the rightmost or bottommost of a group of ! siblings. ! @item prev ! This is the window that is the previous in the chain of siblings. It is ! @code{nil} in a window that is the leftmost or topmost of a group of ! siblings. - @item parent - Internally, XEmacs arranges windows in a tree; each group of siblings has - a parent window whose area includes all the siblings. This field points - to a window's parent. ! Parent windows do not display buffers, and play little role in display ! except to shape their child windows. Emacs Lisp programs usually have ! no access to the parent windows; they operate on the windows at the ! leaves of the tree, which actually display buffers. ! @item hscroll ! This is the number of columns that the display in the window is scrolled ! horizontally to the left. Normally, this is 0. ! @item use_time ! This is the last time that the window was selected. The function ! @code{get-lru-window} uses this field. ! @item display_table ! The window's display table, or @code{nil} if none is specified for it. ! @item update_mode_line ! Non-@code{nil} means this window's mode line needs to be updated. ! @item base_line_number ! The line number of a certain position in the buffer, or @code{nil}. ! This is used for displaying the line number of point in the mode line. ! @item base_line_pos ! The position in the buffer for which the line number is known, or @code{nil} meaning none is known. @item region_showing --- 14183,17449 ---- Asian-language support, and is not currently used. ! @c ! @c DO NOT CHANGE THE NAME OF THIS NODE; ChangeLogs refer to it. ! @c Well, of course you're welcome to seek them out and fix them, too. ! @c ! ! @node The Great Mule Merge of March 2002, , Modules for Internationalization, Multilingual Support ! @section The Great Mule Merge of March 2002 ! @cindex The Great Mule Merge ! @cindex Mule Merge, The Great ! ! In March 2002, just after the release of XEmacs 21.5 beta 5, Ben Wing ! merged what was nominally a very large refactoring of the ``Mule'' ! multilingual support code into the mainline. This merge added robust ! support for Unicode on all platforms, and by providing support for Win32 ! Unicode APIs made the Mule support on the Windows platform a reality. ! This merge also included a large number of other changes and ! improvements, not necessarily related to internationalization. ! ! This node basically amounts to the ChangeLog for 2002-03-12. ! ! Some effort has been put into proper markup for code and file names, and ! some reorganization according to themes of revision. However, much ! remains to be done. @menu ! * List of changed files in new Mule workspace:: ! * Changes to the MULE subsystems:: ! * Pervasive changes throughout XEmacs sources:: ! * Changes to specific subsystems:: ! * Mule changes by theme:: ! * File-coding rewrite:: ! * General User-Visible Changes:: ! * General Lisp-Visible Changes:: ! * User documentation:: ! * General internal changes:: ! * Ben's TODO list:: Probably obsolete. ! * Ben's README:: Probably obsolete. @end menu ! @node List of changed files in new Mule workspace, Changes to the MULE subsystems, , The Great Mule Merge of March 2002 ! @subsection List of changed files in new Mule workspace ! This node lists the files that were touched in the Great Mule Merge. ! @heading Deleted files ! @example ! src/iso-wide.h ! src/mule-charset.h ! src/mule.c ! src/ntheap.h ! src/syscommctrl.h ! lisp/files-nomule.el ! lisp/help-nomule.el ! lisp/mule/mule-help.el ! lisp/mule/mule-init.el ! lisp/mule/mule-misc.el ! nt/config.h ! @end example ! ! @heading Other deleted files ! ! These files were all zero-width and accidentally present. ! ! @example ! src/events-mod.h ! tests/Dnd/README.OffiX ! tests/Dnd/dragtest.el ! netinstall/README.xemacs ! lib-src/srcdir-symlink.stamp ! @end example ! ! @heading New files ! ! @example ! CHANGES-ben-mule ! README.ben-mule-21-5 ! README.ben-separate-stderr ! TODO.ben-mule-21-5 ! etc/TUTORIAL.@{cs,es,nl,sk,sl@} ! etc/unicode/* ! lib-src/make-mswin-unicode.pl ! lisp/code-init.el ! lisp/resize-minibuffer.el ! lisp/unicode.el ! lisp/mule/china-util.el ! lisp/mule/cyril-util.el ! lisp/mule/devan-util.el ! lisp/mule/devanagari.el ! lisp/mule/ethio-util.el ! lisp/mule/indian.el ! lisp/mule/japan-util.el ! lisp/mule/korea-util.el ! lisp/mule/lao-util.el ! lisp/mule/lao.el ! lisp/mule/mule-locale.txt ! lisp/mule/mule-msw-init.el ! lisp/mule/thai-util.el ! lisp/mule/thai.el ! lisp/mule/tibet-util.el ! lisp/mule/tibetan.el ! lisp/mule/viet-util.el ! src/charset.h ! src/intl-auto-encap-win32.c ! src/intl-auto-encap-win32.h ! src/intl-encap-win32.c ! src/intl-win32.c ! src/intl-x.c ! src/mule-coding.c ! src/text.c ! src/text.h ! src/unicode.c ! src/s/win32-common.h ! src/s/win32-native.h ! @end example ! ! @heading Changed files ! ``Too numerous to mention.'' (Ben didn't write that, I did, but it's a ! good guess that's the intent....) ! @node Changes to the MULE subsystems, Pervasive changes throughout XEmacs sources, List of changed files in new Mule workspace, The Great Mule Merge of March 2002 ! @subsection Changes to the MULE subsystems ! @heading configure changes ! @itemize ! @item ! file-coding always compiled in. eol detection is off by default on ! unix, non-mule, but can be enabled with configure option ! @code{--with-default-eol-detection} or command-line flag @code{-eol}. @item ! code that selects which files are compiled is mostly moved to ! @file{Makefile.in.in}. see comment in @file{Makefile.in.in}. @item ! vestigial i18n3 code deleted. @item ! new cygwin mswin libs imm32 (input methods), mpr (user name ! enumeration). @item ! check for @code{link}, @code{symlink}. @item ! @code{vfork}-related code deleted. @item ! fix @file{configure.usage}. (delete @code{--with-file-coding}, ! @code{--no-doc-file}, add @code{--with-default-eol-detection}, ! @code{--quick-build}). @item ! @file{nt/config.h} has been eliminated and everything in it merged into ! @file{config.h.in} and @file{s/windowsnt.h}. see @file{config.h.in} for ! more info. @item ! massive rewrite of @file{s/windowsnt.h}, @file{m/windowsnt.h}, ! @file{s/cygwin32.h}, @file{s/mingw32.h}. common code moved into ! @file{s/win32-common.h}, @file{s/win32-native.h}. @item ! in @file{nt/xemacs.mak}, @file{nt/config.inc.samp}, variable is called ! @code{MULE}, not @code{HAVE_MULE}, for consistency with sources. @item ! define @code{TABDLY}, @code{TAB3} in @file{freebsd.h} (#### from where?) ! @end itemize ! @node Pervasive changes throughout XEmacs sources, Changes to specific subsystems, Changes to the MULE subsystems, The Great Mule Merge of March 2002 ! @subsection Pervasive changes throughout XEmacs sources ! @itemize ! @item ! all @code{#ifdef FILE_CODING} statements removed from code. ! @end itemize ! @heading Changes to string processing ! @itemize ! @item ! new @samp{qxe()} string functions that accept @code{Intbyte *} as ! arguments. These work exactly like the standard @code{strcmp()}, ! @code{strcpy()}, @code{sprintf()}, etc. except for the argument ! declaration differences. We use these whenever we have @code{Intbyte *} ! strings, which is quite often. ! @item ! new fun @code{build_intstring()} takes an @code{Intbyte *}. also new ! funs @code{build_msg_intstring} (like @code{build_intstring()}) and ! @code{build_msg_string} (like @code{build_string()}) to do a ! @code{GETTEXT()} before building the string. (elimination of old ! @code{build_translated_string()}, replaced by ! @code{build_msg_string()}). ! @item ! function @code{intern_int()} for @code{Intbyte *} arguments, like ! @code{intern()}. ! @item ! numerous places throughout code where @code{char *} replaced with ! something else, e.g. @code{Char_ASCII *}, @code{Intbyte *}, ! @code{Char_Binary *}, etc. same with unsigned @code{char *}, going to ! @code{UChar_Binary *}, etc. ! @end itemize ! @node Changes to specific subsystems, Mule changes by theme, Pervasive changes throughout XEmacs sources, The Great Mule Merge of March 2002 ! @subsection Changes to specific subsystems ! @heading Changes to the init code ! @itemize ! @item ! lots of init code rewritten to be mule-correct. ! @end itemize ! @heading Changes to processes ! @itemize ! @item ! always call @code{egetenv()}, never @code{getenv()}, for mule ! correctness. ! @end itemize ! @heading command line (@file{startup.el}, @file{emacs.c}) ! @itemize ! @item ! new option @code{-eol} to enable auto EOL detection under non-mule unix. ! @item ! new option @code{-nuni} (@code{--no-unicode-lib-calls}) to force use of ! non-Unicode API's under Windows NT, mostly for debugging purposes. ! @end itemize ! @node Mule changes by theme, File-coding rewrite, Changes to specific subsystems, The Great Mule Merge of March 2002 ! @subsection Mule changes by theme ! @itemize ! @item ! the code that handles the details of processing multilingual text has ! been consolidated to make it easier to extend it. it has been yanked ! out of various files (@file{buffer.h}, @file{mule-charset.h}, ! @file{lisp.h}, @file{insdel.c}, @file{fns.c}, @file{file-coding.c}, ! etc.) and put into @file{text.c} and @file{text.h}. ! @file{mule-charset.h} has also been renamed @file{charset.h}. all long ! comments concerning the representations and their processing have been ! consolidated into @file{text.c}. ! ! @item ! major rewriting of file-coding. it's mostly abstracted into coding ! systems that are defined by methods (similar to devices and specifiers), ! with the ultimate aim being to allow non-i18n coding systems such as ! gzip. there is a ``chain'' coding system that allows multiple coding ! systems to be chained together. (it doesn't yet have the concept that ! either end of a coding system can be bytes or chars; this needs to be ! added.) ! ! @item ! large amounts of code throughout the code base have been Mule-ized, not ! just Windows code. ! ! @item ! total rewriting of OS locale code. it notices your locale at startup ! and sets the language environment accordingly, and calls ! @code{setlocale()} and sets @code{LANG} when you change the language ! environment. new language environment properties @code{locale}, ! @code{mswindows-locale}, @code{cygwin-locale}, ! @code{native-coding-system}, to determine langenv from locale and ! vice-versa; fix all language environments (lots of language files). ! langenv startup code rewritten. many new functions to convert between ! locales, language environments, etc. ! ! @item ! major overhaul of the way default values for the various coding system ! variables are handled. all default values are collected into one ! location, a new file @file{code-init.el}, which provides a unified ! mechanism for setting and querying what i call ``basic coding system ! variables'' (which may be aliases, parts of conses, etc.) and a ! mechanism of different configurations (Windows w/Mule, Windows w/o Mule, ! Unix w/Mule, Unix w/o Mule, unix w/o Mule but w/auto EOL), each of which ! specifies a set of default values. we determine the configuration at ! startup and set all the values in one place. (@file{code-init.el}, ! @file{code-files.el}, @file{coding.el}, ...) ! ! @item ! i copied the remaining language-specific files from fsf. i made some ! minor changes in certain cases but for the most part the stuff was just ! copied and may not work. ! @item ! ms windows mule support, with full unicode support. required font, ! redisplay, event, other changes. ime support from ikeyama. ! @end itemize ! @heading Lisp-Visible Changes: ! @itemize ! @item ! ensure that @code{escape-quoted} works correctly even without Mule ! support and use it for all auto-saves. (@file{auto-save.el}, ! @file{fileio.c}, @file{coding.el}, @file{files.el}) ! @item ! new var @code{buffer-file-coding-system-when-loaded} specifies the ! actual coding system used when the file was loaded ! (@code{buffer-file-coding-system} is usually the same, but may be ! changed because it controls how the file is written out). use it in ! revert-buffer (@file{files.el}, @file{code-files.el}) and in new submenu ! File->Revert Buffer with Specified Encoding (@file{menubar-items.el}). ! @item ! improve docs on how the coding system is determined when a file is read ! in; improved docs are in both @code{find-file} and ! @code{insert-file-contents} and a reference to where to find them is in ! @code{buffer-file-coding-system-for-read}. (@file{files.el}, ! @file{code-files.el}) ! ! @item ! new (brain-damaged) FSF way of calling post-read-conversion (only one ! arg, not two) is supported, along with our two-argument way, as best we ! can. (@file{code-files.el}) ! ! @item ! add inexplicably missing var @code{default-process-coding-system}. use ! it. get rid of former hacked-up way of setting these defaults using ! @code{comint-exec-hook}. also fun ! @code{set-buffer-process-coding-system}. (@file{code-process.el}, ! @file{code-cmds.el}, @file{process.c}) ! ! @item ! remove function @code{set-default-coding-systems}; replace with ! @code{set-default-output-coding-systems}, which affects only the output ! defaults (@code{buffer-file-coding-system}, output half of ! @code{default-process-coding-system}). the input defaults should not be ! set by this because they should always remain @code{undecided} in normal ! circumstances. fix @code{prefer-coding-system} to use the new function ! and correct its docs. ! ! @item ! fix bug in @code{coding-system-change-eol-conversion} ! (@file{code-cmds.el}) ! ! @item ! recognize all eol types in @code{prefer-coding-system} ! (@file{code-cmds.el}) ! ! @item ! rewrite @code{coding-system-category} to be correct (@file{coding.el}) ! @end itemize ! ! @heading Internal Changes ! ! @itemize ! @item ! major improvements to eistring code, fleshing out of missing funs. ! @end itemize ! ! @itemize ! @item ! Separate encoding and decoding lstreams have been combined into a single ! coding lstream. Functions@samp{ make_encoding_*_stream} and ! @samp{make_decoding_*_stream} have been combined into ! @samp{make_coding_*_stream}, which takes an argument specifying whether ! encode or decode is wanted. ! ! @item ! remove last vestiges of I18N3, I18N4 code. ! ! @item ! ascii optimization for strings: we keep track of the number of ascii ! chars at the beginning and use this to optimize byte<->char conversion ! on strings. ! ! @item ! @file{mule-misc.el}, @file{mule-init.el} deleted; code in there either ! deleted, rewritten, or moved to another file. ! ! @item ! @file{mule.c} deleted. ! ! @item ! move non-Mule-specific code out of @file{mule-cmds.el} into ! @file{code-cmds.el}. (@code{coding-system-change-text-conversion}; ! remove duplicate @code{coding-system-change-eol-conversion}) ! ! @item ! remove duplicate @code{set-buffer-process-coding-system} ! (@file{code-cmds.el}) ! ! @item ! add some commented-out code from FSF @file{mule-cmds.el} ! (@code{find-coding-systems-region-subset-p}, ! @code{find-coding-systems-region}, @code{find-coding-systems-string}, ! @code{find-coding-systems-for-charsets}, ! @code{find-multibyte-characters}, @code{last-coding-system-specified}, ! @code{select-safe-coding-system}, @code{select-message-coding-system}) ! (@file{code-cmds.el}) ! ! @item ! remove obsolete alias @code{pathname-coding-system}, function ! @code{set-pathname-coding-system} (@file{coding.el}) ! ! @item ! remove coding-system property @code{doc-string}; split into ! @code{description} (short, for menu items) and @code{documentation} ! (long); correct coding system defns (@file{coding.el}, ! @file{file-coding.c}, lots of language files) ! ! @item ! move coding-system-base into C and make use of internal info ! (@file{coding.el}, @file{file-coding.c}) ! ! @item ! move @code{undecided} defn into C (@file{coding.el}, ! @file{file-coding.c}) ! ! @item ! use @code{define-coding-system-alias}, not @code{copy-coding-system} ! (@file{coding.el}) ! ! @item ! new coding system @code{iso-8859-6} for arabic ! ! @item ! delete windows-1251 support from @file{cyrillic.el}; we do it ! automatically ! ! @item ! remove @samp{setup-*-environment} as per FSF 21 ! ! @item ! rewrite @file{european.el} with lang envs for each language, so we can ! specify the locale ! ! @item ! fix corruption in @file{greek.el} ! ! @item ! sync @file{japanese.el} with FSF 20.6 ! ! @item ! fix warnings in @file{mule-ccl.el} ! ! @item ! move FSF compat Mule fns from @file{obsolete.el} to ! @file{mule-charset.el} ! ! @item ! eliminate unused @samp{truncate-string@{-to-width@}} ! ! @item ! @code{make-coding-system} accepts (but ignores) the additional ! properties present in the fsf version, for compatibility. ! ! @item ! i fixed the iso2022 handling so it will correctly read in files ! containing unknown charsets, creating a ``temporary'' charset which can ! later be overwritten by the real charset when it's defined. this allows ! iso2022 elisp files with literals in strange languages to compile ! correctly under mule. i also added a hack that will correctly read in ! and write out the emacs-specific ``composition'' escape sequences, ! i.e. @samp{ESC 0} through @samp{ESC 4}. this means that my workspace ! correctly compiles the new file @file{devanagari.el} that i added. ! ! @item ! elimination of @code{string-to-char-list} (use @code{string-to-list}) ! ! @item ! elimination of junky @code{define-charset} ! @end itemize ! ! @heading Selection ! ! @itemize ! @item ! fix msw selection code for Mule. proper encoding for ! @code{RegisterClipboardFormat}. store selection as ! @code{CF_UNICODETEXT}, which will get converted to the other formats. ! don't respond to destroy messages from @code{EmptyClipboard()}. ! @end itemize ! ! @heading Menubar ! ! @itemize ! @item ! new items @samp{Open With Specified Encoding}, ! @samp{Revert Buffer with Specified Encoding} ! ! @item ! split Mule menu into @samp{Encoding} (non-Mule-specific; includes new ! item to control EOL auto-detection) and @samp{International} submenus on ! @samp{Options}, @samp{International} on @samp{Help} ! ! @end itemize ! ! @heading Unicode support: ! ! @itemize ! @item ! translation tables added in @file{etc/unicode} ! ! @item ! new files @file{unicode.c}, @file{unicode.el} containing unicode coding ! systems and support; old code ripped out of @file{file-coding.c} ! ! @item ! translation tables read in at startup (NEEDS WORK TO MAKE IT MORE ! EFFICIENT) ! ! @item ! support @code{CF_TEXT}, @code{CF_UNICODETEXT} in @file{select.el} ! ! @item ! encapsulation code added so that we can support both Windows 9x and NT ! in a single executable, determining at runtime whether to call the ! Unicode or non-Unicode API. encapsulated routines in ! @file{intl-encap-win32.c} (non-auto-generated) and ! @file{intl-auto-encap-win32.[ch]} (auto-generated). code generator in ! @file{lib-src/make-mswin-unicode.pl}. changes throughout the code to ! use the wide structures (W suffix) and call the encapsulated Win32 API ! routines (@samp{qxe} prefix). calling code needs to do proper ! conversion of text using new coding systems @code{Qmswindows_tstr}, ! @code{Qmswindows_unicode}, or @code{Qmswindows_multibyte}. (the first ! points to one of the other two.) ! @end itemize ! ! ! @node File-coding rewrite, General User-Visible Changes, Mule changes by theme, The Great Mule Merge of March 2002 ! @subsection File-coding rewrite ! ! The coding system code has been majorly rewritten. It's abstracted into ! coding systems that are defined by methods (similar to devices and ! specifiers). The types of conversions have also been generalized. ! Formerly, decoding always converted bytes to characters and encoding the ! reverse (these are now called ``text file converters''), but conversion ! can now happen either to or from bytes or characters. This allows ! coding systems such as @code{gzip} and @code{base64} to be written. ! When specifying such a coding system to an operation that expects a text ! file converter (such as reading in or writing out a file), the ! appropriate coding systems to convert between bytes and characters are ! automatically inserted into the conversion chain as necessary. To ! facilitate creating such chains, a special coding system called ! ``chain'' has been created, which chains together two or more coding ! systems. ! ! Encoding detection has also been abstracted. Detectors are logically ! separate from coding systems, and each detector defines one or more ! categories. (For example, the detector for Unicode defines categories ! such as UTF-8, UTF-16, UCS-4, and UTF-7.) When a particular detector is ! given a piece of text to detect, it determines likeliness values (seven ! of them, from 3 [most likely] to -3 [least likely]; specific criteria ! are defined for each possible value). All detectors are run in parallel ! on a particular piece of text, and the results tabulated together to ! determine the actual encoding of the text. ! ! Encoding and decoding are now completely parallel operations, and the ! former ``encoding'' and ``decoding'' lstreams have been combined into a ! single ``coding'' lstream. Coding system methods that were formerly ! split in such a fashion have also been combined. ! ! ! @node General User-Visible Changes, General Lisp-Visible Changes, File-coding rewrite, The Great Mule Merge of March 2002 ! @subsection General User-Visible Changes ! ! @heading Search ! ! @itemize ! @item ! make regex routines reentrant, since they're sometimes called ! reentrantly. (see @file{regex.c} for a description of how.) all global ! variables used by the regex routines get pushed onto a stack by the ! callers before being set, and are restored when finished. redo the ! preprocessor flags controlling @code{REL_ALLOC} in conjunction with ! this. ! @end itemize ! ! @heading Menubar ! ! @itemize ! @item ! move menu-splitting code (@code{menu-split-long-menu}, etc.) from ! @file{font-menu.el} to @file{menubar-items.el} and redo its algorithm; ! use in various items with long generated menus; rename to remove ! @samp{font-} from beginning of functions but keep old names as aliases ! ! @item ! new fn @code{menu-sort-menu} ! ! @item ! redo items @samp{Grep All Files in Current Directory @{and Below@}} ! using stuff from sample @file{init.el} ! ! @item ! @samp{Debug on Error} and friends now affect current session only; not ! saved ! ! @item ! @code{maybe-add-init-button} -> @code{init-menubar-at-startup} and call ! explicitly from @file{startup.el} ! ! @item ! don't use @code{charset-registry} in @file{msw-font-menu.el}; it's only ! for X ! @end itemize ! ! @heading Changes to key bindings ! ! These changes are primarily found in @file{keymap.c}, @file{keydefs.el}, ! and @file{help.el}, but are found in many other files. ! ! @itemize ! @item ! @kbd{M-home}, @kbd{M-end} now move forward and backward in buffers; with ! @key{Shift}, stay within current group (e.g. all C files; same grouping ! as the gutter tabs). (bindings ! @samp{switch-to-@{next/previous@}-buffer[-in-group]} in @file{files.el}) ! ! needed to move code from @file{gutter-items.el} to @file{buff-menu.el} ! that's used by these bindings, since @file{gutter-items.el} is loaded ! only when the gutter is active and these bindings (and hence the code) ! is not (any more) gutter specific. ! ! @item ! new global vars global-tty-map and global-window-system-map specify key ! bindings for use only on TTY's or window systems, respectively. this is ! used to make @kbd{ESC ESC} be keyboard-quit on window systems, but ! @kbd{ESC ESC ESC} on TTY's, where @key{Meta + arrow} keys may appear as ! @kbd{ESC ESC O A} or whatever. @kbd{C-z} on window systems is now ! @code{zap-up-to-char}, and @code{iconify-frame} is moved to @kbd{C-Z}. ! @kbd{ESC ESC} is @code{isearch-quit}. (@file{isearch-mode.el}) ! ! @item ! document @samp{global-@{tty,window-system@}-map} in various places; ! display them when you do @kbd{C-h b}. ! ! @item ! fix up function documentation in general for keyboard primitives. ! e.g. key-bindings now contains a detailed section on the steps prior to ! looking up in keymaps, i.e. @code{function-key-map}, ! @code{keyboard-translate-table}. etc. @code{define-key} and other ! obvious starting points indicate where to look for more info. ! ! @item ! eliminate use and mention of grody @code{advertised-undo} and ! @code{deprecated-help}. (@file{simple.el}, @file{startup.el}, ! @file{picture.el}, @file{menubar-items.el}) ! @end itemize ! ! ! @node General Lisp-Visible Changes, User documentation, General User-Visible Changes, The Great Mule Merge of March 2002 ! @subsection General Lisp-Visible Changes ! ! @heading gzip support ! ! The gzip protocol is now partially supported as a coding system. ! ! @itemize ! @item ! new coding system @code{gzip} (bytes -> bytes); unfortunately, not quite ! working yet because it handles only the raw zlib format and not the ! higher-level gzip format (the zlib library is brain-damaged in that it ! provides low-level, stream-oriented API's only for raw zlib, and for ! gzip you have only high-level API's, which aren't useful for xemacs). ! ! @item ! configure support (@code{--with-zlib}). ! @end itemize ! ! ! @node User documentation, General internal changes, General Lisp-Visible Changes, The Great Mule Merge of March 2002 ! @subsection User documentation ! ! @heading Tutorial ! ! @itemize ! @item ! massive rewrite; sync to FSF 21.0.106, switch focus to window systems, ! new sections on terminology and multiple frames, lots of fixes for ! current xemacs idioms. ! ! @item ! german version from Adrian mostly matching my changes. ! ! @item ! copy new tutorials from FSF (Spanish, Dutch, Slovak, Slovenian, Czech); ! not updated yet though. ! ! @item ! eliminate @file{help-nomule.el} and @file{mule-help.el}; merge into one ! single tutorial function, fix lots of problems, put back in ! @file{help.el} where it belongs. (there was some random junk in ! @file{help-nomule.el}, @code{string-width} and @code{make-char}. ! @code{string-width} is now in @file{subr.el} with a single definition, ! and @code{make-char} in @file{text.c}.) ! @end itemize ! ! @heading Sample init file ! ! @itemize ! @item ! remove forward/backward buffer code, since it's now standard. ! ! @item ! when disabling @kbd{C-x C-c}, make it display a message saying how to ! exit, not just beep and complain ``undefined''. ! @end itemize ! ! ! @node General internal changes, Ben's TODO list, User documentation, The Great Mule Merge of March 2002 ! @subsection General internal changes ! ! @heading Changes to gnuclient and gnuserv ! ! @itemize ! @item ! clean up headers a bit. ! ! @item ! use proper ms win idiom for checking for temp directory (@code{TEMP} or ! @code{TMP}, not @code{TMPDIR}). ! @end itemize ! ! @heading Process changes ! ! @itemize ! @item ! Move @code{setenv} from packages; synch @code{setenv}/@code{getenv} with ! 21.0.105 ! @end itemize ! ! @heading Changes to I/O internals ! ! @itemize ! @item ! use @code{PATH_MAX} consistently instead of @code{MAXPATHLEN}, ! @code{MAX_PATH}, etc. ! ! @item ! all code that does preprocessor games with C lib I/O functions (open, ! read) has been removed. The code has been changed to call the correct ! function directly. Functions that accept @code{Intbyte *} arguments for ! filenames and such and do automatic conversion to or from external ! format will be prefixed @samp{qxe...()}. Functions that are retrying in ! case of @code{EINTR} are prefixed @samp{retry_...()}. ! @code{DONT_ENCAPSULATE} is long-gone. ! ! @item ! never call @code{getcwd()} any more. use our shadowed value always. ! @end itemize ! ! @heading Changes to string processing ! ! @itemize ! @item ! the @file{doprnt.c} external entry points have been completely rewritten ! to be more useful and have more sensible names. We now have, for ! example, versions that work exactly like @code{sprintf()} but return a ! @code{malloc()}ed string. ! ! @item ! code in @file{print.c} that handles @code{stdout}, @code{stderr} ! rewritten. ! ! @item ! places that print to @code{stderr} directly replaced with ! @code{stderr_out()}. ! ! @item ! new convenience functions @code{write_fmt_string()}, ! @code{write_fmt_string_lisp()}, @code{stderr_out_lisp()}, ! @code{write_string()}. ! @end itemize ! ! @heading Changes to Allocation, Objects, and the Lisp Interpreter ! ! @itemize ! @item ! automatically use ``managed lcrecord'' code when allocating. any ! lcrecord can be put on a free list with @code{free_lcrecord()}. ! ! @item ! @code{record_unwind_protect()} returns the old spec depth. ! ! @item ! @code{unbind_to()} now takes only one arg. use @code{unbind_to_1()} if ! you want the 2-arg version, with GC protection of second arg. ! ! @item ! new funs to easily inhibit GC. (@code{@{begin,end@}_gc_forbidden()}) ! use them in places where gc is currently being inhibited in a more ugly ! fashion. also, we disable GC in certain strategic places where string ! data is often passed in, e.g. @samp{dfc} functions, @samp{print} ! functions. ! ! @item ! @code{make_buffer()} -> @code{wrap_buffer()} for consistency with other ! objects; same for @code{make_frame()} ->@code{ wrap_frame()} and ! @code{make_console()} -> @code{wrap_console()}. ! ! @item ! better documentation in condition-case. ! ! @item ! new convenience funs @code{record_unwind_protect_freeing()} and ! @code{record_unwind_protect_freeing_dynarr()} for conveniently setting ! up an unwind-protect to @code{xfree()} or @code{Dynarr_free()} a ! pointer. ! @end itemize ! ! @heading s/m files: ! ! @itemize ! @item ! removal of unused @code{DATA_END}, @code{TEXT_END}, ! @code{SYSTEM_PURESIZE_EXTRA}, @code{HAVE_ALLOCA} (automatically ! determined) ! ! @item ! removal of @code{vfork} references (we no longer use @code{vfork}) ! @end itemize ! ! @heading @file{make-docfile}: ! ! @itemize ! @item ! clean up headers a bit. ! ! @item ! allow @file{.obj} to mean equivalent @file{.c}, just like for @file{.o}. ! ! @item ! allow specification of a ``response file'' (a command-line argument ! beginning with @@, specifying a file containing further command-line ! arguments) -- a standard mswin idiom to avoid potential command-line ! limits and to simplify makefiles. use this in @file{xemacs.mak}. ! @end itemize ! ! @heading debug support ! ! @itemize ! @item ! (@file{cmdloop.el}) new var breakpoint-on-error, which breaks into the C ! debugger when an unhandled error occurs noninteractively. useful when ! debugging errors coming out of complicated make scripts, e.g. package ! compilation, since you can set this through an env var. ! ! @item ! (@file{startup.el}) new env var @code{XEMACSDEBUG}, specifying a Lisp ! form executed early in the startup process; meant to be used for turning ! on debug flags such as @code{breakpoint-on-error} or ! @code{stack-trace-on-error}, to track down noninteractive errors. ! ! @item ! (@file{cmdloop.el}) removed non-working code in @code{command-error} to ! display a backtrace on @code{debug-on-error}. use ! @code{stack-trace-on-error} instead to get this. ! ! @item ! (@file{process.c}) new var @code{debug-process-io} displays data sent to ! and received from a process. ! ! @item ! (@file{alloc.c}) staticpros have name stored with them for easier ! debugging. ! ! @item ! (@file{emacs.c}) code that handles fatal errors consolidated and ! rewritten. much more robust and correctly handles all fatal exits on ! mswin (e.g. aborts, not previously handled right). ! @end itemize ! ! @heading @file{startup.el} ! ! @itemize ! @item ! move init routines from @code{before-init-hook} or ! @code{after-init-hook}; just call them directly ! (@code{init-menubar-at-startup}, @code{init-mule-at-startup}). ! ! @item ! help message fixed up (divided into sections), existing problem causing ! incomplete output fixed, undocumented options documented. ! @end itemize ! ! @heading @file{frame.el} ! ! @itemize ! @item ! delete old commented-out code. ! @end itemize ! ! ! @node Ben's TODO list, Ben's README, General internal changes, The Great Mule Merge of March 2002 ! @subsection Ben's TODO list (probably obsolete) ! ! These notes substantially overlap those in @ref{Ben's README}. They ! should probably be combined. ! ! @heading April 11, 2002 ! ! Priority: ! ! @enumerate ! @item ! Finish checking in current mule ws. ! ! @item ! Start working on bugs reported by others and noticed by me: ! ! @itemize ! @item ! problems cutting and pasting binary data, e.g. from byte-compiler ! instructions ! ! @item ! test suite failures ! ! @item ! process i/o problems w.r.t. eol: |uniq (e.g.) leaves ^M's at end of ! line; running "bash" as shell-file-name doesn't work because it doesn't ! like the extra ^M's. ! @end itemize ! @end enumerate ! ! @heading March 20, 2002 ! ! bugs: ! ! @itemize ! @item ! TTY-mode problem. When you start up in TTY mode, XEmacs goes through ! the loadup process and appears to be working -- you see the startup ! screen pulsing through the different screens, and it appears to be ! listening (hitting a key stops the screen motion), but it's frozen -- ! the screen won't get off the startup, key commands don't cause anything ! to happen. STATUS: In progress. ! ! @item ! Memory ballooning in some cases. Not yet understood. ! ! @item ! other test suite failures? ! ! @item ! need to review the handling of sounds. seems that not everything is ! documented, not everything is consistently used where it's supposed to, ! some sounds are ugly, etc. add sounds to `completer' as well. ! ! @item ! redo with-trapping-errors so that the backtrace is stored away and only ! outputted when an error actually occurs (i.e. in the condition-case ! handler). test. (use ding of various sorts as a helpful way of checking ! out what's going on.) ! ! @item ! problems with process input: |uniq (for example) leaves ^M's at end of ! line. ! ! @item ! carefully review looking up of fonts by charset, esp. wrt the last ! element of a font spec. ! ! @item ! add package support to ignore certain files -- *-util.el for languages. ! ! @item ! review use of escape-quoted in auto_save_1() vs. the buffer's own coding ! system. ! ! @item ! figure out how to get the total amount of data memory (i.e. everything ! but the code, or even including the code if can't distinguish) used by ! the process on each different OS, and use it in a new algorithm for ! triggering GC: trigger only when a certain % of the data size has been ! consed up; in addition, have a minimum. ! ! @item ! fixed bugs??? ! ! @itemize ! @item ! Occasional crash when freeing display structures. The problem seems to ! be this: A window has a "display line dynarr"; each display line has a ! "display block dynarr". Sometimes this display block dynarr is getting ! freed twice. It appears from looking at the code that sometimes a ! display line from somewhere in the dynarr gets added to the end -- hence ! two pointers to the same display block dynarr. need to review this ! code. ! @end itemize ! @end itemize ! ! @heading August 29, 2001 ! ! This is the most current list of priorities in `ben-mule-21-5'. ! Updated often. ! ! high-priority: ! ! @table @strong ! ! @item [input] ! ! @itemize ! @item ! support for WM_IME_CHAR. IME input can work under -nuni if we use ! WM_IME_CHAR. probably we should always be using this, instead of ! snarfing input using WM_COMPOSITION. i'll check this out. ! ! @item ! Russian C-x problem. see above. ! @end itemize ! ! @item [clean-up] ! ! @itemize ! @item ! make sure it compiles and runs under non-mule. remember that some ! code needs the unicode support, or at least a simple version of it. ! ! @item ! make sure it compiles and runs under pdump. see below. ! ! @item ! make sure it compiles and runs under cygwin. see below. ! ! @item ! clean up mswindows-multibyte, TSTR_TO_C_STRING. expand dfc ! optimizations to work across chain. ! ! @item ! eliminate last vestiges of codepage<->charset conversion and similar ! stuff. ! @end itemize ! ! @item [other] ! ! @itemize ! @item ! test the "file-coding is binary only on Unix, no-Mule" stuff. ! ! @item ! test that things work correctly in -nuni if the system environment ! is set to e.g. japanese -- i should get japanese menus, japanese ! file names, etc. same for russian, hebrew ... ! ! @item ! cut and paste. see below. ! ! @item ! misc issues with handling lang environments. see also August 25, ! "finally: working on the @kbd{C-x} in ...". ! ! @itemize ! @item ! when switching lang env, needs to set keyboard layout. ! ! @item ! user var to control whether, when moving into text of a ! particular language, we set the appropriate keyboard layout. we ! would need to have a lisp api for retrieving and setting the ! keyboard layout, set text properties to indicate the layout of ! text, and have a way of dealing with text with no property on ! it. (e.g. saved text has no text properties on it.) basically, ! we need to get a keyboard layout from a charset; getting a ! language would do. Perhaps we need a table that maps charsets ! to language environments. ! ! @item ! test that the lang env is properly set at startup. test that ! switching the lang env properly sets the C locale (call ! @code{setlocale()}, set @code{LANG}, etc.) -- a spawned subprogram ! should have the new locale in its environment. ! @end itemize ! ! @item ! look through everything below and see if anything is missed in this ! priority list, and if so add it. create a separate file for the ! priority list, so it can be updated as appropriate. ! @end itemize ! @end table ! ! mid-priority: ! ! @itemize ! @item ! clean up the chain coding system. its list should specify decode ! order, not encode; i now think this way is more logical. it should ! check the endpoints to make sure they make sense. it should also ! allow for the specification of "reverse-direction coding systems": ! use the specified coding system, but invert the sense of decode and ! encode. ! ! @item ! along with that, places that take an arbitrary coding system and ! expect the ends to be anything specific need to check this, and add ! the appropriate conversions from byte->char or char->byte. ! ! @item ! get some support for arabic, thai, vietnamese, japanese jisx 0212: ! at least get the unicode information in place and make sure we have ! things tied together so that we can display them. worry about r2l ! some other time. ! ! @item ! check the handling of @kbd{C-c}. can XEmacs itself be interrupted with ! @kbd{C-c}? is that impossible now that we are a window, not a console, ! app? at least we should work something out with @file{i} so that if it ! receives a @kbd{C-c} or @kbd{C-break}, it interrupts XEmacs, too. check ! out how process groups work and if they apply only to console apps. ! also redo the way that XEmacs sends @kbd{C-c} to other apps. the ! business of injecting code should be last resort. we should try ! @kbd{C-c} first, and if that doesn't work, then the next time we try to ! interrupt the same process, use the injection method. ! @end itemize ! ! @node Ben's README, , Ben's TODO list, The Great Mule Merge of March 2002 ! @subsection Ben's README (probably obsolete) ! ! These notes substantially overlap those in @ref{Ben's TODO list}. They ! should probably be combined. ! ! This may be of some historical interest as a record of Ben at work. ! There may also be some useful suggestions as yet unimplemented. ! ! @heading oct 27, 2001 ! ! -------- proposal for better buffer-switching commands: ! ! implement what VC++ currently has. you have a single "switch" command ! like @kbd{CTRL-TAB}, which as long as you hold the @key{CTRL} button ! down, brings successive buffers that are "next in line" into the current ! position, bumping the rest forward. once you release the @key{CTRL} ! key, the chain is broken, and further @kbd{CTRL-TAB}s will start from ! the beginning again. this way, frequently used buffers naturally move ! toward the front of the chain, and you can switch back and forth between ! two buffers using @kbd{CTRL-TAB}. the only thing about @kbd{CTRL-TAB} ! is it's a bit awkward. the way to implement is to have modifier-up ! strokes fire off a hook, like modifier-up-hook. this is driven by event ! dispatch, so there are no synchronization issues. when @kbd{C-tab} is ! pressed, the binding function does something like set a one-shot handler ! on the modifier-up-hook (perhaps separate hooks for separate ! modifiers?). ! ! to do this, we'd also want to change the buffer tabs so that they maintain ! their own order. in particular, they start out synched to the regular ! order, but as you make changes, you don't want the tabs to change ! order. (in fact, they may already do this.) selecting a particular buffer ! from the buffer tabs DOES make the buffer go to the head of the line. the ! invariant is that if the tabs are displaying X items, those X items are the ! first X items in the standard buffer list, but may be in a different ! order. (it looks like the tabs may already implement all of this.) ! ! @heading oct 26, 2001 ! ! necessary testing/changes: ! ! @itemize ! @item ! test all eol detection stuff under windows w/ and w/o mule, unix w/ and ! w/o mule. (test configure flag, command-line flag, menu option) may need ! a way of pretending to be unix under cygwin. ! ! @item ! test under windows w/ and w/o mule, cygwin w/ and w/o mule, cygwin x ! windows w/ and w/o mule. ! ! @item ! test undecided-dos/unix/mac. ! ! @item ! check @kbd{ESC ESC} works as @code{isearch-quit} under TTY's. ! ! @item ! test @code{coding-system-base} and all its uses (grep for them). ! ! @item ! menu item to revert to most recent auto save. ! ! @item ! consider renaming @code{build_string} -> @code{build_intstring} and ! @code{build_c_string} to @code{build_string}. (consistent with ! @code{build_msg_string} et al; many more @code{build_c_string} than ! @code{build_string}) ! @end itemize ! ! @heading oct 20, 2001 ! ! fixed problem causing crash due to invalid internal-format data, fixed ! an existing bug in @code{valid_char_p}, and added checks to more quickly ! catch when invalid chars are generated. still need to investigate why ! @code{mswindows-multibyte} is being detected. ! ! i now see why -- we only process 65536 bytes due to a constant ! @code{MAX_BYTES_PROCESSED_FOR_DETECTION}. instead, we should have no ! limit as long as we have a seekable stream. we also need to write ! @code{stderr_out_lisp()}, used in the debug info routines i wrote. ! ! check once more about @code{DEBUG_XEMACS}. i think debugging info ! should be ON by default. make sure it is. check that nothing untoward ! will result in a production system, e.g. presumably @code{assert()}s ! should not really @code{abort()}. (!! Actually, this should be runtime ! settable! Use a variable for this, and it can be set using the same ! @code{XEMACSDEBUG} method. In fact, now that I think of it, I'm sure ! that debugging info should be on always, with runtime ways of turning on ! or off any funny behavior.) ! ! @heading oct 19, 2001 ! ! fixed various bugs preventing packages from being able to be built. ! still another bug, with @file{psgml/etc/cdtd/docbook}, which contains ! some strange characters starting around char pos 110,000. It gets ! detected as @code{mswindows-multibyte} (wrong! why?) and then invalid ! internal-format data is generated. need to fix ! @code{mswindows-multibyte} (and possibly add something that signals an ! error as well; need to work on this error-signalling mechanism) and ! figure out why it's getting detected as such. what i should do is add a ! debug var that outputs blow-by-blow info of the detection process. ! ! @heading oct 9, 2001 ! ! the stuff with @code{global-window-system-map} doesn't appear to work. in any ! case it needs better documentation. [DONE] ! ! @kbd{M-home}, @kbd{M-end} do work, but cause cl-macs to get loaded. why? ! ! @heading oct 8, 2001 ! ! finished the coding system changes and they finally work! ! ! need to implement undecided-unix/dos/mac. they should be easy to do; it ! should be enough to specify an eol-type but not do-eol, but check this. ! ! consider making the standard naming be foo-lf/crlf/cr, with unix/dos/mac as ! aliases. ! ! print methods for coding systems should include some of the generic ! properties. (also then fix print_..._within_print_method). [DONE] ! ! in a little while, go back and delete the ! @code{text-file-wrapper-coding-system} code. (it'll be in CVS if ! necessary to get at it.) [DONE] ! ! need to verify at some point that non-text-file coding systems work ! properly when specified. when gzip is working, this would be a good test ! case. (and consider creating base64 as well!) ! ! remove extra crap from @code{coding-system-category} that checks for ! chain coding systems. [DONE] ! ! perhaps make a primitive that gets at ! @code{coding-system-canonical}. [DONE] ! ! need to test cygwin, compiling the mule packages, get unix-eol stuff ! working. frank from germany says he doesn't see a lisp backtrace when he ! gets an error during temacs? verify that this actually gets outputted. ! ! consider putting the current language on the modeline, mousable so it can ! be switched. also consider making the coding system be mousable and the ! line number (pick a line) and the percentage (pick a percentage). ! ! @heading oct 6, 2001 ! ! added code so that @code{debug_print()} will output a newline to the ! mswindows debugging output, not just the console. need to test. [DONE] ! ! working on problem where all files are being detected as binary. the ! problem may be that the undecided coding system is getting wrapped with ! an auto-eol coding system, which it shouldn't be -- but even in this ! situation, we should get the right results! check the ! canonicalize-after-coding methods. also, ! @code{determine_real_coding_system} appears to be getting called even ! when we're not detecting encoding. also, undecided needs a print method ! to show its params, and chain needs to be updated to show ! @code{canonicalize_after_coding}. check others as well. [DONE] ! ! @heading oct 5, 2001 ! ! finished up coding system changes, testing. ! ! errors byte-compiling files in @code{iso-2022-7-bit}. perhaps it's not ! correctly detecting the encoding? ! ! noticed a problem in the dfc macros: we call ! @code{get_coding_system_for_text_file} with @code{eol_wrap == 1}, to ! allow for auto-detection of the eol type; but this defeats the check and ! short-circuit for unicode. ! ! still need to implement calling @code{determine_real_coding_system()} ! for non-seekable streams. to implement correctly, we need to do our own ! buffering. [DONE, BUT WITHOUT BUFFERING] ! ! @heading oct 4, 2001 ! ! implemented most stuff below. ! ! need to finish up changes to @code{make_coding_system_1}. (i changed the ! way internal coding systems were handled; i need to create subsidiaries ! for all types of coding systems, not just text ones.) there's a nasty ! @code{xfree()} crash i was hitting; perhaps it'll go away once all stuff ! has been rewritten. ! ! check under cygwin to make sure that when an error occurs during loadup, a ! backtrace is output. ! ! as soon as andy releases his new setup, we should put it onto various ! standard windows software repositories. ! ! @heading oct 3, 2001 ! ! added @code{global-tty-map} and @code{global-window-system-map}. add ! some stuff to the maps, e.g. @kbd{C-x ESC} for repeat vs. @kbd{C-x ESC ! ESC} on TTY's, and of course @kbd{ESC ESC} on window systems ! vs. @kbd{ESC ESC ESC} on TTY's. [TEST] ! ! was working on integrating the two @code{help-for-tutorial} versions (mule, ! non-mule). [DONE, but test under non-Mule] ! ! was working on the file-coding changes. need to think more about ! @code{text-file-wrapper}. conclusion i think is that ! @code{get_coding_system_for_text_file} should wrap using a special ! coding system type called a @code{text-file-wrapper}, which inherits ! from chain, and implements @code{canonicalize-after-decoding} to just ! return the unwrapped coding system. We need to implement inheritance of ! coding systems, which will certainly come in extremely useful when ! coding systems get implemented in Lisp, which should happen at some ! point. (see existing docs about this.) essentially, we have a way of ! declaring that we inherit from some system, and the appropriate data ! structures get created, perhaps just an extra inheritance pointer. but ! when we create the coding system, the extra data needs to be a stretchy ! array of offsets, pointing to the type-specific data for the coding ! system type and all its parents. that means that in the methods ! structure for a coding system (which perhaps should be expanded beyond ! method, it's just a "class structure") is the index in these arrays of ! offsets. @code{CODING_SYSTEM_DATA()} can take any of the coding system ! classes (rename type to class!) that make up this class. similarly, a ! coding system class inherits its methods from the class above unless ! specifying its own method, and can call the superclass method at any ! point by either just invoking its name, or conceivably by some macro ! like ! ! @samp{CALL_SUPER (method, (args))} ! ! similar mods would have to be made to coding stream structures. ! ! perhaps for the immediate we can just sort of fake things like we currently ! do with undecided calling some stuff from chain. ! ! @heading oct 2, 2001 ! ! need to implement support for iso-8859-15, i.e. iso-8859-1 + euro symbol. ! figure out how to fall back to iso-8859-1 as necessary. ! ! leave the current bindings the way they are for the moment, but bump off ! @kbd{M-home} and @kbd{M-end} (hardly used), and substitute my buffer ! movement stuff there. [DONE, but test] ! ! there's something to be said for combining block of 6 and paragraph, ! esp. if we make the definition of "paragraph" be so that it skips by 6 when ! within code. hmm. ! ! eliminate @code{advertised-undo} crap, and similar hacks. [DONE] ! ! think about obsolete stuff to be eliminated. think about eliminating or ! dimming obsolete items from @code{hyper-apropos} and something similar ! in completion buffers. ! ! @heading sep 30, 2001 ! ! synched up the tutorials with FSF 21.0.105. was rewriting them to favor ! the cursor keys over the older @kbd{C-p}, etc. keys. ! ! Got thinking about key bindings again. ! ! @enumerate ! @item ! I think that @kbd{M-up/down} and @kbd{M-C-up/down} should be reversed. I use ! scroll-up/down much more often than motion by paragraph. ! ! @item ! Should we eliminate move by block (of 6) and subsitute it for paragraph? ! This would have the advantage that I could make bindings for buffer ! change (forward/back buffer, perhaps @kbd{M-C-up/down}. with shift, ! @kbd{M-C-S-up/down} only goes within the same type (C files, etc.). ! alternatively, just bump off @code{beginning-of-defun} from ! @kbd{C-M-home}, since it's on @kbd{C-M-a} already. ! @end enumerate ! ! need someone to go over the other tutorials (five new ones, from FSF ! 21.0.105) and fix them up to correspond to the english one. ! ! shouldn't shift-motion work with @kbd{C-a} and such as well as arrows? ! ! @heading sep 29, 2001 ! ! @code{charcount_to_bytecount} can also be made to scream -- as can ! @code{scan_buffer}, @code{buffer_mule_signal_inserted_region}, others? ! we should start profiling though before going too far down this line. ! ! Debug code that causes no slowdown should in general remain in the ! executable even in the release version because it may be useful ! (e.g. for people to see the event output). so @code{DEBUG_XEMACS} ! should be rethought. things like use of @file{msvcrtd.dll} should be ! controlled by error_checking on. maybe @code{DEBUG_XEMACS} controls ! general debug code (e.g. use of @file{msvcrtd.dll}, asserts abort, error ! checking), and the actual debugging code should remain always, or be ! conditonalized on something else (e.g. @samp{DEBUGGING_FUNS_PRESENT}). ! ! doc strings in dumped files are displayed with an extra blank line between ! each line. presumably this is recent? i assume either the change to ! detect-coding-region or the double-wrapping mentioned below. ! ! error with @code{coding-system-property} on @code{iso-2022-jp-dos}. ! problem is that that coding system is wrapped, so its type shows up as ! @code{chain}, not @code{iso-2022}. this is a general problem, and i ! think the way to fix it is to in essence do late canonicalization -- ! similar in spirit to what was done long ago, ! @code{canonicalize_when_code}, except that the new coding system (the ! wrapper) is created only once, either when the original cs is created or ! when first needed. this way, operations on the coding system work like ! expected, and you get the same results as currently when ! decoding/encoding. the only thing tricky is handling ! @code{canonicalize-after-coding} and the ever-tricky double-wrapping ! problem mentioned below. i think the proper solution is to move the ! autodetection of eol into the main autodetect type. it can be asked to ! autodetect eol, coding, or both. for just coding, it does like it ! currently does. for just eol, it does similar to what it currently does ! but runs the detection code that @code{convert-eol} currently does, and ! selects the appropriate @code{convert-eol} system. when it does both ! eol and coding, it does something on the order of creating two more ! autodetect coding systems, one for eol only and one for coding only, and ! chains them together. when each has detected the appropriate value, the ! results are combined. this automatically eliminates the double-wrapping ! problem, removes the need for complicated ! @code{canonicalize-after-coding} stuff in chain, and fixes the problem ! of autodetect not having a seekable stream because hidden inside of a ! chain. (we presume that in the both-eol-and-coding case, the various ! autodetect coding streams can communicate with each other ! appropriately.) ! ! also, we should solve the problem of internal coding systems floating ! around and clogging up the list simply by having an "internal" property ! on cs's and an internal param to @code{coding-system-list} (optional; if ! not given, you don't get the internal ones). [DONE] ! ! we should try to reduce the size of the from-unicode tables (the dominant ! memory hog in the tables). one obvious thing is to not store a whole ! emchar as the mapped-to value, but a short that encodes the octets. [DONE] ! ! @heading sep 28, 2001 ! ! need to merge up to latest in trunk. ! ! add unicode charsets for all non-translatable unicode chars; probably ! want to extend the concept of charsets to allow for dimension 3 and ! dimension 4 charsets. for the moment we should stick with just ! dimension 3 charsets; otherwise we run past the current maximum of 4 ! bytes per emchar. (most code would work automatically since it ! uses@code{ MAX_EMCHAR_LEN}; the trickiness is in certain code that has ! intimate knowledge of the representation. ! e.g. @code{bufpos_to_bytind()} has to multiply or divide by 1, 2, 3, or ! 4, and has special ways of handling each number. with 5 or 6 bytes per ! char, we'd have to change that code in various ways.) 96x96x96 = 884,000 ! or so, so with two 96x96x96 charsets, we could tackle all Unicode values ! representable by UTF-16 and then some -- and only these codepoints will ! ever have assigned chars, as far as we know. ! ! need an easy way of showing the current language environment. some menus ! need to have the current one checked or whatever. [DONE] ! ! implement unicode surrogates. ! ! implement @code{buffer-file-coding-system-when-loaded} -- make sure ! @code{find-file}, @code{revert-file}, etc. set the coding system [DONE] ! ! verify all the menu stuff [DONE] ! ! implemented the entirely-ascii check in buffers. not sure how much gain ! it'll get us as we already have a known range inside of which is ! constant time, and with pure-ascii files the known range spans the whole ! buffer. improved the comment about how @code{bufpos-to-bytind} and ! vice-versa work. [DONE] ! ! fix double-wrapping of @code{convert-eol}: when undecided converts ! itself to something with a non-autodetect eol, it needs to tell the ! adjacent @code{convert-eol} to reduce itself to nothing. ! ! need menu item for find file with specified encoding. [DONE] ! ! renamed coding systems mswindows-### to windows-### to follow the standard ! in rfc1345. [DONE] ! ! implemented @code{coding-system-subsidiary-parent} [DONE] ! @code{HAVE_MULE} -> @code{MULE} in files in @file{nt/} so that depend ! checking works [DONE] ! ! need to take the smarter @code{search-all-files-in-dir} stuff from my ! sample init file and put it on the grep menu [DONE] ! ! added item for revert w/specified encoding; mostly works, but needs ! fixes. in particular, you get the correct results, but ! @code{buffer-file-coding-system} does not reflect things right. also, ! there are too many entries. need to split into submenus. there is ! already split code out there; see if it's generalized and if not make it ! so. it should only split when there's more than a specified number, and ! when splitting, split into groups of a specified size, not into a ! specified number of groups. [DONE] ! ! too many entries in the langenv menus; need to split. [DONE] ! ! @heading sep 27, 2001 ! ! NOTE: @kbd{M-x grep} for make-string causes crash now. something ! definitely to do with string changes. check very carefully the diffs ! and put in those sledgehammer checks. [DONE] ! ! fix font-lock bug i introduced. [DONE] ! ! added optimization to strings (keeps track of # of bytes of ascii at the ! beginning of a string). perhaps should also keep an all-ascii flag to deal ! with really large (> 2 MB) strings. rewrite code to count ascii-begin to ! use the 4-or-8-at-a-time stuff in @code{bytecount_to_charcount}. ! ! Error: @kbd{M-q} is causing Invalid Regexp error on the above paragraph. ! It's not in working. I assume it's a side effect of the string stuff. ! VERIFY! Write sledgehammer checks for strings. [DONE] ! ! revamped the locale/init stuff so that it tries much harder to get things ! right. should test a bit more. in particular, test out Describe Language ! on the various created environments and make sure everything looks right. ! ! should change the menus: move the submenus on @samp{Edit->Mule} directly ! under @samp{Edit}. add a menu entry on @samp{File} to say "Reload with ! specified encoding ->". [DONE] ! ! Also @samp{Find File} with specified encoding -> Also entry to change ! the EOL settings for Unix, and implement it. ! ! @code{decode-coding-region} isn't working because it needs to insert a ! binary (char->byte) converter. [DONE] ! ! chain should be rearranged to be in decoding order; similar for ! source/sink-type, other things? ! ! the detector should check for a magic cookie even without a seekable input. ! (currently its input is not seekable, because it's hidden within a chain. ! #### See what we can do about this.) ! ! provide a way to display various settings, e.g. the current category ! mappings and priority (see mule-diag; get this working so it's in the ! path); also a way to print out the likeliness results from a detection, ! perhaps a debug flag. ! ! problem with `env', which causes path issues due to `env' in packages. ! move env code to process, sync with fsf 21.0.105, check that the autoloads ! in `env' don't cause problems. [DONE] ! ! 8-bit iso2022 detection appears broken; or at least, mule-canna.c is not so ! detected. ! ! @heading sep 25, 2001 ! ! something else to do is review the font selection and fix it so that (e.g.) ! JISX-0212 can be displayed. ! ! also, text in widgets needs to be drawn by us so that the correct fonts ! will be displayed even in multi-lingual text. ! ! @heading sep 24, 2001 ! ! the detection system is now properly abstracted. the detectors have been ! rewritten to include multiple levels of abstraction. now we just need ! detectors for ascii, binary, and latin-x, as well as more sophisticated ! detectors in general and further review of the general algorithm for doing ! detection. (#### Is this written up anywhere?) after that, consider adding ! error-checking to decoding (VERY IMPORTANT) and verifying the binary ! correctness of things under unix no-mule. ! ! @heading sep 23, 2001 ! ! began to fix the detection system -- adding multiple levels of likelihood ! and properly abstracting the detectors. the system is in place except for ! the abstraction of the detector-specific data out of the struct ! detection_state. we should get things working first before tackling that ! (which should not be too hard). i'm rewriting algorithms here rather than ! just converting code, so it's harder. mostly done with everything, but i ! need to review all detectors except iso2022 and make them properly follow ! the new way. also write a no-conversion detector. also need to look into ! the `recode' package and see how (if?) they handle detection, and maybe ! copy some of the algorithms. also look at recent FSF 21.0 and see if their ! algorithms have improved. ! ! @heading sep 22, 2001 ! ! @itemize ! @item ! fixed gc bugs from yesterday. ! ! @item ! fixed truename bug. ! ! @item ! close/finalize stuff works. ! ! @item ! eliminated notyet stuff in syswindows.h. ! ! @item ! eliminated special code in tstr_to_c_string. ! ! @item ! fixed pdump problems. (many of them, mostly latent bugs, ugh) ! ! @item ! fixed cygwin @code{sscanf} problems in ! @code{parse-unicode-translation-table}. (NOT a @code{sscanf} bug, but ! subtly different behavior w.r.t. whitespace in the format string, ! combined with a debugger that sucks ROCKS!! and consistently outputs ! garbage for variable values.) ! @end itemize ! ! main stuff to test is the handling of EOF recognition vs. binary ! (i.e. check what the default settings are under Unix). then we may have ! something that WORKS on all platforms!!! (Also need to test Windows ! non-Mule) ! ! @heading sep 21, 2001 ! ! finished redoing the close/finalize stuff in the lstream code. but i ! encountered again the nasty bug mentioned on sep 15 that disappeared on ! its own then. the problem seems to be that the finalize method of some ! of the lstreams is calling @code{Lstream_delete()}, which calls ! @code{free_managed_lcrecord()}, which is a no-no when we're inside of ! garbage-collection and the object passed to ! @code{free_managed_lcrecord()} is unmarked, and about to be released by ! the gc mechanism -- the free lists will end up with @code{xfree()}d ! objects on them, which is very bad. we need to modify ! @code{free_managed_lcrecord()} to check if we're in gc and the object is ! unmarked, and ignore it rather than move it to the free list. [DONE] ! ! (#### What we really need to do is do what Java and C# do w.r.t. their ! finalize methods: For objects with finalizers, when they're about to be ! freed, leave them marked, run the finalizer, and set another bit on them ! indicating that the finalizer has run. Next GC cycle, the objects will ! again come up for freeing, and this time the sweeper notices that the ! finalize method has already been called, and frees them for good (provided ! that a finalize method didn't do something to make the object alive ! again).) ! ! @heading sep 20, 2001 ! ! redid the lstream code so there is only one coding stream. combined the ! various doubled coding stream methods into one; i'm a little bit unsure ! of this last part, though, as the results of combining the two together ! seem unclean. got it to compile, but it crashes in loadup. need to go ! through and rehash the close vs. finalize stuff, as the problem was ! stuff getting freed too quickly, before the canonicalize-after-decoding ! was run. should eliminate entirely @code{CODING_STATE_END} and use a ! different method (close coding stream). rewrite to use these two. make ! sure they're called in the right places. @code{Lstream_close} on a ! stream should *NOT* do finalizing. finalize only on delete. [DONE] ! ! in general i'd like to see the flags eliminated and converted to ! bit-fields. also, rewriting the methods to take advantage of rejecting ! should make it possible to eliminate much of the state in the various ! methods, esp. including the flags. need to test this is working, though -- ! reduce the buffer size down very low and try files with only CRLF's in ! them, with one offset by a byte from the other, and see if we correctly ! handle rejection. ! ! still have the problem with incorrectly truenaming files. ! ! ! @heading sep 19, 2001 ! ! bug reported: crash while closing lstreams. ! ! the lstream/coding system close code needs revamping. we need to document ! that order of closing lstreams is very important, and make sure we're ! consistent. furthermore, chain and undecided lstreams need to close their ! underneath lstreams when they receive the EOF signal (there may be data in ! the underneath streams waiting to come out), not when they themselves are ! closed. [DONE] ! ! (if only we had proper inheritance. i think in any case we should ! simulate it for the chain coding stream -- write things in such a way that ! undecided can use the chain coding stream and not have to duplicate ! anything itself.) ! ! in general we need to carefully think through the closing process to make ! sure everything always works correctly and in the right order. also check ! very carefully to make sure there are no dangling pointers to deleted ! objects floating around. ! ! move the docs for the lstream functions to the functions themselves, not ! the header files. document more carefully what exactly ! @code{Lstream_delete()} means and how it's used, what the connections ! are between @code{Lstream_close(}), @code{Lstream_delete()}, ! @code{Lstream_flush()}, @code{lstream_finalize}, etc. [DONE] ! ! additional error-checking: consider deadbeefing the memory in objects ! stored in lcrecord free lists; furthermore, consider whether lifo or ! fifo is correct; under error-checking, we should perhaps be doing fifo, ! and setting a minimum number of objects on the lists that's quite large ! so that it's highly likely that any erroneous accesses to freed objects ! will go into such deadbeefed memory and cause crashes. also, at the ! earliest available opportunity, go through all freed memory and check ! for any consistency failures (overwrites of the deadbeef), crashing if ! so. perhaps we could have some sort of id for each block, to easier ! trace where the offending block came from. (all of these ideas are ! present in the debug system malloc from VC++, plus more stuff.) there's ! similar code i wrote sitting somewhere (in @file{free-hook.c}? doesn't ! appear so. we need to delete the blocking stuff out of there!). also ! look into using the debug system malloc from VC++, which has lots of ! cool stuff in it. we even have the sources. that means compiling under ! pdump, which would be a good idea anyway. set it as the default. (but ! then, we need to remove the requirement that Xpm be a DLL, which is ! extremely annoying. look into this.) ! ! test the windows code page coding systems recently created. ! ! problems reading my mail files -- 1personal appears to hang, others come up ! with lots of ^M's. investigate. ! ! test the enum functions i just wrote, and finish them. ! ! still pdump problems. ! ! @heading sep 18, 2001 ! ! critical-quit broken sometime after aug 25. ! ! @itemize ! @item ! fixed critical quit. ! ! @item ! fixed process problems. ! ! @item ! print routines work. (no routine for ccl, though) ! ! @item ! can read and write unicode files, and they can still be read by some ! other program ! ! @item ! defaults should come up correctly -- mswindows-multibyte is general. ! @end itemize ! ! still need to test matej's stuff. ! seems ok with multibyte stuff but needs more testing. ! ! @heading sep 17, 2001 ! ! !!!!! something broken with processes !!!!! cannot send mail anymore. must ! investigate. ! ! @heading sep 17, 2001 ! ! on mon/wed nights, stop *BEFORE* 11pm. Otherwise i just start getting ! woozy and can't concentrate. ! ! just finished getting assorted fixups to the main branch committed, so it ! will compile under C++ (Andy committed some code that broke C++ builds). ! cup'd the code into the fixtypes workspace, updated the tags appropriately. ! i've created the appropriate log message, sitting in fixtypes.txt in ! /src/xemacs; perhaps it should go into a README. now i just have to build ! on everything (it's currently building), verify it's ok, run patcher-mail, ! commit, send. ! ! my mule ws is also very close. need to: ! ! @itemize ! @item ! test the new print routines. ! ! @item ! test it can read and write unicode files, and they can still be read by ! some other program. ! ! @item ! try to see if unicode can be auto-detected properly. ! ! @item ! test it can read and write multibyte files in a few different formats. ! currently can't recognize them, but if you set the cs right, it should ! work. ! ! @item ! examine the test files sent by matej and see if we can handle them. ! @end itemize ! ! @heading sep 15, 2001 ! ! more eol fixing. this stuff is utter crap. ! ! currently we wrap coding systems with @code{convert-eol-autodetect} when we create ! them in @code{make_coding_system_1}. i had a feeling that this would be a ! problem, and indeed it is -- when autodetecting with `undecided', for ! example, we end up with multiple layers of eol conversion. to avoid this, ! we need to do the eol wrapping *ONLY* when we actually retrieve a coding ! system in places such as @code{insert-file-contents}. these places are ! @code{insert-file-contents}, load, process input, @code{call-process-internal}, ! @samp{encode/decode/detect-coding-region}, database input, ... ! ! (later) it's fixed, and things basically work. NOTE: for some reason, ! adding code to wrap coding systems with @code{convert-eol-lf} when ! @code{eol-type == lf} results in crashing during garbage collection in ! some pretty obscure place -- an lstream is free when it shouldn't be. ! this is a bad sign. i guess something might be getting initialized too ! early? ! ! we still need to fix the canonicalization-after-decoding code to avoid ! problems with coding systems like `internal-7' showing up. basically, ! when @code{eol==lf} is detected, nil should be returned, and the callers ! should handle it appropriately, eliding when necessary. chain needs to ! recognize when it's got only one (or even 0) items in the chain, and ! elide out the chain. ! ! @heading sep 11, 2001: the day that will live in infamy ! ! rewrite of sep 9 entry about formats: ! ! when calling @samp{make-coding-system}, the name can be a cons of @samp{(format1 . ! format2)}, specifying that it decodes @samp{format1->format2} and encodes the other ! way. if only one name is given, that is assumed to be @samp{format1}, and the ! other is either `external' or `internal' depending on the end type. ! normally the user when decoding gives the decoding order in formats, but ! can leave off the last one, `internal', which is assumed. a multichain ! might look like gzip|multibyte|unicode, using the coding systems named ! `gzip', `(unicode . multibyte)' and `unicode'. the way this actually works ! is by searching for gzip->multibyte; if not found, look for gzip->external ! or gzip->internal. (In general we automatically do conversion between ! internal and external as necessary: thus gzip|crlf does the expected, and ! maps to gzip->external, external->internal, crlf->internal, which when ! fully specified would be gzip|external:external|internal:crlf|internal -- ! see below.) To forcibly fit together two converters that have explicitly ! specified and incompatible names (say you have unicode->multibyte and ! iso8859-1->ebcdic and you know that the multibyte and iso8859-1 in this ! case are compatible), you can force-cast using :, like this: ! ebcdic|iso8859-1:multibyte|unicode. (again, if you force-cast between ! internal and external formats, the conversion happens automatically.) ! ! ! @heading sep 10, 2001 ! ! moved the autodetection stuff (both codesys and eol) into particular coding ! systems -- `undecided' and `convert-eol' (type == `autodetect'). needs ! lots of work. still need to search through the rest of the code and find ! any remaining auto-detect code and move it into the undecided coding ! system. need to modify make-coding-system so that it spits out ! auto-detecting versions of all text-file coding systems unless we say not ! to. need eliminate entirely the EOF flag from both the stream info and the ! coding system; have only the original-eof flag. in ! coding_system_from_mask, need to check that the returned value is not of ! type `undecided', falling back to no-conversion if so. also need to make ! sure we wrap everything appropriate for text-files -- i removed the ! wrapping on set-coding-category-list or whatever (need to check all those ! files to make sure all wrapping is removed). need to review carefully the ! new code in `undecided' to make sure it works are preserves the same logic ! as previously. need to review the closing and rewinding behavior of chain ! and undecided (same -- should really consolidate into helper routines, so ! that any coding system can embed a chain in it) -- make sure the dynarr's ! are getting their data flushed out as necessary, rewound/closed in the ! right order, no missing steps, etc. ! ! also split out mule stuff into @file{mule-coding.c}. work done on ! @file{configure}/@file{xemacs.mak}/@file{Makefile}s not done yet. work ! on @file{emacs.c}/@file{symsinit.h} to interface with the new init ! functions not done yet. ! ! also put in a few declarations of the way i think the abstracted detection ! stuff ought to go. DON'T WORK ON THIS MORE UNTIL THE REST IS DEALT WITH ! AND WE HAVE A WORKING XEMACS AGAIN WITH ALL EOL ISSUES NAILED. ! ! really need a version of @file{cvs-mods} that reports only the current ! directory. WRITE THIS! use it to implement a better ! @file{cvs-checkin}. ! ! @heading sep 9, 2001 ! ! implemented a gzip coding system. unfortunately, doesn't quite work right ! because it doesn't handle the gzip headers -- it just reads and writes raw ! zlib data. there's no function in the library to skip past the header, but ! we do have some code out of the library that we can snarf that implements ! header parsing. we need to snarf that, store it, and output it again at ! the beginning when encoding. in the process, we should create a "get next ! byte" macro that bails out when there are no more. using this, we set up a ! nice way of doing most stuff statelessly -- if we have to bail, we reject ! everything back to the sync point. also need to fix up the autodetection ! of zlib in configure.in. ! ! BIG problems with eol. finished up everything i thought i would need to ! get eol stuff working, but no -- when you have mswindows-unicode, with its ! eol set to autodetect, the detection routines themselves do the autodetect ! (first), and fail (they report CR on CRLF because of the NULL byte between ! the CR and the LF) since they're not looking at ascii data. with a chain ! it's similarly bad. for mswindows-multibyte, for example, which is a chain ! unicode->unicode-to-multibyte, autodetection happens inside of the chain, ! both when unicode and unicode-to-multibyte are active. we could twiddle ! around with the eol flags to try to deal with this, but it's gonna be a ! big mess, which is exactly what we're trying to avoid. what we ! basically want is to entirely rip out all EOL settings from either the ! coding system or the stream (yes, there are two! one might saw ! autodetect, and then the stream contains the actual detected value). ! instead, we simply create an eol-autodetect coding system -- or rather, ! it's part of the convert-eol coding system. convert-eol, type = ! autodetect, does autodetection the first time it gets data sent to it to ! decode, and thereafter sets a stream parameter indicating the actual eol ! type for this stream. this means that all autodetect coding systems, as ! created by @code{make-coding-system}, really are chains with a ! convert-eol at the beginning. only subsidiary xxx-unix has no wrapping ! at all. this should allow eof detection of gzip, unicode, etc. for ! that matter, general autodetection should be entirely encapsulated ! inside of the `autodetect' coding system, with no eol-autodetection -- ! the chain becomes convert-eol (autodetect) -> autodetect or perhaps ! backwards. the generic autodetect similarly has a coding-system in its ! stream methods, and needs somehow or other to insert the detected ! coding-system into the chain. either it contains a chain inside of it ! (perhaps it *IS* a chain), or there's some magic involving ! canonicalization-type switcherooing in the middle of a decode. either ! way, once everything is good and done and we want to save the coding ! system so it can be used later, we need to do another sort of ! canonicalization -- converting auto-detect-type coding systems into the ! detected systems. again, a coding-system method, with some magic ! currently so that subsidiaries get properly used rather than something ! that's new but equivalent to subsidiaries. (#### perhaps we could use a ! hash table to avoid recreating coding systems when not necessary. but ! that would require that coding systems be immutable from external, and ! i'm not sure that's the case.) ! ! i really think, after all, that i should reverse the naming of everything ! in chain and source-sink-type -- they should be decoding-centric. later ! on, if/when we come up with the proper way to make it totally symmetrical, ! we'll be fine whether before then we were encoding or decoding centric. ! ! ! @heading sep 9, 2001 ! ! investigated eol parameter. ! ! implemented handling in @code{make-coding-system} of @code{eol-cr} and ! @code{eol-crlf}. fixed calls everywhere to @code{Fget_coding_system} / ! @code{Ffind_coding_system} to reject non-char->byte coding systems. ! ! still need to handle "query eol type using coding-system-property" so it ! magically returns the right type by parsing the chain. ! ! no work done on formats, as mentioned below. we should consider using : ! instead of || to indicate casting. ! ! @heading early sep 9, 2001 ! ! renamed some codesys properties: `list' in chain -> chain; `subtype' in ! unicode -> type. everything compiles again and sort of works; some CRLF ! problems that may resolve themselves when i finish the convert-eol stuff. ! the stuff to create subsidiaries has been rewritten to use chains; but i ! still need to investigate how the EOL type parameter is used. also, still ! need to implement this: when a coding system is created, and its eol type ! is not autodetect or lf, a chain needs to be created and returned. i think ! that what needs to happen is that the eol type can only be set to ! autodetect or lf; later on this should be changed to simply be either ! autodetect or not (but that would require ripping out the eol converting ! stuff in the various coding systems), and eventually we will do the work on ! the detection mechanism so it can do chain detection; then we won't need an ! eol autodetect setting at all. i think there's a way to query the eol type ! of a coding system; this should check to see if the coding system is a ! chain and there's a convert-eol at the front; if so, the eol type comes ! from the type of the convert-eol. ! ! also check out everywhere that @code{Fget_coding_system} or ! @code{Ffind_coding_system} is called, and see whether anything but a ! char->byte system can be tolerated. create a new function for all the ! places that only want char->byte, something like ! @samp{get_coding_system_char_to_byte_only}. ! ! think about specifying formats in make-coding-system. perhaps the name can ! be a cons of (format1, format2), specifying that it encodes ! format1->format2 and decodes the other way. if only one name is given, ! that is assumed to be format2, and the other is either `byte' or `char' ! depending on the end type. normally the user when decoding gives the ! decoding order in formats, but can leave off the last one, `char', which is ! assumed. perhaps we should say `internal' instead of `char' and `external' ! instead of byte. a multichain might look like gzip|multibyte|unicode, ! using the coding systems named `gzip', `(unicode . multibyte)' and ! `unicode'. we would have to allow something where one format is given only ! as generic byte/char or internal/external to fit with any of the same ! byte/char type. when forcibly fitting together two converters that have ! explicitly specified and incompatible names (say you have ! unicode->multibyte and iso8859-1->ebcdic and you know that the multibyte ! and iso8859-1 in this case are compatible), you can force-cast using ||, ! like this: ebcdic|iso8859-1||multibyte|unicode. this will also force ! external->internal translation as necessary: ! unicode|multibyte||crlf|internal does unicode->multibyte, ! external->internal, crlf->internal. perhaps you'd need to put in the ! internal translation, like this: unicode|multibyte|internal||crlf|internal, ! which means unicode->multibyte, external->internal (multibyte is compatible ! with external); force-cast to crlf format and convert crlf->internal. ! ! @heading even later: Sep 8, 2001 ! ! chain doesn't need to set character mode, that happens automatically when ! the coding systems are created. fixed chain to return correct source/sink ! type for itself and to check the compatibility of source/sink types in its ! chain. fixed decode/encode-coding-region to check the source and sink ! types of the coding system performing the conversion and insert appropriate ! byte->char/char->byte converters (aka "binary" coding system). fixed ! set-coding-category-system to only accept the traditional ! encode-char-to-byte types of coding systems. ! ! still need to extend chain to specify the parameters mentioned below, ! esp. "reverse". also need to extend the print mechanism for chain so it ! prints out the chain. probably this should be general: have a new method ! to return all properties, and output those properties. you could also ! implement a read syntax for coding systems this way. ! ! still need to implement @code{convert-eol} and finish up the rest of the ! eol stuff mentioned below. ! ! @heading later September 7, 2001 (more like Sep 8) ! ! moved many @code{Lisp_Coding_System *} params to @code{Lisp_Object}. In ! general this is the way to go, and if we ever implement a copying GC, we ! will never want to be passing direct pointers around. With no ! error-checking, we lose no cycles using @code{Lisp_Object}s in place of ! pointers -- the @code{Lisp_Object} itself is nothing but a pointer, and ! so all the casts and "dereferences" boil down to nothing. ! ! Clarified and cleaned up the "character mode" on streams, and documented ! who (caller or object itself) has the right to be setting character mode ! on a stream, depending on whether it's a read or write stream. changed ! @code{conversion_end_type} method and @code{enum source_sink_type} to ! return encoding-centric values, rather than decoding-centric. for the ! moment, we're going to be entirely encoding-centric in everything; we ! can rethink later. fixed coding systems so that the decode and encode ! methods are guaranteed to receive only full characters, if that's the ! source type of the data, as per conversion_end_type. ! ! still need to fix the chain method so that it correctly sets the ! character mode on all the lstreams in it and checks the source/sink ! types to be compatible. also fix @code{decode-coding-string} and ! friends to put the appropriate byte->character ! (i.e. @code{no-conversion}) coding systems on the ends as necessary so ! that the final ends are both character. also add to chain a parameter ! giving the ability to switch the direction of conversion of any ! particular item in the chain (i.e. swap encoding and decoding). i think ! what we really want to do is allow for arbitrary parameters to be put ! onto a particular coding system in the chain, of which the only one so ! far is swap-encode-decode. don't need too much codage here for that, ! but make the design extendable. ! ! ! ! @heading September 7, 2001 ! ! just added a return value from the decode and encode methods of a coding ! system, so that some of the data can get rejected. fixed the calling ! routines to handle this. need to investigate when and whether the coding ! lstream is set to character mode, so that the decode/encode methods only ! get whole characters. if not, we should do so, according to the source ! type of these methods. also need to implement the convert_eol coding ! system, and fix the subsidiary coding systems (and in general, any coding ! system where the eol type is specified and is not LF) to be chains ! involving convert_eol. ! ! after everything is working, need to remove eol handling from encode/decode ! methods and eventually consider rewriting (simplifying) them given the ! reject ability. ! ! @heading September 5, 2001 ! ! @itemize ! @item ! need to organize this. get everything below into the TODO list. ! CVS the TODO list frequently so i can delete old stuff. prioritize ! it!!!!!!!!! ! ! @item ! move @file{README.ben-mule...} to @file{STATUS.ben-mule...}; use ! @file{README} for intro, overview of what's new, what's broken, how to ! use the features, etc. ! ! @item ! need a global and local @samp{coding-category-precedence} list, which ! get merged. ! ! @item ! finished the BOM support. also finished something not listed below, ! expansion to the auto-generator of Unicode-encapsulation to support ! bracketing code with @samp{#if ... #endif}, for Cygwin and MINGW ! problems, e.g. This is tested; appears to work. ! ! @item ! need to add more multibyte coding systems now that we have various ! properties to specify them. need to add DEFUN's for mac-code-page ! and ebcdic-code-page for completeness. need to rethink the whole ! way that the priority list works. it will continue to be total ! junk until multiple levels of likeliness get implemented. ! ! @item ! need to finish up the stuff about the various defaults. [need to ! investigate more generally where all the different default values ! are that control encoding. (there are six places or so.) need to ! list them in @code{make-coding-system} docs and put pointers ! elsewhere. [[[[#### what interface to specify that this default ! should be unicode? a "Unicode" language environment seems too ! drastic, as the language environment controls much more.]]]] even ! skipping the Unicode stuff here, we need to survey and list the ! variables that control coding page behavior and determine how they ! need to be set for various possible scenarios: ! ! @itemize ! @item ! total binary: no detection at all. ! ! @item ! raw-text only: wants only autodetection of line endings, nothing else. ! ! @item ! "standard Windows environment": tries for Unicode, falls back on ! code page encoding. ! ! @item ! some sort of East European environment, and Russian. ! ! @item ! some sort of standard Japanese Windows environment. ! ! @item ! standard Chinese Windows environments (traditional and simplified) ! ! @item ! various Unix environments (European, Japanese, Russian, etc.) ! ! @item ! Unicode support in all of these when it's reasonable ! @end itemize ! @end itemize ! ! These really require multiple likelihood levels to be fully ! implementable. We should see what can be done ("gracefully fall ! back") with single likelihood level. need lots of testing. ! ! @itemize ! @item ! need to fix the truename problem. ! ! @item ! lots of testing: need to test all of the stuff above and below that's ! recently been implemented. ! @end itemize ! ! ! @heading September 4, 2001 ! ! mostly everything compiles. currently there is a crash in ! @code{parse-unicode-translation-table}, and Cygwin/Mule won't run. it ! may well be a bug in the @code{sscanf()} in Cygwin. ! ! working on today: ! ! @itemize ! @item ! adding BOM support for Unicode coding systems. mostly there, but ! need to finish adding BOM support to the detection routines. then test. ! ! @item ! adding properties to @code{unicode-to-multibyte} to specify the coding ! system in various flexible ways, e.g. directly specified code page or ! ansi or oem code page of specified locale, current locale, user-default ! or system-default locale. need to test. ! ! @item ! creating a `multibyte' coding system, with the same parameters as ! unicode-to-multibyte and which resolves at coding-system-creation ! time to the appropriate chain. creating the underlying mechanism ! to allow such under-the-scenes switcheroo. need to test. ! ! @item ! set default-value of @code{buffer-file-coding-system} to ! mswindows-multibyte, as Matej said it should be. need to test. ! need to investigate more generally where all the different default ! values are that control encoding. (there are six places or so.) ! need to list them in make-coding-system docs and put pointers ! elsewhere. #### what interface to specify that this default should ! be unicode? a "Unicode" language environment seems too drastic, as ! the language environment controls much more. ! ! @item ! thinking about adding multiple levels of certainty to the detection ! schemes, instead of just a mask. eventually, we need to totally ! abstract things, but that can easier be done in many steps. (we ! need multiple levels of likelihood to more reasonably support a ! Windows environment with code-page type files. currently, in order ! to get them detected, we have to put them first, because they can ! look like lots of other things; but then, other encodings don't get ! detected. with multiple levels of likelihood, we still put the ! code-page categories first, but they will return low levels of ! likelihood. Lower-down encodings may be able to return higher ! levels of likelihood, and will get taken preferentially.) ! ! @item ! making it so you cannot disable file-coding, but you get an ! equivalent default on Unix non-Mule systems where all defaults are ! `binary'. need to test!!!!!!!!! ! @end itemize ! ! Matej (mostly, + some others) notes the following problems, and here ! are possible solutions: ! ! @itemize ! @item ! he wants the defaults to work right. [figure out what those ! defaults are. i presume they are auto-detection of data in current ! code page and in unicode, and new files have current code page set ! as their output encoding.] ! ! @item ! too easy to lose data with incorrect encodings. [need to set up an ! error system for encoding/decoding. extremely important but a ! little tricky to implement so let's deal with other issues now.] ! ! @item ! EOL isn't always detected correctly. [#### ?? need examples] ! ! @item ! truename isn't working: @file{c:\t.txt} and @file{c:\tmp.txt} have the ! same truename. [should be easy to fix] ! ! @item ! unicode files lose the BOM mark. [working on this] ! ! @item ! command-line utilities use OEM. [actually it seems more ! complicated. it seems they use the codepage of the console. we ! may be able to set that, e.g. to UTF8, before we invoke a command. ! need to investigate.] ! ! @item ! no way to handle unicode characters not recognized as charsets. [we ! need to create something like 8 private 2-dimensional charsets to ! handle all BMP Unicode chars. Obviously this is a stopgap ! solution. Switching to Unicode internal will ultimately make life ! far easier and remove the BMP limitation. but for now it will ! work. we translate all characters where we have charsets into ! chars in those charsets, and the remainder in a unicode charset. ! that way we can save them out again and guarantee no data loss with ! unicode. this creates font problems, though ...] ! ! @item ! problems with xemacs font handling. [xemacs font handling is not ! sophisticated enough. it goes on a charset granularity basis and ! only looks for a font whose name contains the corresponding windows ! charset in it. with unicode this fails in various ways. for one ! the granularity needs to be single character, so that those unicode ! charsets mentioned above work; and it needs to query the font to ! see what unicode ranges it supports, rather than just looking at ! the charset ending.] ! @end itemize ! ! ! @heading August 28, 2001 ! ! working on getting everything to compile again: Cygwin, non-MULE, ! pdump. not there yet. ! ! @code{mswindows-multibyte} is now defined using chain, and works. ! removed most vestiges of the @code{mswindows-multibyte} coding system ! type. ! ! file-coding is on by default; should default to binary only on Unix. ! Need to test. (Needs to compile first :-) ! ! @heading August 26, 2001 ! ! I've fixed the issue of inputting non-ASCII text under -nuni, and done ! some of the work on the Russian @key{C-x} problem -- we now compute the ! other possibilities. We still need to fix the key-lookup code, though, ! and that code is unfortunately a bit ugly. the best way, it seems, is ! to expand the command-builder structure so you can specify different ! interpretations for keys. (if we do find an alternative binding, though, ! we need to mess with both the command builder and this-command-keys, as ! does the function-key stuff. probably need to abstract that munging ! code.) ! ! high-priority: ! ! @table @strong ! ! @item [currently doing] ! ! @itemize ! @item ! support for @code{WM_IME_CHAR}. IME input can work under @code{-nuni} ! if we use @code{WM_IME_CHAR}. probably we should always be using this, ! instead of snarfing input using @code{WM_COMPOSITION}. i'll check this ! out. ! ! @item ! Russian @key{C-x} problem. see above. ! @end itemize ! ! @item [clean-up] ! ! @itemize ! @item ! make sure it compiles and runs under non-mule. remember that some ! code needs the unicode support, or at least a simple version of it. ! ! @item ! make sure it compiles and runs under pdump. see below. ! ! @item ! clean up @code{mswindows-multibyte}, @code{TSTR_TO_C_STRING}. see ! below. [DONE] ! ! @item ! eliminate last vestiges of codepage<->charset conversion and similar stuff. ! @end itemize ! ! @item [other] ! ! @itemize ! @item ! cut and paste. see below. ! @item ! misc issues with handling lang environments. see also August 25, ! "finally: working on the C-x in ...". ! @itemize ! @item ! when switching lang env, needs to set keyboard layout. ! @item ! user var to control whether, when moving into text of a ! particular language, we set the appropriate keyboard layout. we ! would need to have a lisp api for retrieving and setting the ! keyboard layout, set text properties to indicate the layout of ! text, and have a way of dealing with text with no property on ! it. (e.g. saved text has no text properties on it.) basically, ! we need to get a keyboard layout from a charset; getting a ! language would do. Perhaps we need a table that maps charsets ! to language environments. ! @item ! test that the lang env is properly set at startup. test that ! switching the lang env properly sets the C locale (call ! setlocale(), set LANG, etc.) -- a spawned subprogram should have ! the new locale in its environment. ! @end itemize ! @item ! look through everything below and see if anything is missed in this ! priority list, and if so add it. create a separate file for the ! priority list, so it can be updated as appropriate. ! @end itemize ! @end table ! ! mid-priority: ! ! @itemize ! @item ! clean up the chain coding system. its list should specify decode ! order, not encode; i now think this way is more logical. it should ! check the endpoints to make sure they make sense. it should also ! allow for the specification of "reverse-direction coding systems": ! use the specified coding system, but invert the sense of decode and ! encode. ! ! @item ! along with that, places that take an arbitrary coding system and ! expect the ends to be anything specific need to check this, and add ! the appropriate conversions from byte->char or char->byte. ! ! @item ! get some support for arabic, thai, vietnamese, japanese jisx 0212: ! at least get the unicode information in place and make sure we have ! things tied together so that we can display them. worry about r2l ! some other time. ! @end itemize ! ! @heading August 25, 2001 ! ! There is actually more non-Unicode-ized stuff, but it's basically ! inconsequential. (See previous note.) You can check using the file ! nmkun.txt (#### RENAME), which is just a list of all the routines that ! have been split. (It was generated from the output of `nmake ! unicode-encapsulate', after removing everything from the output but ! the function names.) Use something like ! ! @example ! fgrep -f ../nmkun.txt -w [a-hj-z]*.[ch] |m ! @end example ! ! in the source directory, which does a word match and skips ! @file{intl-unicode-win32.[ch]} and @file{intl-win32.[ch]}, which have a ! whole lot of references to these, unavoidably. It effectively detects ! what needs to be changed because changed versions either begin ! @samp{qxe...} or end with A or W, and in each case there's no whole-word ! match. ! ! The nasty bug has been fixed below. The @code{-nuni} option now works ! -- all specially-written code to handle the encapsulation has been ! tested by some operation (fonts by loadup and checking the output of ! @code{(list-fonts "")}; devmode by printing; dragdrop tests other ! stuff). ! ! NOTE: for @code{-nuni} (Win 95), areas need work: ! ! @itemize ! @item ! cut and paste. we should be able to receive Unicode text if it's there, ! and we should be able to receive it even in Win 95 or @code{-nuni}. we ! should just check in all circumstances. also, under 95, when we put ! some text in the clipboard, it may or may not also be automatically ! enumerated as unicode. we need to test this out and/or just go ahead ! and manually do the unicode enumeration. ! ! @item ! receiving keyboard input. we get only a single byte, but we should ! be able to correlate the language of the keyboard layout to a ! particular code page, so we can then decode it correctly. ! ! @item ! @code{mswindows-multibyte}. still implemented as its own thing. should ! be done as a chain of (encoding) unicode | unicode-to-multibyte. need ! to turn this on, get it working, and look into optimizations in the dfc ! stuff. (#### perhaps there's a general way to do these optimizations??? ! something like having a method on a coding system that can specify ! whether a pure-ASCII string gets rendered as pure-ASCII bytes and ! vice-versa.) ! @end itemize ! ! ALSO: ! ! @itemize ! @item ! we have special macros @code{TSTR_TO_C_STRING} and such because formerly ! the @samp{DFC} macros didn't know about external stuff that was Unicode ! encoded and would call @code{strlen()} on them. this is fixed, so now ! we should undo the special macros, make em normal, removal the comments ! about this, and make sure it works. [DONE] ! ! ! @item ! finally: working on the @kbd{C-x} in Russian key layout problem. in the ! process will probably end up doing work on cleaning up the handling ! of keyboard layouts, integrating or deleting the FSF stuff, adding ! code to change the keyboard layout as we move in and out of text in ! different languages (implemented as a post-command-hook; we need ! something like internal-post-command-hook if not already there, for ! internal stuff that doesn't want to get mixed up with the regular ! post-command-hook; similar for pre-command-hook). also, when ! langenv changes, ways to set the keyboard layout appropriately. ! ! @item ! i think the stuff above is higher priority than the other stuff ! mentioned below. what i'm aiming for is to be able to input and ! work with multiple languages without weird glitches, both under 95 ! and NT. the problems above are all basic impediments to such work. ! we assume for the moment that the user can make use of the existing ! file i/o conversion stuff, and put that lower in priority, after ! the basic input is working. ! ! @item ! i should get my modem connected and write up what's going on and ! send it to the lists; also cvs commit my workspaces and get more ! testers. ! @end itemize ! ! August 24, 2001: ! ! All code has been Unicode-ized except for some stuff in console-msw.c ! that deals with console output. Much of the Unicode-encapsulation ! stuff, particularly the hand-written stuff, really needs testing. I ! added a new command-line option, @code{-nuni}, to force use of all ANSI ! calls -- @code{XE_UNICODEP} evaluates to false in this case. ! ! There is a nasty bug that appeared recently, probably when the event ! code got Unicode-ized -- bad interactions with OS sticky modifiers. ! Hold the shift key down and release it, then instead of affecting the ! next char only, it gets permanently stuck on (until you do a regular ! shift+char stroke). This needs to be debugged. ! ! Other things on agenda: ! ! @itemize ! @item ! go through and prioritize what's listed below. ! ! @item ! make sure the pdump code can compile and work. for the moment we ! just don't try to dump any Unicode tables and load them up each ! time. this is certainly fast but ... ! ! @item ! there's the problem that XEmacs can't be run in a directory with ! non-ASCII/Latin-1 chars in it, since it will be doing Unicode processing ! before we've had a chance to load the tables. In fact, even finding the ! tables in such a situation is problematic using the normal commands. my ! idea is to eventually load the stuff extremely extremely early, at the ! same time as the pdump data gets loaded. in fact, the unicode table ! data (stored in an efficient binary format) can even be stuck into the ! pdump file (which would mean as a resource to the executable, for ! windows). we'd need to extend pdump a bit: to allow for attaching extra ! data to the pdump file. (something like @code{pdump_attach_extra_data ! (addr, length)} returns a number of some sort, an index into the file, ! which you can then retrieve with @code{pdump_load_extra_data()}, which ! returns an addr (@code{mmap()}ed or loaded), and later you ! @code{pdump_unload_extra_data()} when finished. we'd probably also need ! @code{pdump_attach_extra_data_append()}, which appends data to the data ! just written out with @code{pdump_attach_extra_data()}. this way, ! multiple tables in memory can be written out into one contiguous ! table. (we'd use the tar-like trick of allowing new blocks to be written ! without going back to change the old blocks -- we just rely on the end ! of file/end of memory.) this same mechanism could be extracted out of ! pdump and used to handle the non-pdump situation (or alternatively, we ! could just dump either the memory image of the tables themselves or the ! compressed binary version). in the case of extra unicode tables not ! known about at compile time that get loaded before dumping, we either ! just dump them into the image (pdump and all) or extract them into the ! compressed binary format, free the original tables, and treat them like ! all other tables. ! ! @item ! @kbd{C-x b} when using a Russian keyboard layout. XEmacs currently ! tries to interpret @samp{C+cyrillic char}, which causes an error. We ! want @kbd{C-x b} to still work even when the keyboard normally generates ! Cyrillic. What we should do is expand the keyboard event structure so ! that it contains not only the actual char, but what the char would have ! been in various other keyboard layouts, and in contexts where only ! certain keystrokes make sense (creating control chars, and looking up in ! keymaps), we proceed in order, processing each of them until we get ! something. order should be something like: current keyboard layout; ! layout of the current language environment; layout of the user's default ! language; layout of the system default language; layout of US English. ! ! @item ! reading and writing Unicode files. multiple problems: ! ! @itemize ! @item ! EOL's aren't handled right. for the moment, just fix the ! Unicode coding systems; later on, create EOL-only coding ! systems: ! ! @enumerate ! @item ! they would be character->character and operate next to the ! internal data; this means that coding systems need to be able ! to handle ends of lines that are either CR, LF, or CRLF. ! usually this isn't a problem, as they are just characters ! like any other and get encoded appropriately. however, ! coding systems that are line-oriented need to recognize any ! of the three as line endings. ! ! @item ! we'd also have to complete the stuff that handles coding ! systems where either end can be byte or char (four ! possibilities total; use a single enum such as ! @code{ENCODES_CHAR_TO_BYTE}, @code{ENCODES_BYTE_TO_BYTE}, etc.). ! ! @item ! we'd need ways of specifying the chaining of coding systems. ! e.g. when reading a coding system, a user can specify more ! than one with a | symbol between them. when a context calls ! for a coding system and a chain is needed, the `chain' coding ! system is useful; but we should really expand the contexts ! where a list of coding systems can be given, and whenever ! possible try to inline the chain instead of using a ! surrounding @code{chain} coding system. ! ! @item ! the @code{chain} needs some work so that it passes all sorts of ! lstream commands down to the chain inside it -- it should be ! entirely transparent and the fact that there's actually a ! surrounding coding system should be invisible. more general ! coding system methods might need to be created. ! ! @item ! important: we need a way of specifying how detecting works ! when we have more than one coding system. we might need more ! than a single priority list. need to think about this. ! @end enumerate ! ! @item ! Unicode files beginning with the BOM are not recognized as such. ! we need to fix this; but to make things sensible, we really need ! to add the idea of different levels of confidence regarding ! what's detected. otherwise, Unicode says "yes this is me" but ! others higher up do too. in the process we should probably ! finish abstracting the detection system and fix up some ! stupidities in it. ! ! @item ! When writing a file, we need error detection; otherwise somebody ! will create a Unicode file without realizing the coding system ! of the buffer is Raw, and then lose all the non-ASCII/Latin-1 ! text when it's written out. We need two levels ! ! @enumerate ! @item ! first, a "safe-charset" level that checks before any actual ! encoding to see if all characters in the document can safely ! be represented using the given coding system. FSF has a ! "safe-charset" property of coding systems, but it's stupid ! because this information can be automatically derived from ! the coding system, at least the vast majority of the time. ! What we need is some sort of ! alternative-coding-system-precedence-list, langenv-specific, ! where everything on it can be checked for safe charsets and ! then the user given a list of possibilities. When the user ! does "save with specified encoding", they should see the same ! precedence list. Again like with other precedence lists, ! there's also a global one, and presumably all coding systems ! not on other list get appended to the end (and perhaps not ! checked at all when doing safe-checking?). safe-checking ! should work something like this: compile a list of all ! charsets used in the buffer, along with a count of chars ! used. that way, "slightly unsafe" charsets can perhaps be ! presented at the end, which will lose only a few characters ! and are perhaps what the users were looking for. ! ! @item ! when actually writing out, we need error checking in case an ! individual char in a charset can't be written even though the ! charsets are safe. again, the user gets the choice of other ! reasonable coding systems. ! ! @item ! same thing (error checking, list of alternatives, etc.) needs ! to happen when reading! all of this will be a lot of work! ! @end enumerate ! @end itemize ! @end itemize ! ! ! ! @heading Announcement, August 20, 2001: ! ! I'm looking for testers. There is a complete and fast implementation ! in C of Unicode conversion, translations for almost all of the ! standardly-defined charsets that load up automatically and ! instantaneously at runtime, coding systems supporting the common ! external representations of Unicode [utf-16, ucs-4, utf-8, ! little-endian versions of utf-16 and ucs-4; utf-7 is sitting there ! with abort[]s where the coding routines should go, just waiting for ! somebody to implement], and a nice set of primitives for translating ! characters<->codepoints and setting the priority lists used to control ! codepoint->char lookup. ! ! It's so far hooked into one place: the Windows IME. Currently I can ! select the Japanese IME from the thing on my tray pad in the lower ! right corner of the screen, and type Japanese into XEmacs, and you get ! Japanese in XEmacs -- regardless of whether you set either your ! current or global system locale to Japanese,and regardless of whether ! you set your XEmacs lang env as Japanese. This should work for many ! other languages, too -- Cyrillic, Chinese either Traditional or ! Simplified, and many others, but YMMV. There may be some lurking ! bugs (hardly surprising for something so raw). ! ! To get at this, checkout using `ben-mule-21-5', NOT the simpler ! *`mule-21-5'. For example ! ! cvs -d :pserver:xemacs@@cvs.xemacs.org:/usr/CVSroot checkout -r ben-mule-21-5 xemacs ! ! or you get the idea. the `-r ben-mule-21-5' is important. ! ! I keep track of my progress in a file called README.ben-mule-21-5 in ! the root directory of the source tree. ! ! WARNING: Pdump might not work. Will be fixed rsn. ! ! @heading August 20, 2001 ! ! @itemize ! @item ! still need to sort out demand loading, binary format, etc. figure ! out what the goals are and how we're going to achieve them. for ! the moment let's just say that running XEmacs in a directory with ! Japanese or other weird characters in the name is likely to cause ! problems under MS Windows, but once XEmacs is initialized (and ! before processing init files), all Unicode support is there. ! ! @item ! wrote the size computation routines, although not yet tested. ! ! @item ! lots more abstraction of coding systems; almost done. ! ! @item ! UNICODE WORKS!!!!! ! @end itemize ! ! @heading August 19, 2001 ! ! Still needed on the Unicode support: ! ! @itemize ! @item ! demand loading: load the Unicode table data the first time a ! conversion needs to be done. ! ! @item ! maybe: table size computation: figure out how big the in-memory ! tables actually are. ! ! @item ! maybe: create a space-efficient binary format for the data, and a ! way to dump out an existing charset's data into this binary format. ! it should allow for many such groups of data to be appended ! together in one file, such that you can just append the new data ! onto the end and not have to go back and modify anything ! previously. (like how tar archives work, and how the UFS? for ! CD-R's and CD-RW's works.) ! ! @item ! maybe: figure out how to be able to access the Unicode tables at ! @code{init_intl()} time, before we know how to get at data-directory; ! that way we can handle the need for unicode conversions that come up ! very early, for example if XEmacs is run from a directory containing ! Japanese in it. Presumably we'd want to generalize the stuff in ! @file{pdump.c} that deals with the dumper file, so that it can handle ! other files -- putting the file either in the directory of the ! executable or in a resource, maybe actually attached to the pdump file ! itself -- or maybe we just dump the data into the actual executable. ! With pdump we could extend pdump to allow for data that's in the pdump ! file but not actually mapped at startup, separate from the data that ! does get mapped -- and then at runtime the pointer gets restored not ! with a real pointer but an offset into the file; another pdump call and ! we get some way to access the data. (tricky because it might be in a ! resource, not a file. we might have to just tell pdump to mmap or ! whatever the data in, and then tell pdump to release it.) ! ! @item ! fix multibyte to use unicode. at first, just reverse ! @code{mswindows-multibyte-to-unicode} to be @code{unicode-to-multibyte}; ! later implement something in chain to allow for reversal, for declaring ! the ends of the coding systems, etc. ! ! @item ! actually make sure that the IME stuff is working!!! ! @end itemize ! ! Other things before announcing: ! ! @itemize ! @item ! change so that the Unicode tables are not pdumped. This means we need ! to free any table data out there. Make sure that pdump compiles and try ! to finish the pretty-much-already-done stuff already with ! @code{XD_STRUCT_ARRAY} and dynamic size computation; just need to see ! what's going on with @code{LO_LINK}. ! @end itemize ! ! @heading August 14, 2001 ! ! To do a diff between this workspace and the mainline, use the most recent sync tags, currently: ! ! @example ! cvs diff -r main-branch-ben-mule-21-5-aug-11-2001-sync -r ben-mule-21-5-post-aug-11-2001-sync ! @end example ! ! Unicode support: ! ! Unicode support is important for supporting many languages under ! Windows, such as Cyrillic, without resorting to translation tables for ! particular Windows-specific code pages. Internally, all characters in ! Windows can be represented in two encodings: code pages and Unicode. ! With Unicode support, we can seamlessly support all Windows ! characters. Currently, the test in the drive to support Unicode is if ! IME input works properly, since it is being converted from Unicode. ! ! Unicode support also requires that the various Windows API's be ! "Unicode-encapsulated", so that they automatically call the ANSI or ! Unicode version of the API call appropriately and handle the size ! differences in structures. What this means is: ! ! @itemize ! @item ! first, note that Windows already provides a sort of encapsulation ! of all API's that deal with text. All such API's are underlyingly ! provided in two versions, with an A or W suffix (ANSI or "wide" ! i.e. Unicode), and the compile-time constant UNICODE controls which ! is selected by the unsuffixed API. Same thing happens with ! structures. Unfortunately, this is compile-time only, not ! run-time, so not sufficient. (Creating the necessary run-time ! encoding is not conceptually difficult, but very time-consuming to ! write. It adds no significant overhead, and the only reason it's ! not standard in Windows is conscious marketing attempts by ! Microsoft to cripple Windows 95. FUCK MICROSOFT! They even ! describe in a KnowledgeBase article exactly how to create such an ! API [although we don't exactly follow their procedure], and point ! out its usefulness; the procedure is also described more generally ! in Nadine Kano's book on Win32 internationalization -- written SIX ! YEARS AGO! Obviously Microsoft has such an API available ! internally.) ! ! @item ! what we do is provide an encapsulation of each standard Windows API ! call that is split into A and W versions. current theory is to ! avoid all preprocessor games; so we name the function with a prefix ! -- "qxe" currently -- and require callers to use the prefixed name. ! Callers need to explicitly use the W version of all structures, and ! convert text themselves using @code{Qmswindows_tstr}. the qxe ! encapsulated version will automatically call the appropriate A or W ! version depending on whether we're running on 9x or NT, and copy ! data between W and A versions of the structures as necessary. ! ! @item ! We require the caller to handle the actual translation of text to ! avoid possible overflow when dealing with fixed-size Windows ! structures. There are no such problems when copying data between ! the A and W versions because ANSI text is never larger than its ! equivalent Unicode representation. ! ! @item ! We allow for incremental creation of the encapsulated routines by using ! the coding system @code{Qmswindows_tstr_notyet}. This is an alias for ! @code{Qmswindows_multibyte}, i.e. it always converts to ANSI; but it ! indicates that it will be changed to @code{Qmswindows_tstr} when we have ! a qxe version of the API call that the data is being passed to and ! change the code to use the new function. ! @end itemize ! ! Besides creating the encapsulation, the following needs to be done for ! Unicode support: ! ! @itemize ! @item ! No actual translation tables are fed into XEmacs. We need to ! provide glue code to read the tables in @file{etc/unicode}. See ! @file{etc/unicode/README} for the interface to implement. ! ! @item ! Fix pdump. The translation tables for Unicode characters function as ! unions of structures with different numbers of indirection levels, in ! order to be efficient. pdump doesn't yet support such unions. ! @file{charset.h} has a general description of how the translation tables ! work, and the pdump code has constants added for the new required data ! types, and descriptions of how these should work. ! ! @item ! ultimately, there's no end to additional work (composition, bidi ! reordering, glyph shaping/ordering, etc.), but the above is enough ! to get basic translation working. ! @end itemize ! ! Merging this workspace into the trunk requires some work. ChangeLogs ! have not yet been created. Also, there is a lot of additional code in ! this workspace other than just Windows and Unicode stuff. Some of the ! changes have been somewhat disruptive to the code base, in particular: ! ! @itemize ! @item ! the code that handles the details of processing multilingual text has ! been consolidated to make it easier to extend it. it has been yanked ! out of various files (@file{buffer.h}, @file{mule-charset.h}, ! @file{lisp.h}, @file{insdel.c}, @file{fns.c}, @file{file-coding.c}, ! etc.) and put into @file{text.c} and @file{text.h}. ! @file{mule-charset.h} has also been renamed @file{charset.h}. all long ! comments concerning the representations and their processing have been ! consolidated into @file{text.c}. ! ! @item ! @file{nt/config.h} has been eliminated and everything in it merged into ! @file{config.h.in} and @file{s/windowsnt.h}. see @file{config.h.in} for ! more info. ! ! @item ! @file{s/windowsnt.h} has been completely rewritten, and ! @file{s/cygwin32.h} and @file{s/mingw32.h} have been largely rewritten. ! tons of dead weight has been removed, and stuff common to more than one ! file has been isolated into @file{s/win32-common.h} and ! @file{s/win32-native.h}, similar to what's already done for usg ! variants. ! ! @item ! large amounts of code throughout the code base have been Mule-ized, ! not just Windows code. ! ! @item ! @file{file-coding.c/.h} have been largely rewritten (although still ! mostly syncable); see below. ! @end itemize ! ! ! @heading June 26, 2001 ! ! ben-mule-21-5 ! ! this contains all the mule work i've been doing. this includes mostly ! work done to get mule working under ms windows, but in the process ! i've [of course] fixed a whole lot of other things as well, mostly ! mule issues. the specifics: ! ! @itemize ! @item ! it compiles and runs under windows and should basically work. the ! stuff remaining to do is (a) improved unicode support (see below) ! and (b) smarter handling of keyboard layouts. in particular, it ! should (1) set the right keyboard layout when you change your ! language environment; (2) optionally (a user var) set the ! appropriate keyboard layout as you move the cursor into text in a ! particular language. ! ! @item ! i added a bunch of code to better support OS locales. it tries to ! notice your locale at startup and set the language environment ! accordingly (this more or less works), and call setlocale() and set ! LANG when you change the language environment (may or may not work). ! ! @item ! major rewriting of file-coding. it's mostly abstracted into coding ! systems that are defined by methods (similar to devices and ! specifiers), with the ultimate aim being to allow non-i18n coding ! systems such as gzip. there is a "chain" coding system that allows ! multiple coding systems to be chained together. (it doesn't yet ! have the concept that either end of a coding system can be bytes or ! chars; this needs to be added.) ! ! @item ! unicode support. very raw. a few days ago i wrote a complete and ! efficient implementation of unicode translation. it should be very ! fast, and fairly memory-efficient in its tables. it allows for ! charset priority lists, which should be language-environment ! specific (but i haven't yet written the glue code). it works in ! preliminary testing, but obviously needs more testing and work. ! as of yet there is no translation data added for the standard charsets. ! the tables are in etc/unicode, and all we need is a bit of glue code ! to process them. see etc/unicode/README for the interface to ! implement. ! ! @item ! support for unicode in windows is partly there. this will work even ! on windows 95. the basic model is implemented but it needs finishing ! up. ! ! @item ! there is a preliminary implementation of windows ime support courtesy ! of ikeyama. ! ! @item ! if you want to get cyrillic working under windows (it appears to "work" ! but the wrong chars currently appear), the best way is to add unicode ! support for iso-8859-5 and use it in redisplay-msw.c. we are already ! passing unicode codepoints to the text-draw routine (ExtTextOutW). ! (ExtTextOutW and GetTextExtentPoint32W are implemented on both 95 and NT.) ! ! @item ! i fixed the iso2022 handling so it will correctly read in files ! containing unknown charsets, creating a "temporary" charset which can ! later be overwritten by the real charset when it's defined. this allows ! iso2022 elisp files with literals in strange languages to compile ! correctly under mule. i also added a hack that will correctly read in ! and write out the emacs-specific "composition" escape sequences, ! i.e. @samp{ESC 0} through @samp{ESC 4}. this means that my workspace correctly ! compiles the new file @file{devanagari.el} that i added (see below). ! ! @item ! i copied the remaining language-specific files from fsf. i made ! some minor changes in certain cases but for the most part the stuff ! was just copied and may not work. ! ! @item ! i fixed @code{post-read-conversion} in coding systems to follow fsf ! conventions. (i also support our convention, for the moment. a ! kludge, of course.) ! ! @item ! @code{make-coding-system} accepts (but ignores) the additional properties ! present in the fsf version, for compatibility. ! @end itemize ! ! ! ! @node Consoles; Devices; Frames; Windows, The Redisplay Mechanism, Multilingual Support, Top ! @chapter Consoles; Devices; Frames; Windows ! @cindex consoles; devices; frames; windows ! @cindex devices; frames; windows, consoles; ! @cindex frames; windows, consoles; devices; ! @cindex windows, consoles; devices; frames; ! ! @menu ! * Introduction to Consoles; Devices; Frames; Windows:: ! * Point:: ! * Window Hierarchy:: ! * The Window Object:: ! * Modules for the Basic Displayable Lisp Objects:: ! @end menu ! ! @node Introduction to Consoles; Devices; Frames; Windows, Point, Consoles; Devices; Frames; Windows, Consoles; Devices; Frames; Windows ! @section Introduction to Consoles; Devices; Frames; Windows ! @cindex consoles; devices; frames; windows, introduction to ! @cindex devices; frames; windows, introduction to consoles; ! @cindex frames; windows, introduction to consoles; devices; ! @cindex windows, introduction to consoles; devices; frames; ! ! A window-system window that you see on the screen is called a ! @dfn{frame} in Emacs terminology. Each frame is subdivided into one or ! more non-overlapping panes, called (confusingly) @dfn{windows}. Each ! window displays the text of a buffer in it. (See above on Buffers.) Note ! that buffers and windows are independent entities: Two or more windows ! can be displaying the same buffer (potentially in different locations), ! and a buffer can be displayed in no windows. ! ! A single display screen that contains one or more frames is called ! a @dfn{display}. Under most circumstances, there is only one display. ! However, more than one display can exist, for example if you have ! a @dfn{multi-headed} console, i.e. one with a single keyboard but ! multiple displays. (Typically in such a situation, the various ! displays act like one large display, in that the mouse is only ! in one of them at a time, and moving the mouse off of one moves ! it into another.) In some cases, the different displays will ! have different characteristics, e.g. one color and one mono. ! ! XEmacs can display frames on multiple displays. It can even deal ! simultaneously with frames on multiple keyboards (called @dfn{consoles} in ! XEmacs terminology). Here is one case where this might be useful: You ! are using XEmacs on your workstation at work, and leave it running. ! Then you go home and dial in on a TTY line, and you can use the ! already-running XEmacs process to display another frame on your local ! TTY. ! ! Thus, there is a hierarchy console -> display -> frame -> window. ! There is a separate Lisp object type for each of these four concepts. ! Furthermore, there is logically a @dfn{selected console}, ! @dfn{selected display}, @dfn{selected frame}, and @dfn{selected window}. ! Each of these objects is distinguished in various ways, such as being the ! default object for various functions that act on objects of that type. ! Note that every containing object remembers the ``selected'' object ! among the objects that it contains: e.g. not only is there a selected ! window, but every frame remembers the last window in it that was ! selected, and changing the selected frame causes the remembered window ! within it to become the selected window. Similar relationships apply ! for consoles to devices and devices to frames. ! ! @node Point, Window Hierarchy, Introduction to Consoles; Devices; Frames; Windows, Consoles; Devices; Frames; Windows ! @section Point ! @cindex point ! ! Recall that every buffer has a current insertion position, called ! @dfn{point}. Now, two or more windows may be displaying the same buffer, ! and the text cursor in the two windows (i.e. @code{point}) can be in ! two different places. You may ask, how can that be, since each ! buffer has only one value of @code{point}? The answer is that each window ! also has a value of @code{point} that is squirreled away in it. There ! is only one selected window, and the value of ``point'' in that buffer ! corresponds to that window. When the selected window is changed ! from one window to another displaying the same buffer, the old ! value of @code{point} is stored into the old window's ``point'' and the ! value of @code{point} from the new window is retrieved and made the ! value of @code{point} in the buffer. This means that @code{window-point} ! for the selected window is potentially inaccurate, and if you ! want to retrieve the correct value of @code{point} for a window, ! you must special-case on the selected window and retrieve the ! buffer's point instead. This is related to why @code{save-window-excursion} ! does not save the selected window's value of @code{point}. ! ! @node Window Hierarchy, The Window Object, Point, Consoles; Devices; Frames; Windows ! @section Window Hierarchy ! @cindex window hierarchy ! @cindex hierarchy of windows ! ! If a frame contains multiple windows (panes), they are always created ! by splitting an existing window along the horizontal or vertical axis. ! Terminology is a bit confusing here: to @dfn{split a window ! horizontally} means to create two side-by-side windows, i.e. to make a ! @emph{vertical} cut in a window. Likewise, to @dfn{split a window ! vertically} means to create two windows, one above the other, by making ! a @emph{horizontal} cut. ! ! If you split a window and then split again along the same axis, you ! will end up with a number of panes all arranged along the same axis. ! The precise way in which the splits were made should not be important, ! and this is reflected internally. Internally, all windows are arranged ! in a tree, consisting of two types of windows, @dfn{combination} windows ! (which have children, and are covered completely by those children) and ! @dfn{leaf} windows, which have no children and are visible. Every ! combination window has two or more children, all arranged along the same ! axis. There are (logically) two subtypes of windows, depending on ! whether their children are horizontally or vertically arrayed. There is ! always one root window, which is either a leaf window (if the frame ! contains only one window) or a combination window (if the frame contains ! more than one window). In the latter case, the root window will have ! two or more children, either horizontally or vertically arrayed, and ! each of those children will be either a leaf window or another ! combination window. ! ! Here are some rules: ! ! @enumerate ! @item ! Horizontal combination windows can never have children that are ! horizontal combination windows; same for vertical. ! ! @item ! Only leaf windows can be split (obviously) and this splitting does one ! of two things: (a) turns the leaf window into a combination window and ! creates two new leaf children, or (b) turns the leaf window into one of ! the two new leaves and creates the other leaf. Rule (1) dictates which ! of these two outcomes happens. ! ! @item ! Every combination window must have at least two children. ! ! @item ! Leaf windows can never become combination windows. They can be deleted, ! however. If this results in a violation of (3), the parent combination ! window also gets deleted. ! ! @item ! All functions that accept windows must be prepared to accept combination ! windows, and do something sane (e.g. signal an error if so). ! Combination windows @emph{do} escape to the Lisp level. ! ! @item ! All windows have three fields governing their contents: ! these are @dfn{hchild} (a list of horizontally-arrayed children), ! @dfn{vchild} (a list of vertically-arrayed children), and @dfn{buffer} ! (the buffer contained in a leaf window). Exactly one of ! these will be non-@code{nil}. Remember that @dfn{horizontally-arrayed} ! means ``side-by-side'' and @dfn{vertically-arrayed} means ! @dfn{one above the other}. ! ! @item ! Leaf windows also have markers in their @code{start} (the ! first buffer position displayed in the window) and @code{pointm} ! (the window's stashed value of @code{point}---see above) fields, ! while combination windows have @code{nil} in these fields. ! ! @item ! The list of children for a window is threaded through the ! @code{next} and @code{prev} fields of each child window. ! ! @item ! @strong{Deleted windows can be undeleted}. This happens as a result of ! restoring a window configuration, and is unlike frames, displays, and ! consoles, which, once deleted, can never be restored. Deleting a window ! does nothing except set a special @code{dead} bit to 1 and clear out the ! @code{next}, @code{prev}, @code{hchild}, and @code{vchild} fields, for ! GC purposes. ! ! @item ! Most frames actually have two top-level windows---one for the ! minibuffer and one (the @dfn{root}) for everything else. The modeline ! (if present) separates these two. The @code{next} field of the root ! points to the minibuffer, and the @code{prev} field of the minibuffer ! points to the root. The other @code{next} and @code{prev} fields are ! @code{nil}, and the frame points to both of these windows. ! Minibuffer-less frames have no minibuffer window, and the @code{next} ! and @code{prev} of the root window are @code{nil}. Minibuffer-only ! frames have no root window, and the @code{next} of the minibuffer window ! is @code{nil} but the @code{prev} points to itself. (#### This is an ! artifact that should be fixed.) ! @end enumerate ! ! @node The Window Object, Modules for the Basic Displayable Lisp Objects, Window Hierarchy, Consoles; Devices; Frames; Windows ! @section The Window Object ! @cindex window object, the ! @cindex object, the window ! ! Windows have the following accessible fields: ! ! @table @code ! @item frame ! The frame that this window is on. ! ! @item mini_p ! Non-@code{nil} if this window is a minibuffer window. ! ! @item buffer ! The buffer that the window is displaying. This may change often during ! the life of the window. ! ! @item dedicated ! Non-@code{nil} if this window is dedicated to its buffer. ! ! @item pointm ! @cindex window point internals ! This is the value of point in the current buffer when this window is ! selected; when it is not selected, it retains its previous value. ! ! @item start ! The position in the buffer that is the first character to be displayed ! in the window. ! ! @item force_start ! If this flag is non-@code{nil}, it says that the window has been ! scrolled explicitly by the Lisp program. This affects what the next ! redisplay does if point is off the screen: instead of scrolling the ! window to show the text around point, it moves point to a location that ! is on the screen. ! ! @item last_modified ! The @code{modified} field of the window's buffer, as of the last time ! a redisplay completed in this window. ! ! @item last_point ! The buffer's value of point, as of the last time ! a redisplay completed in this window. ! ! @item left ! This is the left-hand edge of the window, measured in columns. (The ! leftmost column on the screen is @w{column 0}.) ! ! @item top ! This is the top edge of the window, measured in lines. (The top line on ! the screen is @w{line 0}.) ! ! @item height ! The height of the window, measured in lines. ! ! @item width ! The width of the window, measured in columns. ! ! @item next ! This is the window that is the next in the chain of siblings. It is ! @code{nil} in a window that is the rightmost or bottommost of a group of ! siblings. ! ! @item prev ! This is the window that is the previous in the chain of siblings. It is ! @code{nil} in a window that is the leftmost or topmost of a group of ! siblings. ! ! @item parent ! Internally, XEmacs arranges windows in a tree; each group of siblings has ! a parent window whose area includes all the siblings. This field points ! to a window's parent. ! ! Parent windows do not display buffers, and play little role in display ! except to shape their child windows. Emacs Lisp programs usually have ! no access to the parent windows; they operate on the windows at the ! leaves of the tree, which actually display buffers. ! ! @item hscroll ! This is the number of columns that the display in the window is scrolled ! horizontally to the left. Normally, this is 0. ! ! @item use_time ! This is the last time that the window was selected. The function ! @code{get-lru-window} uses this field. ! ! @item display_table ! The window's display table, or @code{nil} if none is specified for it. ! ! @item update_mode_line ! Non-@code{nil} means this window's mode line needs to be updated. ! ! @item base_line_number ! The line number of a certain position in the buffer, or @code{nil}. ! This is used for displaying the line number of point in the mode line. ! ! @item base_line_pos ! The position in the buffer for which the line number is known, or @code{nil} meaning none is known. @item region_showing *************** *** 17400,17405 **** --- 20403,20444 ---- or @code{nil} if it is using pipes. @end table + @menu + * Ben's separate stderr notes:: Probably obsolete. + @end menu + + + @node Ben's separate stderr notes, , , Subprocesses + @subsection Ben's separate stderr notes (probably obsolete) + + This node contains some notes that Ben kept on his separate subprocess + workspace. These notes probably describe changes and features that have + already been included in XEmacs 21.5; somebody should check and/or ask + Ben. + + @heading ben-separate-stderr-improved-error-trapping + + this is an old workspace, very close to being done, containing + + @itemize + @item + subprocess stderr output can be read separately; needed to fully + implement call-process with asynch. subprocesses. + + @item + huge improvements to the internal error-trapping routines (i.e. the + routines that call Lisp code and trap errors); Lisp code can now be + called from within redisplay. + + @item + cleanup and simplification of C-g handling; some things work now + that never used to. + + @item + see the ChangeLogs in the workspace. + @end itemize + + @node Interface to MS Windows, Interface to the X Window System, Subprocesses, Top @chapter Interface to MS Windows @cindex MS Windows, interface to *************** *** 17410,17415 **** --- 20449,20455 ---- * Windows Build Flags:: * Windows I18N Introduction:: * Modules for Interfacing with MS Windows:: + * CHANGES from 21.4-windows branch:: Probably obsolete. @end menu @node Different kinds of Windows environments, Windows Build Flags, Interface to MS Windows, Interface to MS Windows *************** *** 17875,17881 **** prepended with an L (causing it to be a wide string) depending on XEUNICODE_P. ! @node Modules for Interfacing with MS Windows, , Windows I18N Introduction, Interface to MS Windows @section Modules for Interfacing with MS Windows @cindex modules for interfacing with MS Windows @cindex interfacing with MS Windows, modules for --- 20915,20921 ---- prepended with an L (causing it to be a wide string) depending on XEUNICODE_P. ! @node Modules for Interfacing with MS Windows, CHANGES from 21.4-windows branch, Windows I18N Introduction, Interface to MS Windows @section Modules for Interfacing with MS Windows @cindex modules for interfacing with MS Windows @cindex interfacing with MS Windows, modules for *************** *** 17936,17941 **** --- 20976,21170 ---- @item intl-auto-encap-win32.h Auto-generated Unicode encapsulation headers @end table + + + @node CHANGES from 21.4-windows branch, , Modules for Interfacing with MS Windows, Interface to MS Windows + @section CHANGES from 21.4-windows branch (probably obsolete) + + This node contains the @file{CHANGES-msw} log that Andy Piper kept while + he was maintaining the Windows branch of 21.4. These changes have + (presumably) long since been merged to both 21.4 and 21.5, but let's not + throw the list away yet. + + @heading CHANGES-msw + + This file briefly describes all mswindows-specific changes to XEmacs + in the OXYMORON series of releases. The mswindows release branch + contains additional changes on top of the mainline XEmacs + release. These changes are deemed necessary for XEmacs to be fully + functional under mswindows. It is not intended that these changes + cause problems on UNIX systems, but they have not been tested on UNIX + platforms. Caveat Emptor. + + See the file @file{CHANGES-release} for a full list of mainline changes. + + @heading to XEmacs 21.4.9 "Informed Management (Windows)" + + @itemize + @item + Fix layout of widgets so that the search dialog works. + + @item + Fix focus capture of widgets under X. + @end itemize + + @heading to XEmacs 21.4.8 "Honest Recruiter (Windows)" + + @itemize + @item + All changes from 21.4.6 and 21.4.7. + + @item + Make sure revert temporaries are not visiting files. Suggested by + Mike Alexander. + + @item + File renaming fix from Mathias Grimmberger. + + @item + Fix printer metrics on windows 95 from Jonathan Harris. + + @item + Fix layout of widgets so that the search dialog works. + + @item + Fix focus capture of widgets under X. + + @item + Buffers tab doc fixes from John Palmieri. + + @item + Sync with FSF custom @code{:set-after} behavior. + + @item + Virtual window manager freeze fix from Rick Rankin. + + @item + Fix various printing problems. + + @item + Enable windows printing on cygwin. + @end itemize + + @heading to XEmacs 21.4.7 "Economic Science (Windows)" + + @itemize + @item + All changes from 21.4.6. + + @item + Fix problems with auto-revert with noconfirm. + + @item + Undo autoconf 2.5x changes. + + @item + Undo 21.4.7 process change. + @end itemize + + to XEmacs 21.4.6 "Common Lisp (Windows)" + + @itemize + @item + Made native registry entries match the installer. + + @item + Fixed mousewheel lockups. + + @item + Frame iconifcation fix from Adrian Aichner. + + @item + Fixed some printing problems. + + @item + Netinstaller updated to support kit revisions. + + @item + Fixed customize popup menus. + + @item + Fixed problems with too many dialog popups. + + @item + Netinstaller fixed to correctly upgrade shortcuts when upgrading + core XEmacs. + + @item + Fix for virtual window managers from Adrian Aichner. + + @item + Installer registers all C++ file types. + + @item + Short-filename fix from Peter Arius. + + @item + Fix for GC assertions from Adrian Aichner. + + @item + Winclient DDE client from Alastair Houghton. + + @item + Fix event assert from Mike Alexander. + + @item + Warning removal noticed by Ben Wing. + + @item + Redisplay glyph height fix from Ben Wing. + + @item + Printer margin fix from Jonathan Harris. + + @item + Error dialog fix suggested by Thomas Vogler. + + @item + Fixed revert-buffer to not revert in the case that there is + nothing to be done. + + @item + Glyph-baseline fix from Nix. + + @item + Fixed clipping of wide glyphs in non-zero-length extents. + + @item + Windows build fixes. + + @item + Fixed @code{:initial-focus} so that it works. + @end itemize + + @heading to XEmacs 21.4.5 "Civil Service (Windows)" + + @itemize + @item + Fixed a scrollbar problem when selecting the frame with focus. + + @item + Fixed @code{mswindows-shell-execute} under cygwin. + + @item + Added a new function @code{mswindows-cygwin-to-win32-path} for JDE. + + @item + Added support for dialog-based directory selection. + + @item + The installer version has been updated to the 21.5 netinstaller. The 21.5 + installer now does proper dde file association and adds uninstall + capability. + + @item + Handle leak fix from Mike Alexander. + + @item + New release build script. + @end itemize + + @node Interface to the X Window System, Dumping, Interface to MS Windows, Top @chapter Interface to the X Window System diff -c 'xemacs-21.5.25/man/xemacs/building.texi' 'xemacs-21.5.26/man/xemacs/building.texi' Index: ./man/xemacs/building.texi *** ./man/xemacs/building.texi Fri May 6 02:10:44 2005 --- ./man/xemacs/building.texi Sun Feb 26 23:28:34 2006 *************** *** 580,586 **** process. @findex run-lisp ! To run an inferior Lisp process, type @kbd{M-x run-lisp}. This runs the program named @code{lisp}, the same program you would run by typing @code{lisp} as a shell command, with both input and output going through an Emacs buffer named @samp{*lisp*}. In other words, any ``terminal output'' --- 580,587 ---- process. @findex run-lisp ! To run an inferior Lisp process, type @kbd{M-x run-lisp}. ! (You need to the @file{os-utils} package installed for this.) This runs the program named @code{lisp}, the same program you would run by typing @code{lisp} as a shell command, with both input and output going through an Emacs buffer named @samp{*lisp*}. In other words, any ``terminal output'' diff -c 'xemacs-21.5.25/modules/ChangeLog' 'xemacs-21.5.26/modules/ChangeLog' Index: ./modules/ChangeLog *** ./modules/ChangeLog Sun Feb 26 22:14:12 2006 --- ./modules/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,7 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 419,425 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 423,430 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/netinstall/ChangeLog' 'xemacs-21.5.26/netinstall/ChangeLog' Index: ./netinstall/ChangeLog *** ./netinstall/ChangeLog Sun Feb 26 22:14:12 2006 --- ./netinstall/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,7 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 152,158 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 156,163 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/nt/ChangeLog' 'xemacs-21.5.26/nt/ChangeLog' Index: ./nt/ChangeLog *** ./nt/ChangeLog Sun Feb 26 22:14:12 2006 --- ./nt/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,18 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + + 2006-02-27 Vin Shelton + + * config.inc.samp: Comment out PACKAGE_PREFIX. + * xemacs.mak: Convert PACKAGE_PREFIX input from config.inc to + PATH_LATE_PACKAGE_DIRECTORIES. Do not use PACKAGE_PATH. + + 2006-02-22 Marcus Crestani + + * xemacs.mak: Remove mc-alloc, replace with newgc, adjust output. + * config.inc.samp: Remove MC_ALLOC option. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 872,878 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 887,894 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/nt/config.inc.samp' 'xemacs-21.5.26/nt/config.inc.samp' Index: ./nt/config.inc.samp *** ./nt/config.inc.samp Fri Nov 25 10:41:50 2005 --- ./nt/config.inc.samp Tue Mar 14 09:09:09 2006 *************** *** 6,12 **** INSTALL_DIR=c:\Program Files\XEmacs\XEmacs-$(XEMACS_VERSION_STRING) ! PACKAGE_PREFIX=c:\Program Files\XEmacs ############################################################################ # Compiled-in features: basic # --- 6,16 ---- INSTALL_DIR=c:\Program Files\XEmacs\XEmacs-$(XEMACS_VERSION_STRING) ! # PACKAGE_PREFIX is root of the installed package hierarchies. ! # This corresponds to the configure option --with-late-packages. ! # See 'Package Hierarchies' in the info for more documentation. ! # If you don't set this, XEmacs will attempt to find the packages at runtime. ! #PACKAGE_PREFIX=c:\Program Files\XEmacs ############################################################################ # Compiled-in features: basic # *************** *** 220,229 **** # of the traditional XEmacs garbage-collection routines. USE_KKCC=1 ! # Set this to use the new experimental allocator routines ! MC_ALLOC=1 ! ! # Set this to use the new experimental incremental garbage collector routines NEW_GC=0 # Set this to turn on the use of the union type, which gets you improved --- 224,231 ---- # of the traditional XEmacs garbage-collection routines. USE_KKCC=1 ! # Set this to use the new experimental incremental garbage collector ! # and the new allocator routines NEW_GC=0 # Set this to turn on the use of the union type, which gets you improved diff -c 'xemacs-21.5.25/nt/installer/Wise/ChangeLog' 'xemacs-21.5.26/nt/installer/Wise/ChangeLog' Index: ./nt/installer/Wise/ChangeLog *** ./nt/installer/Wise/ChangeLog Sun Feb 26 22:14:12 2006 --- ./nt/installer/Wise/ChangeLog Sat Apr 1 03:46:15 2006 *************** *** 1,3 **** --- 1,7 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 84,90 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 88,95 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/nt/xemacs.mak' 'xemacs-21.5.26/nt/xemacs.mak' Index: ./nt/xemacs.mak *** ./nt/xemacs.mak Fri Nov 25 10:41:50 2005 --- ./nt/xemacs.mak Tue Mar 14 09:09:09 2006 *************** *** 215,223 **** !if !defined(USE_KKCC) USE_KKCC=0 !endif - !if !defined(MC_ALLOC) - MC_ALLOC=0 - !endif !if !defined(NEW_GC) NEW_GC=0 !endif --- 215,220 ---- *************** *** 443,459 **** INSTALL_DIR=c:\Program Files\XEmacs\XEmacs-$(XEMACS_VERSION_STRING) ! endif !endif ! !if !defined(PACKAGE_PATH) ! ! if !defined(PACKAGE_PREFIX) ! PACKAGE_PREFIX=c:\Program Files\XEmacs ! ! endif ! ! if $(MULE) ! PACKAGE_PATH=~\.xemacs;;$(PACKAGE_PREFIX)\site-packages;$(PACKAGE_PREFIX)\mule-packages;$(PACKAGE_PREFIX)\xemacs-packages ! ! else ! PACKAGE_PATH=~\.xemacs;;$(PACKAGE_PREFIX)\site-packages;$(PACKAGE_PREFIX)\xemacs-packages ! ! endif !endif - PATH_PACKAGEPATH="$(PACKAGE_PATH:\=\\)" !if $(INFODOCK) PATH_PREFIX=../.. --- 440,450 ---- INSTALL_DIR=c:\Program Files\XEmacs\XEmacs-$(XEMACS_VERSION_STRING) ! endif !endif ! ! # If PACKAGE_PREFIX was defined, use it to generate a package path. ! !if defined(PACKAGE_PREFIX) ! PATH_LATE_PACKAGE_DIRECTORIES="$(PACKAGE_PREFIX:\=\\)" !endif !if $(INFODOCK) PATH_PREFIX=../.. *************** *** 644,663 **** !if $(NEW_GC) OPT_DEFINES=$(OPT_DEFINES) -DNEW_GC ! OPT_OBJS=$(OPT_OBJS) $(OUTDIR)\vdb.obj $(OUTDIR)\vdb-win32.obj USE_KKCC=1 - MC_ALLOC=1 !endif !if $(USE_KKCC) OPT_DEFINES=$(OPT_DEFINES) -DUSE_KKCC !endif - !if $(MC_ALLOC) - OPT_DEFINES=$(OPT_DEFINES) -DMC_ALLOC - OPT_OBJS=$(OPT_OBJS) $(OUTDIR)\mc-alloc.obj - !endif - !if $(USE_SYSTEM_MALLOC) OPT_DEFINES=$(OPT_DEFINES) -DSYSTEM_MALLOC !else --- 635,649 ---- !if $(NEW_GC) OPT_DEFINES=$(OPT_DEFINES) -DNEW_GC ! OPT_OBJS=$(OPT_OBJS) $(OUTDIR)\vdb.obj $(OUTDIR)\vdb-win32.obj \ ! $(OUTDIR)\mc-alloc.obj USE_KKCC=1 !endif !if $(USE_KKCC) OPT_DEFINES=$(OPT_DEFINES) -DUSE_KKCC !endif !if $(USE_SYSTEM_MALLOC) OPT_DEFINES=$(OPT_DEFINES) -DSYSTEM_MALLOC !else *************** *** 813,820 **** !if defined(xemacs_extra_name) -DXEMACS_EXTRA_NAME=\"$(xemacs_extra_name:"=)\" \ !endif ! -DEMACS_CONFIGURATION=\"$(EMACS_CONFIGURATION)\" \ ! -DPATH_PACKAGEPATH=\"$(PATH_PACKAGEPATH)\" TEMACS_CPP_FLAGS=$(CFLAGS) $(TEMACS_CPP_FLAGS_NO_CFLAGS) TEMACS_CPP_CDECL_FLAGS=$(CFLAGS_CDECL) $(TEMACS_CPP_FLAGS_NO_CFLAGS) --- 799,808 ---- !if defined(xemacs_extra_name) -DXEMACS_EXTRA_NAME=\"$(xemacs_extra_name:"=)\" \ !endif ! !if defined(PATH_LATE_PACKAGE_DIRECTORIES) ! -DPATH_LATE_PACKAGE_DIRECTORIES=\"$(PATH_LATE_PACKAGE_DIRECTORIES)\" \ ! !endif ! -DEMACS_CONFIGURATION=\"$(EMACS_CONFIGURATION)\" TEMACS_CPP_FLAGS=$(CFLAGS) $(TEMACS_CPP_FLAGS_NO_CFLAGS) TEMACS_CPP_CDECL_FLAGS=$(CFLAGS_CDECL) $(TEMACS_CPP_FLAGS_NO_CFLAGS) *************** *** 1075,1082 **** !endif !if [echo LISPDIR>>$(CONFIG_VALUES) && echo "\\$(LISP:\=\\)">>$(CONFIG_VALUES)] !endif ! # PATH_PACKAGEPATH is already a quoted string. ! !if [echo PACKAGE_PATH>>$(CONFIG_VALUES) && echo $(PATH_PACKAGEPATH)>>$(CONFIG_VALUES)] !endif LINK_DEPENDENCY_ARGS = -Fe$@ -Fd$* $** -link $(DEBUG_FLAGS_LINK) --- 1063,1072 ---- !endif !if [echo LISPDIR>>$(CONFIG_VALUES) && echo "\\$(LISP:\=\\)">>$(CONFIG_VALUES)] !endif ! !if defined(PATH_LATE_PACKAGE_DIRECTORIES) ! # PATH_LATE_PACKAGE_DIRECTORIES is already a quoted string. ! ! if [echo PATH_LATE_PACKAGE_DIRECTORIES>>$(CONFIG_VALUES) && echo $(PATH_LATE_PACKAGE_DIRECTORIES)>>$(CONFIG_VALUES)] ! ! endif !endif LINK_DEPENDENCY_ARGS = -Fe$@ -Fd$* $** -link $(DEBUG_FLAGS_LINK) *************** *** 1149,1155 **** Compiling as C++. !endif Installing XEmacs in "$(INSTALL_DIR:\=\\)". ! Package path is $(PATH_PACKAGEPATH). !if $(INFODOCK) Building InfoDock. !endif --- 1139,1147 ---- Compiling as C++. !endif Installing XEmacs in "$(INSTALL_DIR:\=\\)". ! !if defined(PATH_LATE_PACKAGE_DIRECTORIES) ! Package path is $(PATH_LATE_PACKAGE_DIRECTORIES). ! !endif !if $(INFODOCK) Building InfoDock. !endif *************** *** 1266,1278 **** Disabling non-essential build actions. Use with care! !endif !if $(USE_KKCC) ! Using new experimental GC algorithms. ! !endif ! !if $(MC_ALLOC) ! Using new experimental allocator. !endif !if $(NEW_GC) ! Using new experimental incremental garbage collector. !endif < + + * XEmacs 21.5.26 "endive" is released. + + 2006-03-30 Adrian Aichner + + * lisp.h (Dynarr_add): Add local variable imp to avoid VC6 + internal compiler error. + + 2006-03-26 Marcus Crestani + + * gc.c: Remove functions for explicitly-freed statistics + (the need to explicitly free went away with the asynchronous + finalization patch). + * gc.c (struct gc_state): EMACS_INT -> double, remove + explicitly-freed statistics. + * gc.c (Fgc_stats): Remove explicitly-freed statistics. + * gc.c (PL): Use make_float. + * gc.h: Remove prototypes and macros for explicitly-freed + statistics. + + 2006-03-24 Jerry James + + * alsaplay.c: New file providing support for sound with ALSA. + * config.h.in: New symbol HAVE_ALSA_SOUND + * sound.c: Add ALSA support. + + 2006-03-27 Mike Fabian + + * vdb-posix.c (vdb_install_signal_handler): Correct memset. + + 2006-03-26 Marcus Crestani + + * alloc.c (malloc_warning): Move function into scope of + MALLOC_END, add MALLOC_END. + * alloc.c (memory_full): Add memory shortage indication, adjust + error messages. + * mc-alloc.c: Add memory_shortage. + * mc-alloc.c (expand_heap): If memory is short, allocate only the + needed pages, not more. + * mc-alloc.h: Add memory_shortage. + + 2006-03-26 Marcus Crestani + + * alloc.c (make_uninit_string): Use set_lispstringp_direct. + * lisp.h (set_lispstringp_direct): New. + + 2006-03-21 Marcus Crestani + + * mc-alloc.c (visit_all_used_page_headers): + * mc-alloc.c (finalize_page_for_disksave): + * mc-alloc.c (mc_finalize_for_disksave): + * mc-alloc.c (sweep_page): + * mc-alloc.c (mc_sweep): + * mc-alloc.c (protect_heap_page): + * mc-alloc.c (protect_heap_pages): + * mc-alloc.c (unprotect_heap_page): + * mc-alloc.c (unprotect_heap_pages): + * mc-alloc.h: Return number of pages processed. + * vdb.c (vdb_start_dirty_bits_recording): Adjust size of + page_fault_table to its upper bound (= number of pages that + contain BLACK objects) in advance, to avoid malloc in the signal + handler. + + 2006-03-24 Stephen J. Turnbull + + * file-coding.c (decode-coding-region, encode-coding-region): + Convert to interactive commands, and adjust docstrings. + + 2006-03-21 Malcolm Purvis + + * regex.c: Bump INIT_FAILURE_ALLOC and re_max_failures to the + current values found in GNU Emacs. + + 2006-03-20 Marcus Crestani + + * dynarr.c (Dynarr_realloc): Malloc correct size. + * lisp.h: Dynamic array cleanup, remove duplicate code. + + 2006-03-17 Stephen J. Turnbull + + * objects-x.c (x_font_instance_truename): + Eliminate bogus pointer to nowhere. + + 2006-03-09 Jerry James + + * profile.h (RETURN_UNGCPRO_EXIT_PROFILING): Add missing do. + + 2006-03-02 Marcus Crestani + + * gc.c (show_gc_cursor_and_message): New. + * gc.c (remove_gc_cursor_and_message): New. + * gc.c (gc_prepare): Move mouse pointer code to + show_gc_cursor_and_message. + * gc.c (gc_finish): Move mouse pointer code to + remove_gc_cursor_and_message. + * gc.c (gc): Call show/remove_gc_cursor_and_message. + * gc.c (garbage_collect_1): Call + show/remove_gc_cursor_and_message. + + 2006-02-22 Marcus Crestani + + Asynchronous finalization: + + * Makefile.in.in: Remove mc-alloc, replace with newgc. + * alloc.c (alloc_lrecord): Add object that has a finalizer + to Vall_finalizable_objs. + * alloc.c (noseeum_alloc_lrecord): Add object that has a finalizer + to Vall_finalizable_objs. + * alloc.c (alloc_lrecord_array): Add object that has a finalizer + to Vall_finalizable_objs. + * alloc.c (free_lrecord): Disable manual free. + * dumper.c (pdump_register_object): Objects with finalizers cannot + be dumped. + * eval.c (Ffuncall): Add call to run_finalizers. + * gc.c (finalize_elem): New. + * gc.c (add_finalizable_object): New. + * gc.c (register_for_finalization): New. + * gc.c (gc_finalize): Call register_for_finalization. + * gc.c (gc_1): Move kkcc_gc_stack_free after finalization. + * gc.c (common_init_gc_early): Add asynchronous finalization + variables. + * gc.c (init_gc_early): Add asynchronous finalization variables. + * gc.c (vars_of_gc): Add asynchronous finalization variables. + * gc.h: Add asynchronous finalization prototypes. + * mc-alloc.c (finalize_heap): Remove. + * mc-alloc.c (mc_free): Disable manual free. + + * elhash.c (finalize_hash_table): Remove unneeded finalizer for + NEW_GC + * extents.c (finalize_extent_info): Remove unneeded finalizer for + NEW_GC. + * file-coding.c (finalize_coding_system): Remove unneeded + finalizer for NEW_GC. + * gui.c (finalize_gui_item): Remove unneeded finalizer. + * specifier.c (finalize_specifier): Remove unneeded finalizer for + NEW_GC. + + Merge #ifdef MC_ALLOC into #ifdef NEW_GC, remove no longer needed + MC_ALLOC specific code in all files: + * alloc.c: + * buffer.c: + * bytecode.c: + * bytecode.h: + * config.h.in: + * console-stream.c: + * console.c: + * dumper.c: + * dumper.h: + * elhash.c: + * emacs.c: + * event-msw.c: + * event-stream.c: + * extents.c: + * extents.c: + * faces.h: + * file-coding.c: + * gc.c: + * glyphs.h: + * lisp.h: + * lrecord.h: + * lstream.c: + * marker.c: + * mc-alloc.c: + * mc-alloc.h: + * opaque.c: + * print.c: + * ralloc.c: + * specifier.c: + * symbols.c: + * symeval.h: + * symsinit.h: + * tests.c: + * xemacs.def.in.in: + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 15732,15738 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-01-31 John H. Palmieri --- 15907,15914 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-01-31 John H. Palmieri diff -c 'xemacs-21.5.25/src/Makefile.in.in' 'xemacs-21.5.26/src/Makefile.in.in' Index: ./src/Makefile.in.in *** ./src/Makefile.in.in Sat Nov 26 20:46:06 2005 --- ./src/Makefile.in.in Tue Feb 28 01:29:21 2006 *************** *** 254,265 **** xemacs_res.o #endif - #ifdef MC_ALLOC - mc_alloc_objs=mc-alloc.o - #endif - #ifdef NEW_GC ! new_gc_objs=vdb.o # if defined (WIN32_ANY) || defined (VDB_WIN32) vdb_objs=vdb-win32.o # elif defined (VDB_MACH) --- 254,261 ---- xemacs_res.o #endif #ifdef NEW_GC ! new_gc_objs=mc-alloc.o vdb.o # if defined (WIN32_ANY) || defined (VDB_WIN32) vdb_objs=vdb-win32.o # elif defined (VDB_MACH) *************** *** 294,300 **** gutter.o\ hash.o imgproc.o indent.o insdel.o intl.o\ keymap.o $(RTC_patch_objs) line-number.o $(ldap_objs) lread.o lstream.o\ ! $(mc_alloc_objs) $(new_gc_objs) $(vdb_objs) \ macros.o marker.o md5.o minibuf.o $(mswindows_objs) $(mswindows_gui_objs)\ $(mule_objs) $(mule_canna_objs) $(mule_wnn_objs) $(number_objs) objects.o\ opaque.o $(postgresql_objs) print.o process.o $(process_objs) $(profile_objs)\ --- 290,296 ---- gutter.o\ hash.o imgproc.o indent.o insdel.o intl.o\ keymap.o $(RTC_patch_objs) line-number.o $(ldap_objs) lread.o lstream.o\ ! $(new_gc_objs) $(vdb_objs) \ macros.o marker.o md5.o minibuf.o $(mswindows_objs) $(mswindows_gui_objs)\ $(mule_objs) $(mule_canna_objs) $(mule_wnn_objs) $(number_objs) objects.o\ opaque.o $(postgresql_objs) print.o process.o $(process_objs) $(profile_objs)\ diff -c 'xemacs-21.5.25/src/alloc.c' 'xemacs-21.5.26/src/alloc.c' Index: ./src/alloc.c *** ./src/alloc.c Sun Dec 25 20:21:46 2005 --- ./src/alloc.c Mon Mar 27 00:24:26 2006 *************** *** 191,203 **** void *minimum_address_seen; void *maximum_address_seen; ! #ifndef MC_ALLOC int c_readonly (Lisp_Object obj) { return POINTER_TYPE_P (XTYPE (obj)) && C_READONLY (obj); } ! #endif /* MC_ALLOC */ int lisp_readonly (Lisp_Object obj) --- 191,203 ---- void *minimum_address_seen; void *maximum_address_seen; ! #ifndef NEW_GC int c_readonly (Lisp_Object obj) { return POINTER_TYPE_P (XTYPE (obj)) && C_READONLY (obj); } ! #endif /* not NEW_GC */ int lisp_readonly (Lisp_Object obj) *************** *** 216,222 **** int ignore_malloc_warnings; ! #ifndef MC_ALLOC void *breathing_space; void --- 216,222 ---- int ignore_malloc_warnings; ! #ifndef NEW_GC void *breathing_space; void *************** *** 229,275 **** xfree (tmp, void *); } } ! #endif /* not MC_ALLOC */ ! ! /* malloc calls this if it finds we are near exhausting storage */ ! void ! malloc_warning (const char *str) ! { ! if (ignore_malloc_warnings) ! return; ! ! warn_when_safe ! (Qmemory, Qemergency, ! "%s\n" ! "Killing some buffers may delay running out of memory.\n" ! "However, certainly by the time you receive the 95%% warning,\n" ! "you should clean up, kill this Emacs, and start a new one.", ! str); ! } ! ! /* Called if malloc returns zero */ ! DOESNT_RETURN ! memory_full (void) ! { ! fprintf (stderr, "##### M E M O R Y F U L L #####\n"); ! /* Force a GC next time eval is called. ! It's better to loop garbage-collecting (we might reclaim enough ! to win) than to loop beeping and barfing "Memory exhausted" ! */ ! consing_since_gc = gc_cons_threshold + 1; ! recompute_need_to_garbage_collect (); ! #ifndef MC_ALLOC ! release_breathing_space (); ! #endif /* not MC_ALLOC */ ! ! /* Flush some histories which might conceivably contain garbalogical ! inhibitors. */ ! if (!NILP (Fboundp (Qvalues))) ! Fset (Qvalues, Qnil); ! Vcommand_history = Qnil; ! ! out_of_memory ("Memory exhausted", Qunbound); ! } static void set_alloc_mins_and_maxes (void *val, Bytecount size) --- 229,235 ---- xfree (tmp, void *); } } ! #endif /* not NEW_GC */ static void set_alloc_mins_and_maxes (void *val, Bytecount size) *************** *** 302,308 **** } \ while (0) ! #ifdef MC_ALLOC #define FREE_OR_REALLOC_BEGIN(block) \ do \ { \ --- 262,268 ---- } \ while (0) ! #ifdef NEW_GC #define FREE_OR_REALLOC_BEGIN(block) \ do \ { \ *************** *** 313,319 **** MALLOC_BEGIN (); \ } \ while (0) ! #else /* not MC_ALLOC */ #define FREE_OR_REALLOC_BEGIN(block) \ do \ { \ --- 273,279 ---- MALLOC_BEGIN (); \ } \ while (0) ! #else /* not NEW_GC */ #define FREE_OR_REALLOC_BEGIN(block) \ do \ { \ *************** *** 329,335 **** MALLOC_BEGIN (); \ } \ while (0) ! #endif /* not MC_ALLOC */ #define MALLOC_END() \ do \ --- 289,295 ---- MALLOC_BEGIN (); \ } \ while (0) ! #endif /* not NEW_GC */ #define MALLOC_END() \ do \ *************** *** 354,359 **** --- 314,379 ---- set_alloc_mins_and_maxes (val, size); } + /* malloc calls this if it finds we are near exhausting storage */ + void + malloc_warning (const char *str) + { + if (ignore_malloc_warnings) + return; + + /* Remove the malloc lock here, because warn_when_safe may allocate + again. It is safe to remove the malloc lock here, because malloc + is already finished (malloc_warning is called via + after_morecore_hook -> check_memory_limits -> save_warn_fun -> + malloc_warning). */ + MALLOC_END (); + + warn_when_safe + (Qmemory, Qemergency, + "%s\n" + "Killing some buffers may delay running out of memory.\n" + "However, certainly by the time you receive the 95%% warning,\n" + "you should clean up, kill this Emacs, and start a new one.", + str); + } + + /* Called if malloc returns zero */ + DOESNT_RETURN + memory_full (void) + { + /* Force a GC next time eval is called. + It's better to loop garbage-collecting (we might reclaim enough + to win) than to loop beeping and barfing "Memory exhausted" + */ + consing_since_gc = gc_cons_threshold + 1; + recompute_need_to_garbage_collect (); + #ifdef NEW_GC + /* Put mc-alloc into memory shortage mode. This may keep XEmacs + alive until the garbage collector can free enough memory to get + us out of the memory exhaustion. If already in memory shortage + mode, we are in a loop and hopelessly lost. */ + if (memory_shortage) + { + fprintf (stderr, "Memory full, cannot recover.\n"); + ABORT (); + } + fprintf (stderr, + "Memory full, try to recover.\n" + "You should clean up, kill this Emacs, and start a new one.\n"); + memory_shortage++; + #else /* not NEW_GC */ + release_breathing_space (); + #endif /* not NEW_GC */ + + /* Flush some histories which might conceivably contain garbalogical + inhibitors. */ + if (!NILP (Fboundp (Qvalues))) + Fset (Qvalues, Qnil); + Vcommand_history = Qnil; + + out_of_memory ("Memory exhausted", Qunbound); + } + /* like malloc, calloc, realloc, free but: -- check for no memory left *************** *** 415,421 **** #ifdef ERROR_CHECK_GC ! #ifndef MC_ALLOC static void deadbeef_memory (void *ptr, Bytecount size) { --- 435,441 ---- #ifdef ERROR_CHECK_GC ! #ifndef NEW_GC static void deadbeef_memory (void *ptr, Bytecount size) { *************** *** 426,432 **** while (beefs--) (*ptr4++) = 0xDEADBEEF; /* -559038737 base 10 */ } ! #endif /* not MC_ALLOC */ #else /* !ERROR_CHECK_GC */ --- 446,452 ---- while (beefs--) (*ptr4++) = 0xDEADBEEF; /* -559038737 base 10 */ } ! #endif /* not NEW_GC */ #else /* !ERROR_CHECK_GC */ *************** *** 455,461 **** #endif /* NEED_STRDUP */ ! #ifndef MC_ALLOC static void * allocate_lisp_storage (Bytecount size) { --- 475,481 ---- #endif /* NEED_STRDUP */ ! #ifndef NEW_GC static void * allocate_lisp_storage (Bytecount size) { *************** *** 480,488 **** return val; } ! #endif /* not MC_ALLOC */ ! #if defined (MC_ALLOC) && defined (ALLOC_TYPE_STATS) static struct { int instances_in_use; --- 500,508 ---- return val; } ! #endif /* not NEW_GC */ ! #if defined (NEW_GC) && defined (ALLOC_TYPE_STATS) static struct { int instances_in_use; *************** *** 539,554 **** size += lrecord_stats[i].bytes_in_use; return size; } ! #endif /* not (MC_ALLOC && ALLOC_TYPE_STATS) */ ! #ifndef MC_ALLOC /* lcrecords are chained together through their "next" field. After doing the mark phase, GC will walk this linked list and free any lcrecord which hasn't been marked. */ static struct old_lcrecord_header *all_lcrecords; ! #endif /* not MC_ALLOC */ ! #ifdef MC_ALLOC /* The basic lrecord allocation functions. See lrecord.h for details. */ void * alloc_lrecord (Bytecount size, --- 559,574 ---- size += lrecord_stats[i].bytes_in_use; return size; } ! #endif /* NEW_GC && ALLOC_TYPE_STATS */ ! #ifndef NEW_GC /* lcrecords are chained together through their "next" field. After doing the mark phase, GC will walk this linked list and free any lcrecord which hasn't been marked. */ static struct old_lcrecord_header *all_lcrecords; ! #endif /* not NEW_GC */ ! #ifdef NEW_GC /* The basic lrecord allocation functions. See lrecord.h for details. */ void * alloc_lrecord (Bytecount size, *************** *** 567,572 **** --- 587,594 ---- #ifdef ALLOC_TYPE_STATS inc_lrecord_stats (size, lheader); #endif /* ALLOC_TYPE_STATS */ + if (implementation->finalizer) + add_finalizable_obj (wrap_pointer_1 (lheader)); INCREMENT_CONS_COUNTER (size, implementation->name); return lheader; } *************** *** 589,599 **** #ifdef ALLOC_TYPE_STATS inc_lrecord_stats (size, lheader); #endif /* ALLOC_TYPE_STATS */ NOSEEUM_INCREMENT_CONS_COUNTER (size, implementation->name); return lheader; } - #ifdef NEW_GC void * alloc_lrecord_array (Bytecount size, int elemcount, const struct lrecord_implementation *implementation) --- 611,622 ---- #ifdef ALLOC_TYPE_STATS inc_lrecord_stats (size, lheader); #endif /* ALLOC_TYPE_STATS */ + if (implementation->finalizer) + add_finalizable_obj (wrap_pointer_1 (lheader)); NOSEEUM_INCREMENT_CONS_COUNTER (size, implementation->name); return lheader; } void * alloc_lrecord_array (Bytecount size, int elemcount, const struct lrecord_implementation *implementation) *************** *** 619,653 **** #ifdef ALLOC_TYPE_STATS inc_lrecord_stats (size, lh); #endif /* not ALLOC_TYPE_STATS */ } INCREMENT_CONS_COUNTER (size * elemcount, implementation->name); return lheader; } - #endif /* NEW_GC */ void ! free_lrecord (Lisp_Object lrecord) { ! #ifndef NEW_GC ! gc_checking_assert (!gc_in_progress); ! #endif /* not NEW_GC */ ! gc_checking_assert (!LRECORD_FREE_P (XRECORD_LHEADER (lrecord))); ! gc_checking_assert (!XRECORD_LHEADER (lrecord)->free); ! ! #ifdef NEW_GC ! GC_STAT_EXPLICITLY_TRIED_FREED; ! /* Ignore requests to manual free objects while in garbage collection. */ ! if (write_barrier_enabled || gc_in_progress) ! return; ! ! GC_STAT_EXPLICITLY_FREED; ! #endif /* NEW_GC */ ! ! MC_ALLOC_CALL_FINALIZER (XPNTR (lrecord)); ! mc_free (XPNTR (lrecord)); ! recompute_need_to_garbage_collect (); } ! #else /* not MC_ALLOC */ /* The most basic of the lcrecord allocation functions. Not usually called directly. Allocates an lrecord not managed by any lcrecord-list, of a --- 642,661 ---- #ifdef ALLOC_TYPE_STATS inc_lrecord_stats (size, lh); #endif /* not ALLOC_TYPE_STATS */ + if (implementation->finalizer) + add_finalizable_obj (wrap_pointer_1 (lh)); } INCREMENT_CONS_COUNTER (size * elemcount, implementation->name); return lheader; } void ! free_lrecord (Lisp_Object UNUSED (lrecord)) { ! /* Manual frees are not allowed with asynchronous finalization */ ! return; } ! #else /* not NEW_GC */ /* The most basic of the lcrecord allocation functions. Not usually called directly. Allocates an lrecord not managed by any lcrecord-list, of a *************** *** 719,733 **** return; } #endif /* Unused */ ! #endif /* not MC_ALLOC */ static void disksave_object_finalization_1 (void) { ! #ifdef MC_ALLOC mc_finalize_for_disksave (); ! #else /* not MC_ALLOC */ struct old_lcrecord_header *header; for (header = all_lcrecords; header; header = header->next) --- 727,741 ---- return; } #endif /* Unused */ ! #endif /* not NEW_GC */ static void disksave_object_finalization_1 (void) { ! #ifdef NEW_GC mc_finalize_for_disksave (); ! #else /* not NEW_GC */ struct old_lcrecord_header *header; for (header = all_lcrecords; header; header = header->next) *************** *** 736,742 **** !header->free) LHEADER_IMPLEMENTATION (&header->lheader)->finalizer (header, 1); } ! #endif /* not MC_ALLOC */ } /* Bitwise copy all parts of a Lisp object other than the header */ --- 744,750 ---- !header->free) LHEADER_IMPLEMENTATION (&header->lheader)->finalizer (header, 1); } ! #endif /* not NEW_GC */ } /* Bitwise copy all parts of a Lisp object other than the header */ *************** *** 751,761 **** assert (imp == XRECORD_LHEADER_IMPLEMENTATION (dst)); assert (size == lisp_object_size (dst)); ! #ifdef MC_ALLOC memcpy ((char *) XRECORD_LHEADER (dst) + sizeof (struct lrecord_header), (char *) XRECORD_LHEADER (src) + sizeof (struct lrecord_header), size - sizeof (struct lrecord_header)); ! #else /* not MC_ALLOC */ if (imp->basic_p) memcpy ((char *) XRECORD_LHEADER (dst) + sizeof (struct lrecord_header), (char *) XRECORD_LHEADER (src) + sizeof (struct lrecord_header), --- 759,769 ---- assert (imp == XRECORD_LHEADER_IMPLEMENTATION (dst)); assert (size == lisp_object_size (dst)); ! #ifdef NEW_GC memcpy ((char *) XRECORD_LHEADER (dst) + sizeof (struct lrecord_header), (char *) XRECORD_LHEADER (src) + sizeof (struct lrecord_header), size - sizeof (struct lrecord_header)); ! #else /* not NEW_GC */ if (imp->basic_p) memcpy ((char *) XRECORD_LHEADER (dst) + sizeof (struct lrecord_header), (char *) XRECORD_LHEADER (src) + sizeof (struct lrecord_header), *************** *** 766,772 **** (char *) XRECORD_LHEADER (src) + sizeof (struct old_lcrecord_header), size - sizeof (struct old_lcrecord_header)); ! #endif /* not MC_ALLOC */ } --- 774,780 ---- (char *) XRECORD_LHEADER (src) + sizeof (struct old_lcrecord_header), size - sizeof (struct old_lcrecord_header)); ! #endif /* not NEW_GC */ } *************** *** 814,820 **** } ! #ifdef MC_ALLOC #define DECLARE_FIXED_TYPE_ALLOC(type, structture) struct __foo__ #else /************************************************************************/ --- 822,828 ---- } ! #ifdef NEW_GC #define DECLARE_FIXED_TYPE_ALLOC(type, structture) struct __foo__ #else /************************************************************************/ *************** *** 1164,1172 **** #else #define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr) #endif ! #endif /* not MC_ALLOC */ ! #ifdef MC_ALLOC #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \ do { \ (var) = alloc_lrecord_type (lisp_type, lrec_ptr); \ --- 1172,1180 ---- #else #define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr) #endif ! #endif /* NEW_GC */ ! #ifdef NEW_GC #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \ do { \ (var) = alloc_lrecord_type (lisp_type, lrec_ptr); \ *************** *** 1176,1182 **** do { \ (var) = noseeum_alloc_lrecord_type (lisp_type, lrec_ptr); \ } while (0) ! #else /* not MC_ALLOC */ #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \ do \ { \ --- 1184,1190 ---- do { \ (var) = noseeum_alloc_lrecord_type (lisp_type, lrec_ptr); \ } while (0) ! #else /* not NEW_GC */ #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \ do \ { \ *************** *** 1190,1196 **** NOSEEUM_ALLOCATE_FIXED_TYPE (type, lisp_type, var); \ set_lheader_implementation (&(var)->lheader, lrec_ptr); \ } while (0) ! #endif /* MC_ALLOC */ --- 1198,1204 ---- NOSEEUM_ALLOCATE_FIXED_TYPE (type, lisp_type, var); \ set_lheader_implementation (&(var)->lheader, lrec_ptr); \ } while (0) ! #endif /* not NEW_GC */ *************** *** 2292,2298 **** return *string_plist_ptr (string); } ! #ifndef MC_ALLOC /* No `finalize', or `hash' methods. internal_hash() already knows how to hash strings and finalization is done with the ADDITIONAL_FREE_string macro, which is the --- 2300,2306 ---- return *string_plist_ptr (string); } ! #ifndef NEW_GC /* No `finalize', or `hash' methods. internal_hash() already knows how to hash strings and finalization is done with the ADDITIONAL_FREE_string macro, which is the *************** *** 2309,2315 **** string_remprop, string_plist, Lisp_String); ! #endif /* not MC_ALLOC */ #ifdef NEW_GC #define STRING_FULLSIZE(size) \ --- 2317,2323 ---- string_remprop, string_plist, Lisp_String); ! #endif /* not NEW_GC */ #ifdef NEW_GC #define STRING_FULLSIZE(size) \ *************** *** 2348,2379 **** #define MARK_STRING_CHARS_AS_FREE(ptr) ((void) ((ptr)->string = NULL)) #endif /* not NEW_GC */ ! #ifdef MC_ALLOC ! #ifndef NEW_GC ! static void ! finalize_string (void *header, int for_disksave) ! { ! if (!for_disksave) ! { ! Lisp_String *s = (Lisp_String *) header; ! Bytecount size = s->size_; ! if (BIG_STRING_SIZE_P (size)) ! xfree (s->data_, Ibyte *); ! } ! } ! ! DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("string", string, ! 1, /*dumpable-flag*/ ! mark_string, print_string, ! finalize_string, ! string_equal, 0, ! string_description, ! string_getprop, ! string_putprop, ! string_remprop, ! string_plist, ! Lisp_String); ! #else /* NEW_GC */ DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("string", string, 1, /*dumpable-flag*/ mark_string, print_string, --- 2356,2362 ---- #define MARK_STRING_CHARS_AS_FREE(ptr) ((void) ((ptr)->string = NULL)) #endif /* not NEW_GC */ ! #ifdef NEW_GC DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("string", string, 1, /*dumpable-flag*/ mark_string, print_string, *************** *** 2422,2428 **** string_indirect_data_description, Lisp_String_Indirect_Data); #endif /* NEW_GC */ - #endif /* MC_ALLOC */ #ifndef NEW_GC struct string_chars --- 2405,2410 ---- *************** *** 2524,2543 **** assert (length >= 0 && fullsize > 0); ! #ifdef MC_ALLOC s = alloc_lrecord_type (Lisp_String, &lrecord_string); ! #else /* not MC_ALLOC */ /* Allocate the string header */ ALLOCATE_FIXED_TYPE (string, Lisp_String, s); xzero (*s); set_lheader_implementation (&s->u.lheader, &lrecord_string); ! #endif /* not MC_ALLOC */ /* The above allocations set the UID field, which overlaps with the ascii-length field, to some non-zero value. We need to zero it. */ XSET_STRING_ASCII_BEGIN (wrap_string (s), 0); #ifdef NEW_GC STRING_DATA_OBJECT (s) = wrap_string_direct_data (alloc_lrecord (fullsize, &lrecord_string_direct_data)); --- 2506,2526 ---- assert (length >= 0 && fullsize > 0); ! #ifdef NEW_GC s = alloc_lrecord_type (Lisp_String, &lrecord_string); ! #else /* not NEW_GC */ /* Allocate the string header */ ALLOCATE_FIXED_TYPE (string, Lisp_String, s); xzero (*s); set_lheader_implementation (&s->u.lheader, &lrecord_string); ! #endif /* not NEW_GC */ /* The above allocations set the UID field, which overlaps with the ascii-length field, to some non-zero value. We need to zero it. */ XSET_STRING_ASCII_BEGIN (wrap_string (s), 0); #ifdef NEW_GC + set_lispstringp_direct (s); STRING_DATA_OBJECT (s) = wrap_string_direct_data (alloc_lrecord (fullsize, &lrecord_string_direct_data)); *************** *** 2616,2622 **** memmove (XSTRING_DATA (s) + pos + delta, XSTRING_DATA (s) + pos, len); ! #else /* NEW_GC */ oldfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s)); newfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s) + delta); --- 2599,2605 ---- memmove (XSTRING_DATA (s) + pos + delta, XSTRING_DATA (s) + pos, len); ! #else /* not NEW_GC */ oldfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s)); newfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s) + delta); *************** *** 2929,2945 **** bytecount_to_charcount (contents, length); /* Just for the assertions */ #endif ! #ifdef MC_ALLOC s = alloc_lrecord_type (Lisp_String, &lrecord_string); mcpro (wrap_pointer_1 (s)); /* otherwise nocopy_strings get collected and static data is tried to be freed. */ ! #else /* not MC_ALLOC */ /* Allocate the string header */ ALLOCATE_FIXED_TYPE (string, Lisp_String, s); set_lheader_implementation (&s->u.lheader, &lrecord_string); SET_C_READONLY_RECORD_HEADER (&s->u.lheader); ! #endif /* not MC_ALLOC */ /* Don't need to XSET_STRING_ASCII_BEGIN() here because it happens in init_string_ascii_begin(). */ s->plist = Qnil; --- 2912,2928 ---- bytecount_to_charcount (contents, length); /* Just for the assertions */ #endif ! #ifdef NEW_GC s = alloc_lrecord_type (Lisp_String, &lrecord_string); mcpro (wrap_pointer_1 (s)); /* otherwise nocopy_strings get collected and static data is tried to be freed. */ ! #else /* not NEW_GC */ /* Allocate the string header */ ALLOCATE_FIXED_TYPE (string, Lisp_String, s); set_lheader_implementation (&s->u.lheader, &lrecord_string); SET_C_READONLY_RECORD_HEADER (&s->u.lheader); ! #endif /* not NEW_GC */ /* Don't need to XSET_STRING_ASCII_BEGIN() here because it happens in init_string_ascii_begin(). */ s->plist = Qnil; *************** *** 2963,2969 **** } ! #ifndef MC_ALLOC /************************************************************************/ /* lcrecord lists */ /************************************************************************/ --- 2946,2952 ---- } ! #ifndef NEW_GC /************************************************************************/ /* lcrecord lists */ /************************************************************************/ *************** *** 3171,3177 **** free_managed_lcrecord (all_lcrecord_lists[type], rec); } ! #endif /* not MC_ALLOC */ DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /* --- 3154,3160 ---- free_managed_lcrecord (all_lcrecord_lists[type], rec); } ! #endif /* not NEW_GC */ DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /* *************** *** 3350,3356 **** ! #ifdef MC_ALLOC static const struct memory_description mcpro_description_1[] = { { XD_END } }; --- 3333,3339 ---- ! #ifdef NEW_GC static const struct memory_description mcpro_description_1[] = { { XD_END } }; *************** *** 3421,3430 **** } #endif /* not DEBUG_XEMACS */ ! #endif /* MC_ALLOC */ ! #ifndef MC_ALLOC static int gc_count_num_short_string_in_use; static Bytecount gc_count_string_total_size; static Bytecount gc_count_short_string_total_size; --- 3404,3413 ---- } #endif /* not DEBUG_XEMACS */ ! #endif /* NEW_GC */ ! #ifndef NEW_GC static int gc_count_num_short_string_in_use; static Bytecount gc_count_string_total_size; static Bytecount gc_count_short_string_total_size; *************** *** 3470,3479 **** } } } ! #endif /* not MC_ALLOC */ ! #ifndef MC_ALLOC /* Free all unmarked records */ static void sweep_lcrecords_1 (struct old_lcrecord_header **prev, int *used) --- 3453,3462 ---- } } } ! #endif /* not NEW_GC */ ! #ifndef NEW_GC /* Free all unmarked records */ static void sweep_lcrecords_1 (struct old_lcrecord_header **prev, int *used) *************** *** 3669,3678 **** #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ SWEEP_FIXED_TYPE_BLOCK_1 (typename, obj_type, lheader) ! #endif /* not MC_ALLOC */ ! #ifndef MC_ALLOC static void sweep_conses (void) { --- 3652,3661 ---- #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ SWEEP_FIXED_TYPE_BLOCK_1 (typename, obj_type, lheader) ! #endif /* not NEW_GC */ ! #ifndef NEW_GC static void sweep_conses (void) { *************** *** 3681,3700 **** SWEEP_FIXED_TYPE_BLOCK (cons, Lisp_Cons); } ! #endif /* not MC_ALLOC */ /* Explicitly free a cons cell. */ void free_cons (Lisp_Object cons) { ! #ifndef MC_ALLOC /* to avoid compiler warning */ Lisp_Cons *ptr = XCONS (cons); ! #endif /* MC_ALLOC */ #ifdef ERROR_CHECK_GC ! #ifdef MC_ALLOC Lisp_Cons *ptr = XCONS (cons); ! #endif /* MC_ALLOC */ /* If the CAR is not an int, then it will be a pointer, which will always be four-byte aligned. If this cons cell has already been placed on the free list, however, its car will probably contain --- 3664,3683 ---- SWEEP_FIXED_TYPE_BLOCK (cons, Lisp_Cons); } ! #endif /* not NEW_GC */ /* Explicitly free a cons cell. */ void free_cons (Lisp_Object cons) { ! #ifndef NEW_GC /* to avoid compiler warning */ Lisp_Cons *ptr = XCONS (cons); ! #endif /* not NEW_GC */ #ifdef ERROR_CHECK_GC ! #ifdef NEW_GC Lisp_Cons *ptr = XCONS (cons); ! #endif /* NEW_GC */ /* If the CAR is not an int, then it will be a pointer, which will always be four-byte aligned. If this cons cell has already been placed on the free list, however, its car will probably contain *************** *** 3709,3719 **** ASSERT_VALID_POINTER (XPNTR (cons_car (ptr))); #endif /* ERROR_CHECK_GC */ ! #ifdef MC_ALLOC free_lrecord (cons); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, Lisp_Cons, ptr); ! #endif /* not MC_ALLOC */ } /* explicitly free a list. You **must make sure** that you have --- 3692,3702 ---- ASSERT_VALID_POINTER (XPNTR (cons_car (ptr))); #endif /* ERROR_CHECK_GC */ ! #ifdef NEW_GC free_lrecord (cons); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, Lisp_Cons, ptr); ! #endif /* not NEW_GC */ } /* explicitly free a list. You **must make sure** that you have *************** *** 3751,3757 **** } } ! #ifndef MC_ALLOC static void sweep_compiled_functions (void) { --- 3734,3740 ---- } } ! #ifndef NEW_GC static void sweep_compiled_functions (void) { *************** *** 3830,3840 **** SWEEP_FIXED_TYPE_BLOCK (event, Lisp_Event); } ! #endif /* not MC_ALLOC */ #ifdef EVENT_DATA_AS_OBJECTS ! #ifndef MC_ALLOC static void sweep_key_data (void) { --- 3813,3823 ---- SWEEP_FIXED_TYPE_BLOCK (event, Lisp_Event); } ! #endif /* not NEW_GC */ #ifdef EVENT_DATA_AS_OBJECTS ! #ifndef NEW_GC static void sweep_key_data (void) { *************** *** 3843,3861 **** SWEEP_FIXED_TYPE_BLOCK (key_data, Lisp_Key_Data); } ! #endif /* not MC_ALLOC */ void free_key_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (key_data, Lisp_Key_Data, XKEY_DATA (ptr)); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC static void sweep_button_data (void) { --- 3826,3844 ---- SWEEP_FIXED_TYPE_BLOCK (key_data, Lisp_Key_Data); } ! #endif /* not NEW_GC */ void free_key_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (key_data, Lisp_Key_Data, XKEY_DATA (ptr)); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC static void sweep_button_data (void) { *************** *** 3864,3882 **** SWEEP_FIXED_TYPE_BLOCK (button_data, Lisp_Button_Data); } ! #endif /* not MC_ALLOC */ void free_button_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (button_data, Lisp_Button_Data, XBUTTON_DATA (ptr)); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC static void sweep_motion_data (void) { --- 3847,3865 ---- SWEEP_FIXED_TYPE_BLOCK (button_data, Lisp_Button_Data); } ! #endif /* not NEW_GC */ void free_button_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (button_data, Lisp_Button_Data, XBUTTON_DATA (ptr)); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC static void sweep_motion_data (void) { *************** *** 3885,3903 **** SWEEP_FIXED_TYPE_BLOCK (motion_data, Lisp_Motion_Data); } ! #endif /* not MC_ALLOC */ void free_motion_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (motion_data, Lisp_Motion_Data, XMOTION_DATA (ptr)); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC static void sweep_process_data (void) { --- 3868,3886 ---- SWEEP_FIXED_TYPE_BLOCK (motion_data, Lisp_Motion_Data); } ! #endif /* not NEW_GC */ void free_motion_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (motion_data, Lisp_Motion_Data, XMOTION_DATA (ptr)); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC static void sweep_process_data (void) { *************** *** 3906,3924 **** SWEEP_FIXED_TYPE_BLOCK (process_data, Lisp_Process_Data); } ! #endif /* not MC_ALLOC */ void free_process_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (process_data, Lisp_Process_Data, XPROCESS_DATA (ptr)); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC static void sweep_timeout_data (void) { --- 3889,3907 ---- SWEEP_FIXED_TYPE_BLOCK (process_data, Lisp_Process_Data); } ! #endif /* not NEW_GC */ void free_process_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (process_data, Lisp_Process_Data, XPROCESS_DATA (ptr)); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC static void sweep_timeout_data (void) { *************** *** 3927,3945 **** SWEEP_FIXED_TYPE_BLOCK (timeout_data, Lisp_Timeout_Data); } ! #endif /* not MC_ALLOC */ void free_timeout_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (timeout_data, Lisp_Timeout_Data, XTIMEOUT_DATA (ptr)); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC static void sweep_magic_data (void) { --- 3910,3928 ---- SWEEP_FIXED_TYPE_BLOCK (timeout_data, Lisp_Timeout_Data); } ! #endif /* not NEW_GC */ void free_timeout_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (timeout_data, Lisp_Timeout_Data, XTIMEOUT_DATA (ptr)); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC static void sweep_magic_data (void) { *************** *** 3948,3966 **** SWEEP_FIXED_TYPE_BLOCK (magic_data, Lisp_Magic_Data); } ! #endif /* not MC_ALLOC */ void free_magic_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_data, Lisp_Magic_Data, XMAGIC_DATA (ptr)); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC static void sweep_magic_eval_data (void) { --- 3931,3949 ---- SWEEP_FIXED_TYPE_BLOCK (magic_data, Lisp_Magic_Data); } ! #endif /* not NEW_GC */ void free_magic_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_data, Lisp_Magic_Data, XMAGIC_DATA (ptr)); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC static void sweep_magic_eval_data (void) { *************** *** 3969,3987 **** SWEEP_FIXED_TYPE_BLOCK (magic_eval_data, Lisp_Magic_Eval_Data); } ! #endif /* not MC_ALLOC */ void free_magic_eval_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_eval_data, Lisp_Magic_Eval_Data, XMAGIC_EVAL_DATA (ptr)); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC static void sweep_eval_data (void) { --- 3952,3970 ---- SWEEP_FIXED_TYPE_BLOCK (magic_eval_data, Lisp_Magic_Eval_Data); } ! #endif /* not NEW_GC */ void free_magic_eval_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_eval_data, Lisp_Magic_Eval_Data, XMAGIC_EVAL_DATA (ptr)); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC static void sweep_eval_data (void) { *************** *** 3990,4008 **** SWEEP_FIXED_TYPE_BLOCK (eval_data, Lisp_Eval_Data); } ! #endif /* not MC_ALLOC */ void free_eval_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (eval_data, Lisp_Eval_Data, XEVAL_DATA (ptr)); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC static void sweep_misc_user_data (void) { --- 3973,3991 ---- SWEEP_FIXED_TYPE_BLOCK (eval_data, Lisp_Eval_Data); } ! #endif /* not NEW_GC */ void free_eval_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (eval_data, Lisp_Eval_Data, XEVAL_DATA (ptr)); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC static void sweep_misc_user_data (void) { *************** *** 4011,4031 **** SWEEP_FIXED_TYPE_BLOCK (misc_user_data, Lisp_Misc_User_Data); } ! #endif /* not MC_ALLOC */ void free_misc_user_data (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (misc_user_data, Lisp_Misc_User_Data, XMISC_USER_DATA (ptr)); ! #endif /* not MC_ALLOC */ } #endif /* EVENT_DATA_AS_OBJECTS */ ! #ifndef MC_ALLOC static void sweep_markers (void) { --- 3994,4014 ---- SWEEP_FIXED_TYPE_BLOCK (misc_user_data, Lisp_Misc_User_Data); } ! #endif /* not NEW_GC */ void free_misc_user_data (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (misc_user_data, Lisp_Misc_User_Data, XMISC_USER_DATA (ptr)); ! #endif /* not NEW_GC */ } #endif /* EVENT_DATA_AS_OBJECTS */ ! #ifndef NEW_GC static void sweep_markers (void) { *************** *** 4038,4054 **** SWEEP_FIXED_TYPE_BLOCK (marker, Lisp_Marker); } ! #endif /* not MC_ALLOC */ /* Explicitly free a marker. */ void free_marker (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, XMARKER (ptr)); ! #endif /* not MC_ALLOC */ } --- 4021,4037 ---- SWEEP_FIXED_TYPE_BLOCK (marker, Lisp_Marker); } ! #endif /* not NEW_GC */ /* Explicitly free a marker. */ void free_marker (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, XMARKER (ptr)); ! #endif /* not NEW_GC */ } *************** *** 4201,4207 **** } #endif /* not NEW_GC */ ! #ifndef MC_ALLOC #if 1 /* Hack to debug missing purecopy's */ static int debug_string_purity; --- 4184,4190 ---- } #endif /* not NEW_GC */ ! #ifndef NEW_GC #if 1 /* Hack to debug missing purecopy's */ static int debug_string_purity; *************** *** 4224,4232 **** stderr_out ("\"\n"); } #endif /* 1 */ ! #endif /* not MC_ALLOC */ ! #ifndef MC_ALLOC static void sweep_strings (void) { --- 4207,4215 ---- stderr_out ("\"\n"); } #endif /* 1 */ ! #endif /* not NEW_GC */ ! #ifndef NEW_GC static void sweep_strings (void) { *************** *** 4259,4275 **** gc_count_string_total_size = num_bytes; gc_count_short_string_total_size = num_small_bytes; } ! #endif /* not MC_ALLOC */ #ifndef NEW_GC void gc_sweep_1 (void) { - #ifdef MC_ALLOC - compact_string_chars (); - mc_finalize (); - mc_sweep (); - #else /* not MC_ALLOC */ /* Free all unmarked records. Do this at the very beginning, before anything else, so that the finalize methods can safely examine items in the objects. sweep_lcrecords_1() makes --- 4242,4253 ---- gc_count_string_total_size = num_bytes; gc_count_short_string_total_size = num_small_bytes; } ! #endif /* not NEW_GC */ #ifndef NEW_GC void gc_sweep_1 (void) { /* Free all unmarked records. Do this at the very beginning, before anything else, so that the finalize methods can safely examine items in the objects. sweep_lcrecords_1() makes *************** *** 4344,4356 **** sweep_eval_data (); sweep_misc_user_data (); #endif /* EVENT_DATA_AS_OBJECTS */ ! #endif /* not MC_ALLOC */ ! #ifndef MC_ALLOC #ifdef PDUMP pdump_objects_unmark (); #endif - #endif /* not MC_ALLOC */ } #endif /* not NEW_GC */ --- 4322,4333 ---- sweep_eval_data (); sweep_misc_user_data (); #endif /* EVENT_DATA_AS_OBJECTS */ ! #endif /* not NEW_GC */ ! #ifndef NEW_GC #ifdef PDUMP pdump_objects_unmark (); #endif } #endif /* not NEW_GC */ *************** *** 4440,4446 **** int i; EMACS_INT tgu_val = 0; ! #ifdef MC_ALLOC for (i = 0; i < (countof (lrecord_implementations_table) + MODULE_DEFINABLE_TYPE_COUNT); i++) --- 4417,4423 ---- int i; EMACS_INT tgu_val = 0; ! #ifdef NEW_GC for (i = 0; i < (countof (lrecord_implementations_table) + MODULE_DEFINABLE_TYPE_COUNT); i++) *************** *** 4475,4481 **** } } ! #else /* not MC_ALLOC */ #define HACK_O_MATIC(type, name, pl) do { \ EMACS_INT s = 0; \ --- 4452,4458 ---- } } ! #else /* not NEW_GC */ #define HACK_O_MATIC(type, name, pl) do { \ EMACS_INT s = 0; \ *************** *** 4577,4583 **** #undef HACK_O_MATIC ! #endif /* MC_ALLOC */ if (set_total_gc_usage) { --- 4554,4560 ---- #undef HACK_O_MATIC ! #endif /* NEW_GC */ if (set_total_gc_usage) { *************** *** 4625,4631 **** total_gc_usage_set = 0; #ifdef ALLOC_TYPE_STATS /* The things we do for backwards-compatibility */ ! #ifdef MC_ALLOC return list6 (Fcons (make_int (lrecord_stats[lrecord_type_cons].instances_in_use), --- 4602,4608 ---- total_gc_usage_set = 0; #ifdef ALLOC_TYPE_STATS /* The things we do for backwards-compatibility */ ! #ifdef NEW_GC return list6 (Fcons (make_int (lrecord_stats[lrecord_type_cons].instances_in_use), *************** *** 4642,4648 **** make_int (lrecord_stats[lrecord_type_vector] .bytes_in_use_including_overhead), object_memory_usage_stats (1)); ! #else /* not MC_ALLOC */ return list6 (Fcons (make_int (gc_count_num_cons_in_use), make_int (gc_count_num_cons_freelist)), --- 4619,4625 ---- make_int (lrecord_stats[lrecord_type_vector] .bytes_in_use_including_overhead), object_memory_usage_stats (1)); ! #else /* not NEW_GC */ return list6 (Fcons (make_int (gc_count_num_cons_in_use), make_int (gc_count_num_cons_freelist)), *************** *** 4654,4660 **** make_int (lcrecord_stats[lrecord_type_vector].bytes_in_use + lcrecord_stats[lrecord_type_vector].bytes_freed), object_memory_usage_stats (1)); ! #endif /* not MC_ALLOC */ #else /* not ALLOC_TYPE_STATS */ return Qnil; #endif /* ALLOC_TYPE_STATS */ --- 4631,4637 ---- make_int (lcrecord_stats[lrecord_type_vector].bytes_in_use + lcrecord_stats[lrecord_type_vector].bytes_freed), object_memory_usage_stats (1)); ! #endif /* not NEW_GC */ #else /* not ALLOC_TYPE_STATS */ return Qnil; #endif /* ALLOC_TYPE_STATS */ *************** *** 4849,4855 **** return claimed_size; } ! #ifndef MC_ALLOC Bytecount fixed_type_block_overhead (Bytecount size) { --- 4826,4832 ---- return claimed_size; } ! #ifndef NEW_GC Bytecount fixed_type_block_overhead (Bytecount size) { *************** *** 4865,4871 **** overhead += sizeof (void *) + per_block - storage_size; return overhead; } ! #endif /* not MC_ALLOC */ #endif /* MEMORY_USAGE_STATS */ --- 4842,4848 ---- overhead += sizeof (void *) + per_block - storage_size; return overhead; } ! #endif /* not NEW_GC */ #endif /* MEMORY_USAGE_STATS */ *************** *** 4883,4894 **** Qnull_pointer = wrap_pointer_1 (0); #endif ! #ifndef MC_ALLOC breathing_space = 0; - #endif /* not MC_ALLOC */ - #ifndef MC_ALLOC all_lcrecords = 0; ! #endif /* not MC_ALLOC */ ignore_malloc_warnings = 1; #ifdef DOUG_LEA_MALLOC mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ --- 4860,4869 ---- Qnull_pointer = wrap_pointer_1 (0); #endif ! #ifndef NEW_GC breathing_space = 0; all_lcrecords = 0; ! #endif /* not NEW_GC */ ignore_malloc_warnings = 1; #ifdef DOUG_LEA_MALLOC mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ *************** *** 4899,4906 **** #endif #ifndef NEW_GC init_string_chars_alloc (); - #endif /* not NEW_GC */ - #ifndef MC_ALLOC init_string_alloc (); init_string_chars_alloc (); init_cons_alloc (); --- 4874,4879 ---- *************** *** 4930,4936 **** init_eval_data_alloc (); init_misc_user_data_alloc (); #endif /* EVENT_DATA_AS_OBJECTS */ ! #endif /* not MC_ALLOC */ ignore_malloc_warnings = 0; --- 4903,4909 ---- init_eval_data_alloc (); init_misc_user_data_alloc (); #endif /* EVENT_DATA_AS_OBJECTS */ ! #endif /* not NEW_GC */ ignore_malloc_warnings = 0; *************** *** 4945,4951 **** Dynarr_resize (staticpro_nodump_names, 100); /* ditto */ #endif ! #ifdef MC_ALLOC mcpros = Dynarr_new2 (Lisp_Object_dynarr, Lisp_Object); Dynarr_resize (mcpros, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&mcpros, &mcpros_description); --- 4918,4924 ---- Dynarr_resize (staticpro_nodump_names, 100); /* ditto */ #endif ! #ifdef NEW_GC mcpros = Dynarr_new2 (Lisp_Object_dynarr, Lisp_Object); Dynarr_resize (mcpros, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&mcpros, &mcpros_description); *************** *** 4954,4960 **** Dynarr_resize (mcpro_names, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description); #endif ! #endif /* MC_ALLOC */ consing_since_gc = 0; need_to_check_c_alloca = 0; --- 4927,4933 ---- Dynarr_resize (mcpro_names, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description); #endif ! #endif /* NEW_GC */ consing_since_gc = 0; need_to_check_c_alloca = 0; *************** *** 4962,4970 **** funcall_alloca_count = 0; lrecord_uid_counter = 259; ! #ifndef MC_ALLOC debug_string_purity = 0; ! #endif /* not MC_ALLOC */ #ifdef ERROR_CHECK_TYPES ERROR_ME.really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = --- 4935,4943 ---- funcall_alloca_count = 0; lrecord_uid_counter = 259; ! #ifndef NEW_GC debug_string_purity = 0; ! #endif /* not NEW_GC */ #ifdef ERROR_CHECK_TYPES ERROR_ME.really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = *************** *** 4980,4986 **** #endif /* ERROR_CHECK_TYPES */ } ! #ifndef MC_ALLOC static void init_lcrecord_lists (void) { --- 4953,4959 ---- #endif /* ERROR_CHECK_TYPES */ } ! #ifndef NEW_GC static void init_lcrecord_lists (void) { *************** *** 4992,4998 **** staticpro_nodump (&all_lcrecord_lists[i]); } } ! #endif /* not MC_ALLOC */ void init_alloc_early (void) --- 4965,4971 ---- staticpro_nodump (&all_lcrecord_lists[i]); } } ! #endif /* not NEW_GC */ void init_alloc_early (void) *************** *** 5013,5021 **** reinit_alloc_early (void) { common_init_alloc_early (); ! #ifndef MC_ALLOC init_lcrecord_lists (); ! #endif /* not MC_ALLOC */ } void --- 4986,4994 ---- reinit_alloc_early (void) { common_init_alloc_early (); ! #ifndef NEW_GC init_lcrecord_lists (); ! #endif /* not NEW_GC */ } void *************** *** 5036,5045 **** INIT_LRECORD_IMPLEMENTATION (string_indirect_data); INIT_LRECORD_IMPLEMENTATION (string_direct_data); #endif /* NEW_GC */ ! #ifndef MC_ALLOC INIT_LRECORD_IMPLEMENTATION (lcrecord_list); INIT_LRECORD_IMPLEMENTATION (free); ! #endif /* not MC_ALLOC */ staticpros = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); Dynarr_resize (staticpros, 1410); /* merely a small optimization */ --- 5009,5018 ---- INIT_LRECORD_IMPLEMENTATION (string_indirect_data); INIT_LRECORD_IMPLEMENTATION (string_direct_data); #endif /* NEW_GC */ ! #ifndef NEW_GC INIT_LRECORD_IMPLEMENTATION (lcrecord_list); INIT_LRECORD_IMPLEMENTATION (free); ! #endif /* not NEW_GC */ staticpros = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); Dynarr_resize (staticpros, 1410); /* merely a small optimization */ *************** *** 5050,5056 **** dump_add_root_block_ptr (&staticpro_names, &staticpro_names_description); #endif ! #ifdef MC_ALLOC mcpros = Dynarr_new2 (Lisp_Object_dynarr, Lisp_Object); Dynarr_resize (mcpros, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&mcpros, &mcpros_description); --- 5023,5029 ---- dump_add_root_block_ptr (&staticpro_names, &staticpro_names_description); #endif ! #ifdef NEW_GC mcpros = Dynarr_new2 (Lisp_Object_dynarr, Lisp_Object); Dynarr_resize (mcpros, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&mcpros, &mcpros_description); *************** *** 5059,5069 **** Dynarr_resize (mcpro_names, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description); #endif ! #endif /* MC_ALLOC */ ! ! #ifndef MC_ALLOC init_lcrecord_lists (); ! #endif /* not MC_ALLOC */ } void --- 5032,5040 ---- Dynarr_resize (mcpro_names, 1410); /* merely a small optimization */ dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description); #endif ! #else /* not NEW_GC */ init_lcrecord_lists (); ! #endif /* not NEW_GC */ } void diff -c /dev/null 'xemacs-21.5.26/src/alsaplay.c' Index: ./src/alsaplay.c *** ./src/alsaplay.c Thu Jan 1 09:00:00 1970 --- ./src/alsaplay.c Tue Mar 28 02:40:58 2006 *************** *** 0 **** --- 1,404 ---- + /* Play sound with the ALSA library + Copyright (C) 2006 Jerry James. + + This file is part of XEmacs. + + XEmacs 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. + + XEmacs 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 XEmacs; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + /* Synched up with: Not in FSF. */ + + /* TODO: Support asynchronous sound playing; see the NAS support in sound.c */ + + #include + #include "lisp.h" + #include "sound.h" + #include "sysfile.h" + + /* We can't just include because it tries to redefine + * several symbols defined by the previous header files. + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + struct mixer_state + { + snd_mixer_t *mixer; + snd_mixer_elem_t *vol_ctl; + + /* Which channels need the old volume restored */ + int reset_front_left; + int reset_front_center; + int reset_front_right; + int reset_rear_left; + int reset_rear_center; + int reset_rear_right; + int reset_side_left; + int reset_side_right; + int reset_woofer; + + /* Old volumes for the channels */ + long front_left_vol; + long front_center_vol; + long front_right_vol; + long rear_left_vol; + long rear_center_vol; + long rear_right_vol; + long side_left_vol; + long side_right_vol; + long woofer_vol; + }; + + /* Assemble a machine half-word in little-endian order */ + #define HALF_LE(arr,start) (arr[start] + (arr[start + 1] << 8)) + + /* Assemble a machine word in little-endian order */ + #define WORD_LE(arr,start) (arr[start] + (arr[start + 1] << 8) + \ + (arr[start + 2] << 16) + (arr[start + 3] << 24)) + + /* Assemble a machine word in big-endian order */ + #define WORD_BE(arr,start) ((arr[start] << 24) + (arr[start + 1] << 16) + \ + (arr[start + 2] << 8) + arr[start + 3]) + + /* This function was inspired by miscplay.c. + * Examine sound data to determine its format. + * + * TODO: Detect other formats that ALSA can play, such as GSM and MPEG. + */ + static snd_pcm_format_t + analyze_format (const Binbyte *format, int *speed, int *tracks) + { + if (!memcmp (format, "Creative Voice File\x1A\x1A\x00", 22) && + HALF_LE (format, 22) == ((0x1233 - HALF_LE (format, 24)) & 0xFFFF)) + { + /* VOC */ + *speed = 8000; + *tracks = 2; + return SND_PCM_FORMAT_U8; + } + else if (!memcmp (format, "RIFF", 4) && !memcmp (format + 8, "WAVEfmt ", 8)) + { + /* WAVE */ + *speed = WORD_LE (format, 24); + *tracks = format[22]; + return format[32] / format[22] == 1 + ? SND_PCM_FORMAT_U8 + : SND_PCM_FORMAT_S16_LE; + } + else if (!memcmp (format, ".snd", 4)) + { + /* Sun/NeXT Audio (big endian) */ + if (WORD_BE (format, 4) < 24) + { + *speed = 8000; + *tracks = 1; + return SND_PCM_FORMAT_MU_LAW; + } + *speed = WORD_BE (format, 16); + *tracks = format[23]; + if (!memcmp (format + 12, "\000\000\000", 3)) + { + switch (format[15]) + { + case 1: + case 17: + case 29: + return SND_PCM_FORMAT_MU_LAW; + case 2: + return SND_PCM_FORMAT_S8; + case 3: + return SND_PCM_FORMAT_S16_BE; + case 4: + return SND_PCM_FORMAT_S24_BE; + case 5: + return SND_PCM_FORMAT_S32_BE; + case 23: + case 24: + case 25: + case 26: + return SND_PCM_FORMAT_IMA_ADPCM; + case 27: + return SND_PCM_FORMAT_A_LAW; + default: + break; + } + } + return SND_PCM_FORMAT_UNKNOWN; + } + else if (!memcmp (format, ".sd", 4)) + { + /* DEC Audio (little endian) */ + if (WORD_LE (format, 4) < 24) + { + *speed = 8000; + *tracks = 1; + return SND_PCM_FORMAT_MU_LAW; + } + *speed = WORD_LE (format, 16); + *tracks = format[20]; + if (!memcmp (format + 13, "\000\000\000", 3)) + { + switch (format[12]) + { + case 1: + case 17: + case 29: + return SND_PCM_FORMAT_MU_LAW; + case 2: + return SND_PCM_FORMAT_S8; + case 3: + return SND_PCM_FORMAT_S16_LE; + case 4: + return SND_PCM_FORMAT_S24_LE; + case 5: + return SND_PCM_FORMAT_S32_LE; + case 23: + case 24: + case 25: + case 26: + return SND_PCM_FORMAT_IMA_ADPCM; + case 27: + return SND_PCM_FORMAT_A_LAW; + default: + break; + } + } + return SND_PCM_FORMAT_UNKNOWN; + } + else + { + /* We don't know what it is. Guess that it is mono audio in unsigned + * byte format. Maybe we should error if we reach this point. + */ + *speed = 8000; + *tracks = 1; + return SND_PCM_FORMAT_U8; + } + } + + /* Set the volume: if any errors occur, we accept the existing volume */ + static void + set_volume (struct mixer_state *mix, int volume) + { + snd_mixer_selem_id_t *volume_id; + long min_vol, max_vol, dev_vol; + + if (snd_mixer_open (&mix->mixer, 0) < 0) + return; + + if (snd_mixer_attach (mix->mixer, "default") < 0) + return; + + if (snd_mixer_selem_register (mix->mixer, NULL, NULL) < 0) + return; + + if (snd_mixer_load (mix->mixer) < 0) + return; + + snd_mixer_selem_id_alloca (&volume_id); + snd_mixer_selem_id_set_name (volume_id, "PCM"); + + if ((mix->vol_ctl = snd_mixer_find_selem (mix->mixer, volume_id)) == NULL) + { + snd_mixer_selem_id_set_name (volume_id, "Master"); + if ((mix->vol_ctl = snd_mixer_find_selem (mix->mixer, volume_id)) + == NULL) + return; + } + + /* Translate the Lisp volume range to the device volume range */ + if (snd_mixer_selem_get_playback_volume_range (mix->vol_ctl, &min_vol, + &max_vol) < 0) + return; + + dev_vol = volume * (max_vol - min_vol) / 100 + min_vol; + + /* Record the old volumes */ + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_FRONT_LEFT, &mix->front_left_vol) >= 0) + mix->reset_front_left = 1; + + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_FRONT_CENTER, &mix->front_center_vol) >= 0) + mix->reset_front_center = 1; + + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_FRONT_RIGHT, &mix->front_right_vol) >= 0) + mix->reset_front_right = 1; + + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_REAR_LEFT, &mix->rear_left_vol) >= 0) + mix->reset_rear_left = 1; + + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_REAR_CENTER, &mix->rear_center_vol) >= 0) + mix->reset_rear_center = 1; + + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_REAR_RIGHT, &mix->rear_right_vol) >= 0) + mix->reset_rear_right = 1; + + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_SIDE_LEFT, &mix->side_left_vol) >= 0) + mix->reset_side_left = 1; + + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_SIDE_RIGHT, &mix->side_right_vol) >= 0) + mix->reset_side_right = 1; + + if (snd_mixer_selem_get_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_WOOFER, &mix->woofer_vol) >= 0) + mix->reset_woofer = 1; + + /* Set the volume */ + snd_mixer_selem_set_playback_volume_all (mix->vol_ctl, dev_vol); + } + + static void + reset_volume (const struct mixer_state *mix) + { + if (mix->reset_front_left) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_FRONT_LEFT, mix->front_left_vol); + + if (mix->reset_front_center) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_FRONT_CENTER, mix->front_center_vol); + + if (mix->reset_front_right) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_FRONT_RIGHT, mix->front_right_vol); + + if (mix->reset_rear_left) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_REAR_LEFT, mix->rear_left_vol); + + if (mix->reset_rear_center) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_REAR_CENTER, mix->rear_center_vol); + + if (mix->reset_rear_right) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_REAR_RIGHT, mix->rear_right_vol); + + if (mix->reset_side_left) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_SIDE_LEFT, mix->side_left_vol); + + if (mix->reset_side_right) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_SIDE_RIGHT, mix->side_right_vol); + + if (mix->reset_woofer) + snd_mixer_selem_set_playback_volume + (mix->vol_ctl, SND_MIXER_SCHN_WOOFER, mix->woofer_vol); + + snd_mixer_close (mix->mixer); + } + + int + alsa_play_sound_data (const Binbyte *data, int length, int volume) + { + snd_pcm_t *pcm_handle; + snd_pcm_hw_params_t *hwparams; + snd_pcm_format_t format; + struct mixer_state mix; + int speed, tracks, err; + + /* Set the PCM parameters */ + if ((err = snd_pcm_open (&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, + 0)) < 0) + goto error_pcm_open; + + snd_pcm_hw_params_alloca (&hwparams); + + if ((err = snd_pcm_hw_params_any (pcm_handle, hwparams)) < 0) + goto error_pcm; + + format = analyze_format (data, &speed, &tracks); + + if ((err = snd_pcm_hw_params_set_access (pcm_handle, hwparams, + SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) + goto error_pcm; + + if ((err = snd_pcm_hw_params_set_format (pcm_handle, hwparams, format)) < 0) + goto error_pcm; + + if ((err = snd_pcm_hw_params_set_rate (pcm_handle, hwparams, speed, 0)) < 0) + goto error_pcm; + + if ((err = snd_pcm_hw_params_set_channels (pcm_handle, hwparams, tracks)) + < 0) + goto error_pcm; + + if ((err = snd_pcm_hw_params (pcm_handle, hwparams)) < 0) + goto error_pcm; + + /* Set the volume */ + memset (&mix, 0, sizeof (mix)); + set_volume (&mix, volume); + + /* Play the sound */ + if ((err = snd_pcm_writei (pcm_handle, data, length)) < 0) + goto error_mixer; + + /* Put the volume back the way it used to be */ + reset_volume (&mix); + + /* Release resources */ + snd_pcm_close (pcm_handle); + return 1; + + error_mixer: + reset_volume (&mix); + error_pcm: + snd_pcm_close (pcm_handle); + error_pcm_open: + sound_perror (snd_strerror (err)); + return 0; + } + + /* Read the sound file into an internal buffer, then call + * alsa_play_sound_data. + */ + int + alsa_play_sound_file (const Extbyte *sound_file, int volume) + { + Binbyte *data; + int fd, retval; + struct stat st; + + fd = retry_open (sound_file, O_RDONLY, 0); + if (fd < 0) { + sound_perror (sound_file); + return 0; + } + + qxe_fstat (fd, &st); + data = xnew_array (Binbyte, st.st_size); + retry_read (fd, data, st.st_size); + retry_close (fd); + retval = alsa_play_sound_data (data, st.st_size, volume); + xfree (data, Binbyte); + return retval; + } diff -c 'xemacs-21.5.25/src/buffer.c' 'xemacs-21.5.26/src/buffer.c' Index: ./src/buffer.c *** ./src/buffer.c Sun Dec 18 06:04:16 2005 --- ./src/buffer.c Tue Feb 28 01:29:22 2006 *************** *** 2130,2136 **** /* The docstrings for DEFVAR_* are recorded externally by make-docfile. */ ! #ifdef MC_ALLOC #define DEFVAR_BUFFER_LOCAL_1(lname, field_name, forward_type, magic_fun) \ do \ { \ --- 2130,2136 ---- /* The docstrings for DEFVAR_* are recorded externally by make-docfile. */ ! #ifdef NEW_GC #define DEFVAR_BUFFER_LOCAL_1(lname, field_name, forward_type, magic_fun) \ do \ { \ *************** *** 2155,2161 **** } \ } while (0) ! #else /* not MC_ALLOC */ /* Renamed from DEFVAR_PER_BUFFER because FSFmacs D_P_B takes a bogus extra arg, which confuses an otherwise identical make-docfile.c */ #define DEFVAR_BUFFER_LOCAL_1(lname, field_name, forward_type, magicfun) \ --- 2155,2161 ---- } \ } while (0) ! #else /* not NEW_GC */ /* Renamed from DEFVAR_PER_BUFFER because FSFmacs D_P_B takes a bogus extra arg, which confuses an otherwise identical make-docfile.c */ #define DEFVAR_BUFFER_LOCAL_1(lname, field_name, forward_type, magicfun) \ *************** *** 2189,2195 **** = intern (lname); \ } \ } while (0) ! #endif /* not MC_ALLOC */ #define DEFVAR_BUFFER_LOCAL_MAGIC(lname, field_name, magicfun) \ DEFVAR_BUFFER_LOCAL_1 (lname, field_name, \ --- 2189,2195 ---- = intern (lname); \ } \ } while (0) ! #endif /* not NEW_GC */ #define DEFVAR_BUFFER_LOCAL_MAGIC(lname, field_name, magicfun) \ DEFVAR_BUFFER_LOCAL_1 (lname, field_name, \ diff -c 'xemacs-21.5.25/src/bytecode.c' 'xemacs-21.5.26/src/bytecode.c' Index: ./src/bytecode.c *** ./src/bytecode.c Fri Nov 25 10:41:56 2005 --- ./src/bytecode.c Tue Feb 28 01:29:22 2006 *************** *** 2247,2275 **** { XD_END } }; - #if defined(MC_ALLOC) && !defined(NEW_GC) - static void - finalize_compiled_function (void *header, int for_disksave) - { - if (!for_disksave) - { - struct Lisp_Compiled_Function *cf = - (struct Lisp_Compiled_Function *) header; - if (cf->args_in_array) - xfree (cf->args, Lisp_Object *); - } - } - - DEFINE_BASIC_LRECORD_IMPLEMENTATION ("compiled-function", compiled_function, - 1, /*dumpable_flag*/ - mark_compiled_function, - print_compiled_function, - finalize_compiled_function, - compiled_function_equal, - compiled_function_hash, - compiled_function_description, - Lisp_Compiled_Function); - #else /* !MC_ALLOC || NEW_GC */ DEFINE_BASIC_LRECORD_IMPLEMENTATION ("compiled-function", compiled_function, 1, /*dumpable_flag*/ mark_compiled_function, --- 2247,2252 ---- *************** *** 2278,2284 **** compiled_function_hash, compiled_function_description, Lisp_Compiled_Function); - #endif /* !MC_ALLOC || NEW_GC */ DEFUN ("compiled-function-p", Fcompiled_function_p, 1, 1, 0, /* --- 2255,2260 ---- diff -c 'xemacs-21.5.25/src/bytecode.h' 'xemacs-21.5.26/src/bytecode.h' Index: ./src/bytecode.h *** ./src/bytecode.h Fri Nov 25 10:41:56 2005 --- ./src/bytecode.h Tue Feb 28 01:29:22 2006 *************** *** 55,61 **** #define compiled_function_args_data(v) ((v)->args) #define XCOMPILED_FUNCTION_ARGS_DATA(s) \ compiled_function_args_data (XCOMPILED_FUNCTION_ARGS (s)) ! #endif /* not NEW_GC */ /* Meanings of slots in a Lisp_Compiled_Function. Don't use these! For backward compatibility only. */ --- 55,61 ---- #define compiled_function_args_data(v) ((v)->args) #define XCOMPILED_FUNCTION_ARGS_DATA(s) \ compiled_function_args_data (XCOMPILED_FUNCTION_ARGS (s)) ! #endif /* NEW_GC */ /* Meanings of slots in a Lisp_Compiled_Function. Don't use these! For backward compatibility only. */ diff -c 'xemacs-21.5.25/src/config.h.in' 'xemacs-21.5.26/src/config.h.in' Index: ./src/config.h.in *** ./src/config.h.in Wed Dec 28 03:51:29 2005 --- ./src/config.h.in Tue Mar 28 02:40:58 2006 *************** *** 693,702 **** /* If defined, use experimental pdump-based GC algorithms. */ #undef USE_KKCC ! /* If defined, use experimental allocator. */ ! #undef MC_ALLOC ! ! /* If defined, use experimental incremental garbage collector. */ #undef NEW_GC /* Virtual dirty bit implementation for incremental gc. */ --- 693,700 ---- /* If defined, use experimental pdump-based GC algorithms. */ #undef USE_KKCC ! /* If defined, use experimental incremental garbage collector and new ! allocator. */ #undef NEW_GC /* Virtual dirty bit implementation for incremental gc. */ *************** *** 797,802 **** --- 795,803 ---- /* Native sound may be provided via soundcard.h, in various directories */ #undef SOUNDCARD_H_FILE + + /* Compile in support for ALSA (Advanced Linux Sound Architecture) */ + #undef HAVE_ALSA_SOUND /* Compile in support for NAS (Network Audio System)? NAS_NO_ERROR_JUMP means that the NAS libraries don't include some diff -c 'xemacs-21.5.25/src/console-stream.c' 'xemacs-21.5.26/src/console-stream.c' Index: ./src/console-stream.c *** ./src/console-stream.c Fri Nov 25 10:41:57 2005 --- ./src/console-stream.c Tue Feb 28 01:29:23 2006 *************** *** 137,145 **** if (stream_con->in != stdin) retry_fclose (stream_con->in); ! #ifdef NEW_GC ! mc_free (stream_con); ! #else /* not NEW_GC */ xfree (stream_con, struct stream_console *); #endif /* not NEW_GC */ CONSOLE_STREAM_DATA (con) = NULL; --- 137,143 ---- if (stream_con->in != stdin) retry_fclose (stream_con->in); ! #ifndef NEW_GC xfree (stream_con, struct stream_console *); #endif /* not NEW_GC */ CONSOLE_STREAM_DATA (con) = NULL; diff -c 'xemacs-21.5.25/src/console.c' 'xemacs-21.5.26/src/console.c' Index: ./src/console.c *** ./src/console.c Sun Dec 18 20:44:28 2005 --- ./src/console.c Tue Feb 28 01:29:23 2006 *************** *** 1202,1208 **** INIT_LRECORD_IMPLEMENTATION (tty_console); #endif INIT_LRECORD_IMPLEMENTATION (stream_console); ! #endif /* not NEW_GC */ DEFSUBR (Fvalid_console_type_p); DEFSUBR (Fconsole_type_list); --- 1202,1208 ---- INIT_LRECORD_IMPLEMENTATION (tty_console); #endif INIT_LRECORD_IMPLEMENTATION (stream_console); ! #endif /* NEW_GC */ DEFSUBR (Fvalid_console_type_p); DEFSUBR (Fconsole_type_list); *************** *** 1325,1331 **** } /* The docstrings for DEFVAR_* are recorded externally by make-docfile. */ ! #ifdef MC_ALLOC #define DEFVAR_CONSOLE_LOCAL_1(lname, field_name, forward_type, magic_fun) \ do { \ struct symbol_value_forward *I_hate_C = \ --- 1325,1331 ---- } /* The docstrings for DEFVAR_* are recorded externally by make-docfile. */ ! #ifdef NEW_GC #define DEFVAR_CONSOLE_LOCAL_1(lname, field_name, forward_type, magic_fun) \ do { \ struct symbol_value_forward *I_hate_C = \ *************** *** 1349,1355 **** = intern (lname); \ } \ } while (0) ! #else /* not MC_ALLOC */ #define DEFVAR_CONSOLE_LOCAL_1(lname, field_name, forward_type, magicfun) \ do { \ static const struct symbol_value_forward I_hate_C = \ --- 1349,1355 ---- = intern (lname); \ } \ } while (0) ! #else /* not NEW_GC */ #define DEFVAR_CONSOLE_LOCAL_1(lname, field_name, forward_type, magicfun) \ do { \ static const struct symbol_value_forward I_hate_C = \ *************** *** 1382,1388 **** = intern (lname); \ } \ } while (0) ! #endif /* not MC_ALLOC */ #define DEFVAR_CONSOLE_LOCAL_MAGIC(lname, field_name, magicfun) \ DEFVAR_CONSOLE_LOCAL_1 (lname, field_name, \ --- 1382,1388 ---- = intern (lname); \ } \ } while (0) ! #endif /* not NEW_GC */ #define DEFVAR_CONSOLE_LOCAL_MAGIC(lname, field_name, magicfun) \ DEFVAR_CONSOLE_LOCAL_1 (lname, field_name, \ diff -c 'xemacs-21.5.25/src/depend' 'xemacs-21.5.26/src/depend' Index: ./src/depend *** ./src/depend Sat Nov 26 21:09:39 2005 --- ./src/depend Tue Mar 28 06:51:28 2006 *************** *** 106,111 **** --- 106,112 ---- abbrev.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h commands.h insdel.h redisplay.h scrollbar.h syntax.h window.h alloc.o: $(LISP_H) backtrace.h buffer.h bufslots.h bytecode.h casetab.h charset.h chartab.h coding-system-slots.h conslots.h console-impl.h console-stream.h console.h device.h elhash.h events.h extents-impl.h extents.h file-coding.h frame-impl.h frame.h frameslots.h glyphs.h lstream.h opaque.h process.h profile.h redisplay.h scrollbar.h specifier.h sysdep.h sysfile.h systime.h window-impl.h window.h winslots.h alloca.o: $(LISP_H) + alsaplay.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h sound.h sysfile.h blocktype.o: $(LISP_H) blocktype.h buffer.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h coding-system-slots.h commands.h conslots.h console-impl.h console.h device-impl.h device.h devslots.h elhash.h extents.h faces.h file-coding.h frame-impl.h frame.h frameslots.h insdel.h intl-auto-encap-win32.h lstream.h ndir.h process.h redisplay.h scrollbar.h select.h specifier.h syntax.h sysdir.h sysfile.h syswindows.h window.h bytecode.o: $(LISP_H) backtrace.h buffer.h bufslots.h bytecode.h casetab.h charset.h chartab.h opaque.h redisplay.h scrollbar.h syntax.h window.h diff -c 'xemacs-21.5.25/src/dumper.c' 'xemacs-21.5.26/src/dumper.c' Index: ./src/dumper.c *** ./src/dumper.c Tue Nov 29 00:44:06 2005 --- ./src/dumper.c Tue Feb 28 01:29:23 2006 *************** *** 237,243 **** static Rawbyte *pdump_rt_list = 0; ! #ifndef MC_ALLOC void pdump_objects_unmark (void) { --- 237,243 ---- static Rawbyte *pdump_rt_list = 0; ! #ifndef NEW_GC void pdump_objects_unmark (void) { *************** *** 261,270 **** break; } } ! #endif /* not MC_ALLOC */ ! #ifdef MC_ALLOC /* The structure of the dump file looks like this: 0 - header - dumped objects --- 261,270 ---- break; } } ! #endif /* not NEW_GC */ ! #ifdef NEW_GC /* The structure of the dump file looks like this: 0 - header - dumped objects *************** *** 281,287 **** - root lisp object address/value couples with the count preceding the list */ ! #else /* not MC_ALLOC */ /* The structure of the dump file looks like this: 0 - header - dumped objects --- 281,287 ---- - root lisp object address/value couples with the count preceding the list */ ! #else /* not NEW_GC */ /* The structure of the dump file looks like this: 0 - header - dumped objects *************** *** 296,302 **** - root lisp object address/value couples with the count preceding the list */ ! #endif /* not MC_ALLOC */ #define PDUMP_SIGNATURE "XEmacsDP" --- 296,302 ---- - root lisp object address/value couples with the count preceding the list */ ! #endif /* not NEW_GC */ #define PDUMP_SIGNATURE "XEmacsDP" *************** *** 434,440 **** static void *pdump_buf; static FILE *pdump_out; ! #ifdef MC_ALLOC /* PDUMP_HASHSIZE is a large prime. */ #define PDUMP_HASHSIZE 1000003 /* Nothing special about PDUMP_HASH_MULTIPLIER: arbitrary odd integer --- 434,440 ---- static void *pdump_buf; static FILE *pdump_out; ! #ifdef NEW_GC /* PDUMP_HASHSIZE is a large prime. */ #define PDUMP_HASHSIZE 1000003 /* Nothing special about PDUMP_HASH_MULTIPLIER: arbitrary odd integer *************** *** 443,465 **** /* Nothing special about PDUMP_HASH_STEP: arbitrary integer for linear probing. */ #define PDUMP_HASH_STEP 574853 ! #else /* not MC_ALLOC */ #define PDUMP_HASHSIZE 200001 ! #endif /* not MC_ALLOC */ static pdump_block_list_elt **pdump_hash; ! #ifndef MC_ALLOC /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */ ! #endif /* not MC_ALLOC */ static int pdump_make_hash (const void *obj) { ! #ifdef MC_ALLOC return ((unsigned long)(obj) * PDUMP_HASH_MULTIPLIER) % PDUMP_HASHSIZE; ! #else /* not MC_ALLOC */ return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE; ! #endif /* not MC_ALLOC */ } /* Return the entry for an already-registered memory block at OBJ, --- 443,465 ---- /* Nothing special about PDUMP_HASH_STEP: arbitrary integer for linear probing. */ #define PDUMP_HASH_STEP 574853 ! #else /* not NEW_GC */ #define PDUMP_HASHSIZE 200001 ! #endif /* not NEW_GC */ static pdump_block_list_elt **pdump_hash; ! #ifndef NEW_GC /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */ ! #endif /* not NEW_GC */ static int pdump_make_hash (const void *obj) { ! #ifdef NEW_GC return ((unsigned long)(obj) * PDUMP_HASH_MULTIPLIER) % PDUMP_HASHSIZE; ! #else /* not NEW_GC */ return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE; ! #endif /* not NEW_GC */ } /* Return the entry for an already-registered memory block at OBJ, *************** *** 524,530 **** } } ! #ifdef MC_ALLOC typedef struct mc_addr_elt { const void *obj; --- 524,530 ---- } } ! #ifdef NEW_GC typedef struct mc_addr_elt { const void *obj; *************** *** 587,593 **** pdump_mc_hash[pos].obj = obj; pdump_mc_hash[pos].addr = addr; } ! #endif /* MC_ALLOC */ static pdump_block_list * pdump_get_block_list (const struct memory_description *desc) --- 587,593 ---- pdump_mc_hash[pos].obj = obj; pdump_mc_hash[pos].addr = addr; } ! #endif /* NEW_GC */ static pdump_block_list * pdump_get_block_list (const struct memory_description *desc) *************** *** 879,884 **** --- 879,889 ---- imp = LHEADER_IMPLEMENTATION (objh); if (imp->description + #ifdef NEW_GC + /* Objects with finalizers cannot be dumped with the new + allocator's asynchronous finalization strategy. */ + && !imp->finalizer + #endif /* not NEW_GC */ && RECORD_DUMPABLE (objh)) { pdump_bump_depth (); *************** *** 1200,1206 **** retry_fwrite (desc ? pdump_buf : elt->obj, size, count, pdump_out); } ! #ifdef MC_ALLOC /* To be able to relocate during load time, more information about the dumped objects are needed: The count (for array-like data structures), the size of the object, and the location in the dumped --- 1205,1211 ---- retry_fwrite (desc ? pdump_buf : elt->obj, size, count, pdump_out); } ! #ifdef NEW_GC /* To be able to relocate during load time, more information about the dumped objects are needed: The count (for array-like data structures), the size of the object, and the location in the dumped *************** *** 1237,1245 **** if (pdump_object_table[i].align == align) for (elt = pdump_object_table[i].first; elt; elt = elt->next) { - #ifndef NEW_GC - assert (elt->count == 1); - #endif /* not NEW_GC */ f (elt, lrecord_implementations_table[i]->description); } } --- 1242,1247 ---- *************** *** 1300,1308 **** case XD_LONG: case XD_INT_RESET: break; - #ifdef NEW_GC case XD_LISP_OBJECT_BLOCK_PTR: - #endif /* NEW_GC */ case XD_OPAQUE_DATA_PTR: case XD_ASCII_STRING: case XD_BLOCK_PTR: --- 1302,1308 ---- *************** *** 1405,1411 **** } } } ! #else /* not MC_ALLOC */ /* Relocate a single memory block at DATA, described by DESC, from its assumed load location to its actual one by adding DELTA to all pointers in the block. Does not recursively relocate any other memory blocks --- 1405,1411 ---- } } } ! #else /* not NEW_GC */ /* Relocate a single memory block at DATA, described by DESC, from its assumed load location to its actual one by adding DELTA to all pointers in the block. Does not recursively relocate any other memory blocks *************** *** 1539,1545 **** } } } ! #endif /* not MC_ALLOC */ static void pdump_allocate_offset (pdump_block_list_elt *elt, --- 1539,1545 ---- } } } ! #endif /* not NEW_GC */ static void pdump_allocate_offset (pdump_block_list_elt *elt, *************** *** 2160,2166 **** fseek (pdump_out, header.stab_offset, SEEK_SET); ! #ifdef MC_ALLOC { EMACS_INT zero = 0; pdump_scan_lisp_objects_by_alignment (pdump_dump_mc_data); --- 2160,2166 ---- fseek (pdump_out, header.stab_offset, SEEK_SET); ! #ifdef NEW_GC { EMACS_INT zero = 0; pdump_scan_lisp_objects_by_alignment (pdump_dump_mc_data); *************** *** 2168,2184 **** pdump_scan_non_lisp_objects_by_alignment (pdump_dump_mc_data); PDUMP_WRITE_ALIGNED (EMACS_INT, zero); } ! #endif /* MC_ALLOC */ pdump_dump_cv_data_info (); pdump_dump_cv_ptr_info (); ! #ifdef MC_ALLOC pdump_dump_rtables (); ! #endif /* MC_ALLOC */ pdump_dump_root_block_ptrs (); pdump_dump_root_blocks (); ! #ifndef MC_ALLOC pdump_dump_rtables (); ! #endif /* not MC_ALLOC */ pdump_dump_root_lisp_objects (); retry_fclose (pdump_out); --- 2168,2184 ---- pdump_scan_non_lisp_objects_by_alignment (pdump_dump_mc_data); PDUMP_WRITE_ALIGNED (EMACS_INT, zero); } ! #endif /* NEW_GC */ pdump_dump_cv_data_info (); pdump_dump_cv_ptr_info (); ! #ifdef NEW_GC pdump_dump_rtables (); ! #endif /* NEW_GC */ pdump_dump_root_block_ptrs (); pdump_dump_root_blocks (); ! #ifndef NEW_GC pdump_dump_rtables (); ! #endif /* not NEW_GC */ pdump_dump_root_lisp_objects (); retry_fclose (pdump_out); *************** *** 2227,2233 **** delta = ((EMACS_INT) pdump_start) - header->reloc_address; p = pdump_start + header->stab_offset; ! #ifdef MC_ALLOC pdump_mc_hash = xnew_array_and_zero (mc_addr_elt, PDUMP_HASHSIZE); /* Allocate space for each object individually. First the --- 2227,2233 ---- delta = ((EMACS_INT) pdump_start) - header->reloc_address; p = pdump_start + header->stab_offset; ! #ifdef NEW_GC pdump_mc_hash = xnew_array_and_zero (mc_addr_elt, PDUMP_HASHSIZE); /* Allocate space for each object individually. First the *************** *** 2251,2260 **** { if (elt_count <= 1) mc_addr = (Rawbyte *) mc_alloc (real_size); - #ifdef NEW_GC else mc_addr = (Rawbyte *) mc_alloc_array (size, elt_count); - #endif /* NEW_GC */ #ifdef ALLOC_TYPE_STATS inc_lrecord_stats (real_size, (const struct lrecord_header *) --- 2251,2258 ---- *************** *** 2274,2280 **** else if (!(--count)) break; } ! #endif /* MC_ALLOC */ /* Get the cv_data array */ p = (Rawbyte *) ALIGN_PTR (p, pdump_cv_data_dump_info); --- 2272,2278 ---- else if (!(--count)) break; } ! #endif /* NEW_GC */ /* Get the cv_data array */ p = (Rawbyte *) ALIGN_PTR (p, pdump_cv_data_dump_info); *************** *** 2293,2299 **** pdump_loaded_cv_ptr[i].adr = 0; } ! #ifdef MC_ALLOC /* Relocate the heap objects */ pdump_rt_list = p; count = 2; --- 2291,2297 ---- pdump_loaded_cv_ptr[i].adr = 0; } ! #ifdef NEW_GC /* Relocate the heap objects */ pdump_rt_list = p; count = 2; *************** *** 2314,2331 **** else if (!(--count)) break; } ! #endif /* MC_ALLOC */ /* Put back the pdump_root_block_ptrs */ p = (Rawbyte *) ALIGN_PTR (p, pdump_static_pointer); for (i = 0; i < header->nb_root_block_ptrs; i++) { pdump_static_pointer ptr = PDUMP_READ (p, pdump_static_pointer); ! #ifdef MC_ALLOC (* ptr.address) = (Rawbyte *) pdump_get_mc_addr (ptr.value); ! #else /* not MC_ALLOC */ (* ptr.address) = ptr.value + delta; ! #endif /* not MC_ALLOC */ } /* Put back the pdump_root_blocks and relocate */ --- 2312,2329 ---- else if (!(--count)) break; } ! #endif /* NEW_GC */ /* Put back the pdump_root_block_ptrs */ p = (Rawbyte *) ALIGN_PTR (p, pdump_static_pointer); for (i = 0; i < header->nb_root_block_ptrs; i++) { pdump_static_pointer ptr = PDUMP_READ (p, pdump_static_pointer); ! #ifdef NEW_GC (* ptr.address) = (Rawbyte *) pdump_get_mc_addr (ptr.value); ! #else /* not NEW_GC */ (* ptr.address) = ptr.value + delta; ! #endif /* not NEW_GC */ } /* Put back the pdump_root_blocks and relocate */ *************** *** 2334,2348 **** pdump_root_block info = PDUMP_READ_ALIGNED (p, pdump_root_block); memcpy ((void *) info.blockaddr, p, info.size); if (info.desc) ! #ifdef MC_ALLOC pdump_reloc_one_mc ((void *) info.blockaddr, info.desc); ! #else /* not MC_ALLOC */ pdump_reloc_one ((void *) info.blockaddr, delta, info.desc); ! #endif /* not MC_ALLOC */ p += info.size; } ! #ifndef MC_ALLOC /* Relocate the heap objects */ pdump_rt_list = p; count = 2; --- 2332,2346 ---- pdump_root_block info = PDUMP_READ_ALIGNED (p, pdump_root_block); memcpy ((void *) info.blockaddr, p, info.size); if (info.desc) ! #ifdef NEW_GC pdump_reloc_one_mc ((void *) info.blockaddr, info.desc); ! #else /* not NEW_GC */ pdump_reloc_one ((void *) info.blockaddr, delta, info.desc); ! #endif /* not NEW_GC */ p += info.size; } ! #ifndef NEW_GC /* Relocate the heap objects */ pdump_rt_list = p; count = 2; *************** *** 2363,2369 **** else if (!(--count)) break; } ! #endif /* not MC_ALLOC */ /* Put the pdump_root_lisp_objects variables in place */ i = PDUMP_READ_ALIGNED (p, Elemcount); --- 2361,2367 ---- else if (!(--count)) break; } ! #endif /* not NEW_GC */ /* Put the pdump_root_lisp_objects variables in place */ i = PDUMP_READ_ALIGNED (p, Elemcount); *************** *** 2373,2384 **** pdump_static_Lisp_Object obj = PDUMP_READ (p, pdump_static_Lisp_Object); if (POINTER_TYPE_P (XTYPE (obj.value))) ! #ifdef MC_ALLOC obj.value = wrap_pointer_1 ((Rawbyte *) pdump_get_mc_addr (XPNTR (obj.value))); ! #else /* not MC_ALLOC */ obj.value = wrap_pointer_1 ((Rawbyte *) XPNTR (obj.value) + delta); ! #endif /* not MC_ALLOC */ (* obj.address) = obj.value; } --- 2371,2382 ---- pdump_static_Lisp_Object obj = PDUMP_READ (p, pdump_static_Lisp_Object); if (POINTER_TYPE_P (XTYPE (obj.value))) ! #ifdef NEW_GC obj.value = wrap_pointer_1 ((Rawbyte *) pdump_get_mc_addr (XPNTR (obj.value))); ! #else /* not NEW_GC */ obj.value = wrap_pointer_1 ((Rawbyte *) XPNTR (obj.value) + delta); ! #endif /* not NEW_GC */ (* obj.address) = obj.value; } *************** *** 2402,2410 **** p += sizeof (Lisp_Object) * rt.count; } ! #ifdef MC_ALLOC xfree (pdump_mc_hash, mc_addr_elt *); ! #endif /* MC_ALLOC */ #ifdef NEW_GC allow_incremental_gc = allow_inc_gc; --- 2400,2408 ---- p += sizeof (Lisp_Object) * rt.count; } ! #ifdef NEW_GC xfree (pdump_mc_hash, mc_addr_elt *); ! #endif /* NEW_GC */ #ifdef NEW_GC allow_incremental_gc = allow_inc_gc; *************** *** 2748,2756 **** { pdump_load_finish (); in_pdump = 0; ! #ifdef MC_ALLOC pdump_free (); ! #endif /* MC_ALLOC */ return 1; } --- 2746,2754 ---- { pdump_load_finish (); in_pdump = 0; ! #ifdef NEW_GC pdump_free (); ! #endif /* NEW_GC */ return 1; } *************** *** 2761,2769 **** { pdump_load_finish (); in_pdump = 0; ! #ifdef MC_ALLOC pdump_free (); ! #endif /* MC_ALLOC */ return 1; } pdump_free (); --- 2759,2767 ---- { pdump_load_finish (); in_pdump = 0; ! #ifdef NEW_GC pdump_free (); ! #endif /* NEW_GC */ return 1; } pdump_free (); diff -c 'xemacs-21.5.25/src/dumper.h' 'xemacs-21.5.26/src/dumper.h' Index: ./src/dumper.h *** ./src/dumper.h Sat Apr 9 08:11:23 2005 --- ./src/dumper.h Tue Feb 28 01:29:23 2006 *************** *** 27,35 **** BEGIN_C_DECLS ! #ifndef MC_ALLOC void pdump_objects_unmark (void); ! #endif /* not MC_ALLOC */ void pdump (void); int pdump_load (const Wexttext *argv0); void pdump_backtrace (void); --- 27,35 ---- BEGIN_C_DECLS ! #ifndef NEW_GC void pdump_objects_unmark (void); ! #endif /* not NEW_GC */ void pdump (void); int pdump_load (const Wexttext *argv0); void pdump_backtrace (void); diff -c 'xemacs-21.5.25/src/dynarr.c' 'xemacs-21.5.26/src/dynarr.c' Index: ./src/dynarr.c *** ./src/dynarr.c Sat Jan 21 02:59:50 2006 --- ./src/dynarr.c Tue Mar 21 06:20:28 2006 *************** *** 133,139 **** { if (DUMPEDP (dy->base)) { ! void *new_base = malloc (new_size); memcpy (new_base, dy->base, (dy->max < new_size ? dy->max : new_size) * dy->elsize); dy->base = new_base; --- 133,139 ---- { if (DUMPEDP (dy->base)) { ! void *new_base = malloc (new_size * dy->elsize); memcpy (new_base, dy->base, (dy->max < new_size ? dy->max : new_size) * dy->elsize); dy->base = new_base; diff -c 'xemacs-21.5.25/src/elhash.c' 'xemacs-21.5.26/src/elhash.c' Index: ./src/elhash.c *** ./src/elhash.c Fri Nov 25 10:42:00 2005 --- ./src/elhash.c Tue Feb 28 01:29:23 2006 *************** *** 417,425 **** #endif #ifdef ERROR_CHECK_STRUCTURES size_t size ! #else size_t UNUSED (size) ! #endif ) { #ifdef NEW_GC --- 417,425 ---- #endif #ifdef ERROR_CHECK_STRUCTURES size_t size ! #else /* not (NEW_GC && ! ERROR_CHECK_STRUCTURES) */ size_t UNUSED (size) ! #endif /* not (NEW_GC && ! ERROR_CHECK_STRUCTURES) */ ) { #ifdef NEW_GC *************** *** 443,448 **** --- 443,449 ---- #endif /* not NEW_GC */ } + #ifndef NEW_GC static void finalize_hash_table (void *header, int for_disksave) { *************** *** 453,458 **** --- 454,460 ---- ht->hentries = 0; } } + #endif /* not NEW_GC */ static const struct memory_description htentry_description_1[] = { { XD_LISP_OBJECT, offsetof (htentry, key) }, *************** *** 515,520 **** --- 517,530 ---- { XD_END } }; + #ifdef NEW_GC + DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table, + 1, /*dumpable-flag*/ + mark_hash_table, print_hash_table, + 0, hash_table_equal, hash_table_hash, + hash_table_description, + Lisp_Hash_Table); + #else /* not NEW_GC */ DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table, 1, /*dumpable-flag*/ mark_hash_table, print_hash_table, *************** *** 522,527 **** --- 532,538 ---- hash_table_equal, hash_table_hash, hash_table_description, Lisp_Hash_Table); + #endif /* not NEW_GC */ static Lisp_Hash_Table * xhash_table (Lisp_Object hash_table) diff -c 'xemacs-21.5.25/src/emacs.c' 'xemacs-21.5.26/src/emacs.c' Index: ./src/emacs.c *** ./src/emacs.c Wed Dec 28 03:51:29 2005 --- ./src/emacs.c Tue Feb 28 01:29:23 2006 *************** *** 914,920 **** display_use = 0; inhibit_non_essential_conversion_operations = 1; ! #ifdef MC_ALLOC #ifndef PDUMP if (!initialized) #endif --- 914,920 ---- display_use = 0; inhibit_non_essential_conversion_operations = 1; ! #ifdef NEW_GC #ifndef PDUMP if (!initialized) #endif *************** *** 927,933 **** #endif /* ALLOC_TYPE_STATS */ } } ! #endif /* MC_ALLOC */ #ifdef NeXT /* 19-Jun-1995 -baw --- 927,933 ---- #endif /* ALLOC_TYPE_STATS */ } } ! #endif /* NEW_GC */ #ifdef NeXT /* 19-Jun-1995 -baw *************** *** 1320,1326 **** init_signals_very_early (); #ifdef NEW_GC vdb_install_signal_handler (); ! #endif init_data_very_early (); /* Catch math errors. */ init_floatfns_very_early (); /* Catch floating-point math errors. */ init_process_times_very_early (); /* Initialize our process timers. --- 1320,1326 ---- init_signals_very_early (); #ifdef NEW_GC vdb_install_signal_handler (); ! #endif /* NEW_GC */ init_data_very_early (); /* Catch math errors. */ init_floatfns_very_early (); /* Catch floating-point math errors. */ init_process_times_very_early (); /* Initialize our process timers. *************** *** 1454,1462 **** syms_of_abbrev (); syms_of_alloc (); ! #ifdef MC_ALLOC syms_of_mc_alloc (); ! #endif /* MC_ALLOC */ syms_of_gc (); #ifdef NEW_GC syms_of_vdb (); --- 1454,1462 ---- syms_of_abbrev (); syms_of_alloc (); ! #ifdef NEW_GC syms_of_mc_alloc (); ! #endif /* NEW_GC */ syms_of_gc (); #ifdef NEW_GC syms_of_vdb (); *************** *** 1874,1882 **** reinit_alloc_early (); reinit_gc_early (); reinit_symbols_early (); ! #ifndef MC_ALLOC reinit_opaque_early (); ! #endif /* not MC_ALLOC */ reinit_eistring_early (); reinit_console_type_create_stream (); --- 1874,1882 ---- reinit_alloc_early (); reinit_gc_early (); reinit_symbols_early (); ! #ifndef NEW_GC reinit_opaque_early (); ! #endif /* not NEW_GC */ reinit_eistring_early (); reinit_console_type_create_stream (); *************** *** 2296,2304 **** reinit_vars_of_glyphs_widget (); reinit_vars_of_insdel (); reinit_vars_of_lread (); ! #ifndef MC_ALLOC reinit_vars_of_lstream (); ! #endif /* not MC_ALLOC */ reinit_vars_of_minibuf (); #ifdef HAVE_SHLIB reinit_vars_of_module (); --- 2296,2304 ---- reinit_vars_of_glyphs_widget (); reinit_vars_of_insdel (); reinit_vars_of_lread (); ! #ifndef NEW_GC reinit_vars_of_lstream (); ! #endif /* not NEW_GC */ reinit_vars_of_minibuf (); #ifdef HAVE_SHLIB reinit_vars_of_module (); *************** *** 3239,3247 **** fflush (stdout); disksave_object_finalization (); ! #ifndef MC_ALLOC release_breathing_space (); ! #endif /* not MC_ALLOC */ /* Tell malloc where start of impure now is */ /* Also arrange for warnings when nearly out of space. */ --- 3239,3247 ---- fflush (stdout); disksave_object_finalization (); ! #ifndef NEW_GC release_breathing_space (); ! #endif /* not NEW_GC */ /* Tell malloc where start of impure now is */ /* Also arrange for warnings when nearly out of space. */ diff -c 'xemacs-21.5.25/src/eval.c' 'xemacs-21.5.26/src/eval.c' Index: ./src/eval.c *** ./src/eval.c Fri Nov 25 10:42:00 2005 --- ./src/eval.c Tue Feb 28 01:29:24 2006 *************** *** 3835,3840 **** --- 3835,3843 ---- { need_to_signal_post_gc = 0; recompute_funcall_allocation_flag (); + #ifdef NEW_GC + run_finalizers (); + #endif /* NEW_GC */ run_post_gc_hook (); } } diff -c 'xemacs-21.5.25/src/event-msw.c' 'xemacs-21.5.26/src/event-msw.c' Index: ./src/event-msw.c *** ./src/event-msw.c Fri Nov 25 10:42:01 2005 --- ./src/event-msw.c Tue Feb 28 01:29:24 2006 *************** *** 2502,2508 **** /* If you hit this, rewrite the offending API call to occur after GC, using register_post_gc_action(). */ assert (!gc_in_progress); ! #endif /* NEW_GC */ #ifdef DEBUG_XEMACS if (debug_mswindows_events) --- 2502,2508 ---- /* If you hit this, rewrite the offending API call to occur after GC, using register_post_gc_action(). */ assert (!gc_in_progress); ! #endif /* not NEW_GC */ #ifdef DEBUG_XEMACS if (debug_mswindows_events) diff -c 'xemacs-21.5.25/src/event-stream.c' 'xemacs-21.5.26/src/event-stream.c' Index: ./src/event-stream.c *** ./src/event-stream.c Tue Oct 25 20:16:23 2005 --- ./src/event-stream.c Tue Feb 28 01:29:24 2006 *************** *** 329,337 **** #define CHECK_COMMAND_BUILDER(x) CHECK_RECORD (x, command_builder) #define CONCHECK_COMMAND_BUILDER(x) CONCHECK_RECORD (x, command_builder) ! #ifndef MC_ALLOC static Lisp_Object Vcommand_builder_free_list; ! #endif /* not MC_ALLOC */ static const struct memory_description command_builder_description [] = { { XD_LISP_OBJECT, offsetof (struct command_builder, current_events) }, --- 329,337 ---- #define CHECK_COMMAND_BUILDER(x) CHECK_RECORD (x, command_builder) #define CONCHECK_COMMAND_BUILDER(x) CONCHECK_RECORD (x, command_builder) ! #ifndef NEW_GC static Lisp_Object Vcommand_builder_free_list; ! #endif /* not NEW_GC */ static const struct memory_description command_builder_description [] = { { XD_LISP_OBJECT, offsetof (struct command_builder, current_events) }, *************** *** 389,400 **** allocate_command_builder (Lisp_Object console, int with_echo_buf) { Lisp_Object builder_obj = ! #ifdef MC_ALLOC wrap_pointer_1 (alloc_lrecord_type (struct command_builder, &lrecord_command_builder)); ! #else /* not MC_ALLOC */ alloc_managed_lcrecord (Vcommand_builder_free_list); ! #endif /* not MC_ALLOC */ struct command_builder *builder = XCOMMAND_BUILDER (builder_obj); builder->console = console; --- 389,400 ---- allocate_command_builder (Lisp_Object console, int with_echo_buf) { Lisp_Object builder_obj = ! #ifdef NEW_GC wrap_pointer_1 (alloc_lrecord_type (struct command_builder, &lrecord_command_builder)); ! #else /* not NEW_GC */ alloc_managed_lcrecord (Vcommand_builder_free_list); ! #endif /* not NEW_GC */ struct command_builder *builder = XCOMMAND_BUILDER (builder_obj); builder->console = console; *************** *** 463,474 **** xfree (builder->echo_buf, Ibyte *); builder->echo_buf = NULL; } ! #ifdef MC_ALLOC free_lrecord (wrap_command_builder (builder)); ! #else /* not MC_ALLOC */ free_managed_lcrecord (Vcommand_builder_free_list, wrap_command_builder (builder)); ! #endif /* not MC_ALLOC */ } static void --- 463,474 ---- xfree (builder->echo_buf, Ibyte *); builder->echo_buf = NULL; } ! #ifdef NEW_GC free_lrecord (wrap_command_builder (builder)); ! #else /* not NEW_GC */ free_managed_lcrecord (Vcommand_builder_free_list, wrap_command_builder (builder)); ! #endif /* not NEW_GC */ } static void *************** *** 1031,1039 **** static Lisp_Object pending_timeout_list, pending_async_timeout_list; ! #ifndef MC_ALLOC static Lisp_Object Vtimeout_free_list; ! #endif /* not MC_ALLOC */ static Lisp_Object mark_timeout (Lisp_Object obj) --- 1031,1039 ---- static Lisp_Object pending_timeout_list, pending_async_timeout_list; ! #ifndef NEW_GC static Lisp_Object Vtimeout_free_list; ! #endif /* not NEW_GC */ static Lisp_Object mark_timeout (Lisp_Object obj) *************** *** 1062,1073 **** Lisp_Object function, Lisp_Object object, int async_p) { ! #ifdef MC_ALLOC Lisp_Object op = wrap_pointer_1 (alloc_lrecord_type (Lisp_Timeout, &lrecord_timeout)); ! #else /* not MC_ALLOC */ Lisp_Object op = alloc_managed_lcrecord (Vtimeout_free_list); ! #endif /* not MC_ALLOC */ Lisp_Timeout *timeout = XTIMEOUT (op); EMACS_TIME current_time; EMACS_TIME interval; --- 1062,1073 ---- Lisp_Object function, Lisp_Object object, int async_p) { ! #ifdef NEW_GC Lisp_Object op = wrap_pointer_1 (alloc_lrecord_type (Lisp_Timeout, &lrecord_timeout)); ! #else /* not NEW_GC */ Lisp_Object op = alloc_managed_lcrecord (Vtimeout_free_list); ! #endif /* not NEW_GC */ Lisp_Timeout *timeout = XTIMEOUT (op); EMACS_TIME current_time; EMACS_TIME interval; *************** *** 1185,1195 **** *timeout_list = noseeum_cons (op, *timeout_list); } else ! #ifdef MC_ALLOC free_lrecord (op); ! #else /* not MC_ALLOC */ free_managed_lcrecord (Vtimeout_free_list, op); ! #endif /* not MC_ALLOC */ UNGCPRO; return id; --- 1185,1195 ---- *timeout_list = noseeum_cons (op, *timeout_list); } else ! #ifdef NEW_GC free_lrecord (op); ! #else /* not NEW_GC */ free_managed_lcrecord (Vtimeout_free_list, op); ! #endif /* not NEW_GC */ UNGCPRO; return id; *************** *** 1226,1236 **** signal_remove_async_interval_timeout (timeout->interval_id); else event_stream_remove_timeout (timeout->interval_id); ! #ifdef MC_ALLOC free_lrecord (op); ! #else /* not MC_ALLOC */ free_managed_lcrecord (Vtimeout_free_list, op); ! #endif /* not MC_ALLOC */ } } --- 1226,1236 ---- signal_remove_async_interval_timeout (timeout->interval_id); else event_stream_remove_timeout (timeout->interval_id); ! #ifdef NEW_GC free_lrecord (op); ! #else /* not NEW_GC */ free_managed_lcrecord (Vtimeout_free_list, op); ! #endif /* not NEW_GC */ } } *************** *** 4925,4931 **** recent_keys_ring_index = 0; recent_keys_ring_size = 100; num_input_chars = 0; ! #ifndef MC_ALLOC Vtimeout_free_list = make_lcrecord_list (sizeof (Lisp_Timeout), &lrecord_timeout); staticpro_nodump (&Vtimeout_free_list); --- 4925,4931 ---- recent_keys_ring_index = 0; recent_keys_ring_size = 100; num_input_chars = 0; ! #ifndef NEW_GC Vtimeout_free_list = make_lcrecord_list (sizeof (Lisp_Timeout), &lrecord_timeout); staticpro_nodump (&Vtimeout_free_list); *************** *** 4933,4939 **** make_lcrecord_list (sizeof (struct command_builder), &lrecord_command_builder); staticpro_nodump (&Vcommand_builder_free_list); ! #endif /* not MC_ALLOC */ the_low_level_timeout_blocktype = Blocktype_new (struct low_level_timeout_blocktype); something_happened = 0; --- 4933,4939 ---- make_lcrecord_list (sizeof (struct command_builder), &lrecord_command_builder); staticpro_nodump (&Vcommand_builder_free_list); ! #endif /* not NEW_GC */ the_low_level_timeout_blocktype = Blocktype_new (struct low_level_timeout_blocktype); something_happened = 0; diff -c 'xemacs-21.5.25/src/extents.c' 'xemacs-21.5.26/src/extents.c' Index: ./src/extents.c *** ./src/extents.c Tue Feb 21 20:33:45 2006 --- ./src/extents.c Tue Feb 28 01:29:25 2006 *************** *** 1269,1274 **** --- 1269,1282 ---- return Qnil; } + #ifdef NEW_GC + DEFINE_LRECORD_IMPLEMENTATION ("extent-info", extent_info, + 0, /*dumpable-flag*/ + mark_extent_info, internal_object_printer, + 0, 0, 0, + extent_info_description, + struct extent_info); + #else /* not NEW_GC */ static void finalize_extent_info (void *header, int for_disksave) { *************** *** 1277,1286 **** if (for_disksave) return; - #ifdef NEW_GC data->soe = 0; data->extents = 0; - #else /* not NEW_GC */ if (data->soe) { free_soe (data->soe); --- 1285,1292 ---- *************** *** 1291,1297 **** free_extent_list (data->extents); data->extents = 0; } - #endif /* not NEW_GC */ } DEFINE_LRECORD_IMPLEMENTATION ("extent-info", extent_info, --- 1297,1302 ---- *************** *** 1300,1305 **** --- 1305,1311 ---- finalize_extent_info, 0, 0, extent_info_description, struct extent_info); + #endif /* not NEW_GC */ static Lisp_Object allocate_extent_info (void) *************** *** 7458,7464 **** INIT_LRECORD_IMPLEMENTATION (extent_list_marker); INIT_LRECORD_IMPLEMENTATION (extent_list); INIT_LRECORD_IMPLEMENTATION (stack_of_extents); ! #endif /* not NEW_GC */ DEFSYMBOL (Qextentp); DEFSYMBOL (Qextent_live_p); --- 7464,7470 ---- INIT_LRECORD_IMPLEMENTATION (extent_list_marker); INIT_LRECORD_IMPLEMENTATION (extent_list); INIT_LRECORD_IMPLEMENTATION (stack_of_extents); ! #endif /* NEW_GC */ DEFSYMBOL (Qextentp); DEFSYMBOL (Qextent_live_p); diff -c 'xemacs-21.5.25/src/faces.h' 'xemacs-21.5.26/src/faces.h' Index: ./src/faces.h *** ./src/faces.h Sat Nov 26 20:46:08 2005 --- ./src/faces.h Tue Feb 28 01:29:25 2006 *************** *** 119,125 **** { #ifdef NEW_GC struct lrecord_header header; ! #endif /* not NEW_GC */ /* There are two kinds of cachels; those created from a single face and those created by merging more than one face. In the former case, the FACE element specifies the face used. In the latter --- 119,125 ---- { #ifdef NEW_GC struct lrecord_header header; ! #endif /* NEW_GC */ /* There are two kinds of cachels; those created from a single face and those created by merging more than one face. In the former case, the FACE element specifies the face used. In the latter diff -c 'xemacs-21.5.25/src/file-coding.c' 'xemacs-21.5.26/src/file-coding.c' Index: ./src/file-coding.c *** ./src/file-coding.c Sun Dec 18 04:47:03 2005 --- ./src/file-coding.c Sun Mar 26 22:05:17 2006 *************** *** 305,310 **** --- 305,311 ---- write_c_string (printcharfun, "]"); } + #ifndef NEW_GC static void finalize_coding_system (void *header, int for_disksave) { *************** *** 315,320 **** --- 316,322 ---- if (!for_disksave) /* see comment in lstream.c */ MAYBE_XCODESYSMETH (cs, finalize, (cs)); } + #endif /* not NEW_GC */ static Bytecount sizeof_coding_system (const void *header) *************** *** 366,371 **** --- 368,382 ---- 0, coding_system_empty_extra_description_1 }; + #ifdef NEW_GC + DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("coding-system", coding_system, + 1, /*dumpable-flag*/ + mark_coding_system, + print_coding_system, + 0, 0, 0, coding_system_description, + sizeof_coding_system, + Lisp_Coding_System); + #else /* not NEW_GC */ DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("coding-system", coding_system, 1, /*dumpable-flag*/ mark_coding_system, *************** *** 374,379 **** --- 385,391 ---- 0, 0, coding_system_description, sizeof_coding_system, Lisp_Coding_System); + #endif /* not NEW_GC */ /************************************************************************/ /* Creating coding systems */ *************** *** 2276,2288 **** } } ! DEFUN ("decode-coding-region", Fdecode_coding_region, 3, 4, 0, /* Decode the text between START and END which is encoded in CODING-SYSTEM. This is useful if you've read in encoded text from a file without decoding it (e.g. you read in a JIS-formatted file but used the `binary' or `no-conversion' coding system, so that it shows up as "^[$B!basic_p || \ ! ((struct old_lcrecord_header *) lheader)->free) ! #endif /* MC_ALLOC */ #ifdef USE_KKCC /* The following functions implement the new mark algorithm. --- 580,594 ---- } #endif /* defined (USE_KKCC) || defined (PDUMP) */ ! #ifdef NEW_GC #define GC_CHECK_NOT_FREE(lheader) \ gc_checking_assert (! LRECORD_FREE_P (lheader)); ! #else /* not NEW_GC */ #define GC_CHECK_NOT_FREE(lheader) \ gc_checking_assert (! LRECORD_FREE_P (lheader)); \ gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || \ ! ((struct old_lcrecord_header *) lheader)->free) ! #endif /* not NEW_GC */ #ifdef USE_KKCC /* The following functions implement the new mark algorithm. *************** *** 1147,1159 **** though. */ if (EQ (*stored_obj, Qnull_pointer)) break; ! #ifdef MC_ALLOC mark_object_maybe_checking_free (*stored_obj, 0, level, pos); ! #else /* not MC_ALLOC */ mark_object_maybe_checking_free (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT, level, pos); ! #endif /* not MC_ALLOC */ break; } case XD_LISP_OBJECT_ARRAY: --- 1095,1107 ---- though. */ if (EQ (*stored_obj, Qnull_pointer)) break; ! #ifdef NEW_GC mark_object_maybe_checking_free (*stored_obj, 0, level, pos); ! #else /* not NEW_GC */ mark_object_maybe_checking_free (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT, level, pos); ! #endif /* not NEW_GC */ break; } case XD_LISP_OBJECT_ARRAY: *************** *** 1169,1182 **** if (EQ (*stored_obj, Qnull_pointer)) break; ! #ifdef MC_ALLOC mark_object_maybe_checking_free (*stored_obj, 0, level, pos); ! #else /* not MC_ALLOC */ mark_object_maybe_checking_free (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT, level, pos); ! #endif /* not MC_ALLOC */ } break; } --- 1117,1130 ---- if (EQ (*stored_obj, Qnull_pointer)) break; ! #ifdef NEW_GC mark_object_maybe_checking_free (*stored_obj, 0, level, pos); ! #else /* not NEW_GC */ mark_object_maybe_checking_free (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT, level, pos); ! #endif /* not NEW_GC */ } break; } *************** *** 1392,1397 **** --- 1340,1415 ---- } } + #ifdef NEW_GC + /* Asynchronous finalization. */ + typedef struct finalize_elem + { + Lisp_Object obj; + struct finalize_elem *next; + } finalize_elem; + + finalize_elem *Vall_finalizable_objs; + Lisp_Object Vfinalizers_to_run; + + void + add_finalizable_obj (Lisp_Object obj) + { + finalize_elem *next = Vall_finalizable_objs; + Vall_finalizable_objs = + (finalize_elem *) xmalloc_and_zero (sizeof (finalize_elem)); + Vall_finalizable_objs->obj = obj; + Vall_finalizable_objs->next = next; + } + + void + register_for_finalization (void) + { + finalize_elem *rest = Vall_finalizable_objs; + + if (!rest) + return; + + while (!marked_p (rest->obj)) + { + finalize_elem *temp = rest; + Vfinalizers_to_run = Fcons (rest->obj, Vfinalizers_to_run); + Vall_finalizable_objs = rest->next; + xfree (temp, finalize_elem *); + rest = Vall_finalizable_objs; + } + + while (rest->next) + { + if (LRECORDP (rest->next->obj) + && !marked_p (rest->next->obj)) + { + finalize_elem *temp = rest->next; + Vfinalizers_to_run = Fcons (rest->next->obj, Vfinalizers_to_run); + rest->next = rest->next->next; + xfree (temp, finalize_elem *); + } + else + { + rest = rest->next; + } + } + /* Keep objects alive that need to be finalized by marking + Vfinalizers_to_run transitively. */ + kkcc_gc_stack_push_lisp_object (Vfinalizers_to_run, 0, -1); + kkcc_marking (0); + } + + void + run_finalizers (void) + { + Lisp_Object rest; + for (rest = Vfinalizers_to_run; !NILP (rest); rest = XCDR (rest)) + { + MC_ALLOC_CALL_FINALIZER (XPNTR (XCAR (rest))); + } + Vfinalizers_to_run = Qnil; + } + #endif /* not NEW_GC */ /************************************************************************/ *************** *** 1429,1452 **** #endif void ! gc_prepare (void) { ! #if MAX_SAVE_STACK > 0 ! char stack_top_variable; ! extern char *stack_bottom; ! #endif ! ! #ifdef NEW_GC ! GC_STAT_START_NEW_GC; ! GC_SET_PHASE (INIT_GC); ! #endif /* NEW_GC */ ! ! do_backtrace = profiling_active || backtrace_with_internal_sections; ! ! assert (!gc_in_progress); ! assert (!in_display || gc_currently_forbidden); ! ! PROFILE_RECORD_ENTERING_SECTION (QSin_garbage_collection); /* We used to call selected_frame() here. --- 1447,1457 ---- #endif void ! show_gc_cursor_and_message (void) { ! /* Now show the GC cursor/message. */ ! pre_gc_cursor = Qnil; ! cursor_changed = 0; /* We used to call selected_frame() here. *************** *** 1463,1480 **** f = XFRAME (frame); } - pre_gc_cursor = Qnil; - cursor_changed = 0; - - need_to_signal_post_gc = 0; - recompute_funcall_allocation_flag (); - - if (!gc_hooks_inhibited) - run_hook_trapping_problems - (Qgarbage_collecting, Qpre_gc_hook, - INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); - - /* Now show the GC cursor/message. */ if (!noninteractive) { if (FRAME_WIN_P (f)) --- 1468,1473 ---- *************** *** 1508,1520 **** } } } /***** Now we actually start the garbage collection. */ gc_in_progress = 1; #ifndef NEW_GC inhibit_non_essential_conversion_operations = 1; ! #endif /* NEW_GC */ #if MAX_SAVE_STACK > 0 --- 1501,1572 ---- } } } + } + + void + remove_gc_cursor_and_message (void) + { + /* Now remove the GC cursor/message */ + if (!noninteractive) + { + if (cursor_changed) + Fset_frame_pointer (wrap_frame (f), pre_gc_cursor); + else if (!FRAME_STREAM_P (f)) + { + /* Show "...done" only if the echo area would otherwise be empty. */ + if (NILP (clear_echo_area (selected_frame (), + Qgarbage_collecting, 0))) + { + if (garbage_collection_messages) + { + Lisp_Object args[2], whole_msg; + args[0] = (STRINGP (Vgc_message) ? Vgc_message : + build_msg_string (gc_default_message)); + args[1] = build_msg_string ("... done"); + whole_msg = Fconcat (2, args); + echo_area_message (selected_frame (), (Ibyte *) 0, + whole_msg, 0, -1, + Qgarbage_collecting); + } + } + } + } + } + + void + gc_prepare (void) + { + #if MAX_SAVE_STACK > 0 + char stack_top_variable; + extern char *stack_bottom; + #endif + + #ifdef NEW_GC + GC_STAT_START_NEW_GC; + GC_SET_PHASE (INIT_GC); + #endif /* NEW_GC */ + + do_backtrace = profiling_active || backtrace_with_internal_sections; + + assert (!gc_in_progress); + assert (!in_display || gc_currently_forbidden); + + PROFILE_RECORD_ENTERING_SECTION (QSin_garbage_collection); + + need_to_signal_post_gc = 0; + recompute_funcall_allocation_flag (); + + if (!gc_hooks_inhibited) + run_hook_trapping_problems + (Qgarbage_collecting, Qpre_gc_hook, + INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); /***** Now we actually start the garbage collection. */ gc_in_progress = 1; #ifndef NEW_GC inhibit_non_essential_conversion_operations = 1; ! #endif /* not NEW_GC */ #if MAX_SAVE_STACK > 0 *************** *** 1596,1609 **** **p++; } ! #ifdef MC_ALLOC { /* mcpro () */ Lisp_Object *p = Dynarr_begin (mcpros); Elemcount count; for (count = Dynarr_length (mcpros); count; count--) mark_object (*p++); } ! #endif /* MC_ALLOC */ { /* GCPRO() */ struct gcpro *tail; --- 1648,1661 ---- **p++; } ! #ifdef NEW_GC { /* mcpro () */ Lisp_Object *p = Dynarr_begin (mcpros); Elemcount count; for (count = Dynarr_length (mcpros); count; count--) mark_object (*p++); } ! #endif /* NEW_GC */ { /* GCPRO() */ struct gcpro *tail; *************** *** 1708,1714 **** gc_finalize (void) { GC_SET_PHASE (FINALIZE); ! mc_finalize (); } void --- 1760,1766 ---- gc_finalize (void) { GC_SET_PHASE (FINALIZE); ! register_for_finalization (); } void *************** *** 1743,1780 **** /******* End of garbage collection ********/ ! /* Now remove the GC cursor/message */ ! if (!noninteractive) ! { ! if (cursor_changed) ! Fset_frame_pointer (wrap_frame (f), pre_gc_cursor); ! else if (!FRAME_STREAM_P (f)) ! { ! /* Show "...done" only if the echo area would otherwise be empty. */ ! if (NILP (clear_echo_area (selected_frame (), ! Qgarbage_collecting, 0))) ! { ! if (garbage_collection_messages) ! { ! Lisp_Object args[2], whole_msg; ! args[0] = (STRINGP (Vgc_message) ? Vgc_message : ! build_msg_string (gc_default_message)); ! args[1] = build_msg_string ("... done"); ! whole_msg = Fconcat (2, args); ! echo_area_message (selected_frame (), (Ibyte *) 0, ! whole_msg, 0, -1, ! Qgarbage_collecting); ! } ! } ! } ! } ! ! #ifndef MC_ALLOC if (!breathing_space) { breathing_space = malloc (4096 - MALLOC_OVERHEAD); } ! #endif /* not MC_ALLOC */ need_to_signal_post_gc = 1; funcall_allocation_flag = 1; --- 1795,1806 ---- /******* End of garbage collection ********/ ! #ifndef NEW_GC if (!breathing_space) { breathing_space = malloc (4096 - MALLOC_OVERHEAD); } ! #endif /* not NEW_GC */ need_to_signal_post_gc = 1; funcall_allocation_flag = 1; *************** *** 1887,1898 **** if (!gc_resume_mark (incremental)) return; /* suspend gc */ gc_finish_mark (); kkcc_gc_stack_free (); #ifdef DEBUG_XEMACS kkcc_bt_free (); #endif - case FINISH_MARK: - gc_finalize (); case FINALIZE: gc_sweep (); case SWEEP: --- 1913,1924 ---- if (!gc_resume_mark (incremental)) return; /* suspend gc */ gc_finish_mark (); + case FINISH_MARK: + gc_finalize (); kkcc_gc_stack_free (); #ifdef DEBUG_XEMACS kkcc_bt_free (); #endif case FINALIZE: gc_sweep (); case SWEEP: *************** *** 1914,1921 **** --- 1940,1951 ---- have infinite GC recursion. */ speccount = begin_gc_forbidden (); + show_gc_cursor_and_message (); + gc_1 (incremental); + remove_gc_cursor_and_message (); + /* now stop inhibiting GC */ unbind_to (speccount); } *************** *** 1975,1980 **** --- 2005,2012 ---- have infinite GC recursion. */ speccount = begin_gc_forbidden (); + show_gc_cursor_and_message (); + gc_prepare (); #ifdef USE_KKCC kkcc_gc_stack_init(); *************** *** 1996,2001 **** --- 2028,2035 ---- gc_sweep_1 (); gc_finish (); + remove_gc_cursor_and_message (); + /* now stop inhibiting GC */ unbind_to (speccount); } *************** *** 2023,2034 **** #ifdef NEW_GC gc_cons_incremental_threshold = GC_CONS_INCREMENTAL_THRESHOLD; gc_incremental_traversal_threshold = GC_INCREMENTAL_TRAVERSAL_THRESHOLD; ! #endif /* not NEW_GC */ } void init_gc_early (void) { } void --- 2057,2072 ---- #ifdef NEW_GC gc_cons_incremental_threshold = GC_CONS_INCREMENTAL_THRESHOLD; gc_incremental_traversal_threshold = GC_INCREMENTAL_TRAVERSAL_THRESHOLD; ! #endif /* NEW_GC */ } void init_gc_early (void) { + #ifdef NEW_GC + /* Reset the finalizers_to_run list after pdump_load. */ + Vfinalizers_to_run = Qnil; + #endif /* NEW_GC */ } void *************** *** 2174,2179 **** --- 2212,2220 ---- *incremental garbage collection, the garbage collector then only does *full collects (even if (gc-incremental) is called). */ ); + + Vfinalizers_to_run = Qnil; + staticpro_nodump (&Vfinalizers_to_run); #endif /* NEW_GC */ } diff -c 'xemacs-21.5.25/src/gc.h' 'xemacs-21.5.26/src/gc.h' Index: ./src/gc.h *** ./src/gc.h Fri Nov 25 10:42:04 2005 --- ./src/gc.h Wed Mar 29 02:43:54 2006 *************** *** 34,50 **** void gc_stat_print_stats (void); void gc_stat_finalized (void); void gc_stat_freed (void); - void gc_stat_explicitly_freed (void); - void gc_stat_explicitly_tried_freed (void); # define GC_STAT_FINALIZED gc_stat_finalized () # define GC_STAT_FREED gc_stat_freed () - # define GC_STAT_EXPLICITLY_FREED gc_stat_explicitly_freed () - # define GC_STAT_EXPLICITLY_TRIED_FREED gc_stat_explicitly_tried_freed () #else /* not ERROR_CHECK_GC */ # define GC_STAT_FINALIZED # define GC_STAT_FREED - # define GC_STAT_EXPLICITLY_FREED - # define GC_STAT_EXPLICITLY_TRIED_FREED #endif /* not ERROR_CHECK_GC */ #endif /* not NEW_GC */ --- 34,44 ---- *************** *** 169,178 **** alloc.c to gc.c. */ void gc_sweep_1 (void); - #ifndef MC_ALLOC extern void *breathing_space; - #endif /* not MC_ALLOC */ #endif /* not NEW_GC */ END_C_DECLS --- 163,176 ---- alloc.c to gc.c. */ void gc_sweep_1 (void); extern void *breathing_space; #endif /* not NEW_GC */ + + #ifdef NEW_GC + void add_finalizable_obj (Lisp_Object obj); + void register_for_finalization (void); + void run_finalizers (void); + #endif /* NEW_GC */ END_C_DECLS diff -c 'xemacs-21.5.25/src/glyphs.h' 'xemacs-21.5.26/src/glyphs.h' Index: ./src/glyphs.h *** ./src/glyphs.h Fri Nov 25 10:42:04 2005 --- ./src/glyphs.h Tue Feb 28 01:29:26 2006 *************** *** 1069,1075 **** { #ifdef NEW_GC struct lrecord_header header; ! #endif /* not NEW_GC */ Lisp_Object glyph; unsigned int dirty :1; /* I'm copying faces here. I'm not --- 1069,1075 ---- { #ifdef NEW_GC struct lrecord_header header; ! #endif /* NEW_GC */ Lisp_Object glyph; unsigned int dirty :1; /* I'm copying faces here. I'm not diff -c 'xemacs-21.5.25/src/gui.c' 'xemacs-21.5.26/src/gui.c' Index: ./src/gui.c *** ./src/gui.c Mon Oct 24 19:07:37 2005 --- ./src/gui.c Tue Feb 28 01:29:26 2006 *************** *** 804,818 **** RETURN_UNGCPRO (ret); } - static void - finalize_gui_item (void *UNUSED (header), int UNUSED (for_disksave)) - { - } - DEFINE_LRECORD_IMPLEMENTATION ("gui-item", gui_item, 0, /*dumpable-flag*/ mark_gui_item, print_gui_item, ! finalize_gui_item, gui_item_equal, gui_item_hash, gui_item_description, Lisp_Gui_Item); --- 804,813 ---- RETURN_UNGCPRO (ret); } DEFINE_LRECORD_IMPLEMENTATION ("gui-item", gui_item, 0, /*dumpable-flag*/ mark_gui_item, print_gui_item, ! 0, gui_item_equal, gui_item_hash, gui_item_description, Lisp_Gui_Item); diff -c 'xemacs-21.5.25/src/lisp.h' 'xemacs-21.5.26/src/lisp.h' Index: ./src/lisp.h *** ./src/lisp.h Tue Feb 21 20:33:46 2006 --- ./src/lisp.h Fri Mar 31 08:10:38 2006 *************** *** 1251,1388 **** } \ } while (0) - /* ------------------------ dynamic arrays ------------------- */ - - #ifndef NEW_GC - #ifdef ERROR_CHECK_STRUCTURES - #define Dynarr_declare(type) \ - type *base; \ - int locked; \ - int elsize; \ - int cur; \ - int largest; \ - int max - #else - #define Dynarr_declare(type) \ - type *base; \ - int elsize; \ - int cur; \ - int largest; \ - int max - #endif /* ERROR_CHECK_STRUCTURES */ - - typedef struct dynarr - { - Dynarr_declare (void); - } Dynarr; - - MODULE_API void *Dynarr_newf (int elsize); - MODULE_API void Dynarr_resize (void *dy, Elemcount size); - MODULE_API void Dynarr_insert_many (void *d, const void *el, int len, int start); - MODULE_API void Dynarr_delete_many (void *d, int start, int len); - MODULE_API void Dynarr_free (void *d); - - #define Dynarr_new(type) ((type##_dynarr *) Dynarr_newf (sizeof (type))) - #define Dynarr_new2(dynarr_type, type) \ - ((dynarr_type *) Dynarr_newf (sizeof (type))) - #define Dynarr_at(d, pos) ((d)->base[pos]) - #define Dynarr_atp(d, pos) (&Dynarr_at (d, pos)) - #define Dynarr_begin(d) Dynarr_atp (d, 0) - #define Dynarr_end(d) Dynarr_atp (d, Dynarr_length (d) - 1) - #define Dynarr_sizeof(d) ((d)->cur * (d)->elsize) - - #ifdef ERROR_CHECK_STRUCTURES - DECLARE_INLINE_HEADER ( - Dynarr * - Dynarr_verify_1 (void *d, const Ascbyte *file, int line) - ) - { - Dynarr *dy = (Dynarr *) d; - assert_at_line (dy->cur >= 0 && dy->cur <= dy->largest && - dy->largest <= dy->max, file, line); - return dy; - } - - DECLARE_INLINE_HEADER ( - Dynarr * - Dynarr_verify_mod_1 (void *d, const Ascbyte *file, int line) - ) - { - Dynarr *dy = (Dynarr *) d; - assert_at_line (!dy->locked, file, line); - assert_at_line (dy->cur >= 0 && dy->cur <= dy->largest && - dy->largest <= dy->max, file, line); - return dy; - } - - #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__) - #define Dynarr_verify_mod(d) Dynarr_verify_mod_1 (d, __FILE__, __LINE__) - #define Dynarr_lock(d) (Dynarr_verify_mod (d)->locked = 1) - #define Dynarr_unlock(d) ((d)->locked = 0) - #else - #define Dynarr_verify(d) (d) - #define Dynarr_verify_mod(d) (d) - #define Dynarr_lock(d) - #define Dynarr_unlock(d) - #endif /* ERROR_CHECK_STRUCTURES */ - - #define Dynarr_length(d) (Dynarr_verify (d)->cur) - #define Dynarr_largest(d) (Dynarr_verify (d)->largest) - #define Dynarr_reset(d) (Dynarr_verify_mod (d)->cur = 0) - #define Dynarr_add_many(d, el, len) Dynarr_insert_many (d, el, len, (d)->cur) - #define Dynarr_insert_many_at_start(d, el, len) \ - Dynarr_insert_many (d, el, len, 0) - #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1) - #define Dynarr_add_lisp_string(d, s, codesys) \ - do { \ - Lisp_Object dyna_ls_s = (s); \ - Lisp_Object dyna_ls_cs = (codesys); \ - Extbyte *dyna_ls_eb; \ - Bytecount dyna_ls_bc; \ - \ - LISP_STRING_TO_SIZED_EXTERNAL (dyna_ls_s, dyna_ls_eb, \ - dyna_ls_bc, dyna_ls_cs); \ - Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc); \ - } while (0) - - #define Dynarr_add(d, el) ( \ - Dynarr_verify_mod (d)->cur >= (d)->max ? Dynarr_resize ((d), (d)->cur+1) : \ - (void) 0, \ - ((d)->base)[(d)->cur++] = (el), \ - (d)->cur > (d)->largest ? (d)->largest = (d)->cur : (int) 0) - - /* The following defines will get you into real trouble if you aren't - careful. But they can save a lot of execution time when used wisely. */ - #define Dynarr_increment(d) (Dynarr_verify_mod (d)->cur++) - #define Dynarr_set_size(d, n) (Dynarr_verify_mod (d)->cur = n) - - #define Dynarr_pop(d) \ - (assert ((d)->cur > 0), Dynarr_verify_mod (d)->cur--, \ - Dynarr_at (d, (d)->cur)) - #define Dynarr_delete(d, i) Dynarr_delete_many (d, i, 1) - #define Dynarr_delete_by_pointer(d, p) \ - Dynarr_delete_many (d, (p) - ((d)->base), 1) - - #define Dynarr_delete_object(d, el) \ - do \ - { \ - REGISTER int i; \ - for (i = Dynarr_length (d) - 1; i >= 0; i--) \ - { \ - if (el == Dynarr_at (d, i)) \ - Dynarr_delete_many (d, i, 1); \ - } \ - } while (0) - - #ifdef MEMORY_USAGE_STATS - struct overhead_stats; - Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats); - #endif - - void *stack_like_malloc (Bytecount size); - void stack_like_free (void *val); - #endif /* not NEW_GC */ - /************************************************************************/ /** Definitions of more complex types **/ /************************************************************************/ --- 1251,1256 ---- *************** *** 1468,1560 **** typedef struct Lisp_Image_Instance Lisp_Image_Instance; /* glyphs.h */ typedef struct Lisp_Gui_Item Lisp_Gui_Item; - #ifndef NEW_GC - /* ------------------------------- */ - /* Dynarr typedefs */ - /* ------------------------------- */ - - /* Dynarr typedefs -- basic types first */ - - typedef struct - { - Dynarr_declare (Ibyte); - } Ibyte_dynarr; - - typedef struct - { - Dynarr_declare (Extbyte); - } Extbyte_dynarr; - - typedef struct - { - Dynarr_declare (Ichar); - } Ichar_dynarr; - - typedef struct - { - Dynarr_declare (char); - } char_dynarr; - - typedef struct - { - Dynarr_declare (char *); - } char_ptr_dynarr; - - typedef unsigned char unsigned_char; - typedef struct - { - Dynarr_declare (unsigned char); - } unsigned_char_dynarr; - - typedef unsigned long unsigned_long; - typedef struct - { - Dynarr_declare (unsigned long); - } unsigned_long_dynarr; - - typedef struct - { - Dynarr_declare (int); - } int_dynarr; - - typedef struct - { - Dynarr_declare (Charbpos); - } Charbpos_dynarr; - - typedef struct - { - Dynarr_declare (Bytebpos); - } Bytebpos_dynarr; - - typedef struct - { - Dynarr_declare (Charcount); - } Charcount_dynarr; - - typedef struct - { - Dynarr_declare (Bytecount); - } Bytecount_dynarr; - - /* Dynarr typedefs -- more complex types */ - - typedef struct - { - Dynarr_declare (struct face_cachel); - } face_cachel_dynarr; - - typedef struct - { - Dynarr_declare (struct glyph_cachel); - } glyph_cachel_dynarr; - - typedef struct - { - Dynarr_declare (struct console_type_entry); - } console_type_entry_dynarr; - #endif /* not NEW_GC */ - /* ------------------------------- */ /* enum typedefs */ /* ------------------------------- */ --- 1336,1341 ---- *************** *** 1670,1689 **** #define XPNTR(x) ((void *) XPNTRVAL(x)) - #ifndef NEW_GC - /* WARNING WARNING WARNING. You must ensure on your own that proper - GC protection is provided for the elements in this array. */ - typedef struct - { - Dynarr_declare (Lisp_Object); - } Lisp_Object_dynarr; - - typedef struct - { - Dynarr_declare (Lisp_Object *); - } Lisp_Object_ptr_dynarr; - #endif /* not NEW_GC */ - /* Close your eyes now lest you vomit or spontaneously combust ... */ #define HACKEQ_UNSAFE(obj1, obj2) \ --- 1451,1456 ---- *************** *** 1713,1721 **** BEGIN_C_DECLS - #ifdef NEW_GC /* ------------------------ dynamic arrays ------------------- */ #ifdef ERROR_CHECK_STRUCTURES #define Dynarr_declare(type) \ struct lrecord_header header; \ --- 1480,1488 ---- BEGIN_C_DECLS /* ------------------------ dynamic arrays ------------------- */ + #ifdef NEW_GC #ifdef ERROR_CHECK_STRUCTURES #define Dynarr_declare(type) \ struct lrecord_header header; \ *************** *** 1736,1741 **** --- 1503,1528 ---- int largest; \ int max #endif /* ERROR_CHECK_STRUCTURES */ + #else /* not NEW_GC */ + #ifdef ERROR_CHECK_STRUCTURES + #define Dynarr_declare(type) \ + struct lrecord_header header; \ + type *base; \ + int locked; \ + int elsize; \ + int cur; \ + int largest; \ + int max + #else + #define Dynarr_declare(type) \ + struct lrecord_header header; \ + type *base; \ + int elsize; \ + int cur; \ + int largest; \ + int max + #endif /* ERROR_CHECK_STRUCTURES */ + #endif /* not NEW_GC */ typedef struct dynarr { *************** *** 1748,1753 **** --- 1535,1541 ---- MODULE_API void Dynarr_delete_many (void *d, int start, int len); MODULE_API void Dynarr_free (void *d); + #ifdef NEW_GC MODULE_API void *Dynarr_lisp_newf (int elsize, const struct lrecord_implementation *dynarr_imp, *************** *** 1757,1762 **** --- 1545,1551 ---- ((type##_dynarr *) Dynarr_lisp_newf (sizeof (type), dynarr_imp, imp)) #define Dynarr_lisp_new2(dynarr_type, type, dynarr_imp, imp) \ ((dynarr_type *) Dynarr_lisp_newf (sizeof (type)), dynarr_imp, imp) + #endif /* NEW_GC */ #define Dynarr_new(type) ((type##_dynarr *) Dynarr_newf (sizeof (type))) #define Dynarr_new2(dynarr_type, type) \ ((dynarr_type *) Dynarr_newf (sizeof (type))) *************** *** 1820,1848 **** Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc); \ } while (0) ! #if 1 #define Dynarr_add(d, el) \ do { \ if (Dynarr_verify_mod (d)->cur >= (d)->max) \ Dynarr_resize ((d), (d)->cur+1); \ ((d)->base)[(d)->cur] = (el); \ \ ! if ((d)->lisp_imp) \ set_lheader_implementation \ ! ((struct lrecord_header *)&(((d)->base)[(d)->cur]), \ ! (d)->lisp_imp); \ \ (d)->cur++; \ if ((d)->cur > (d)->largest) \ (d)->largest = (d)->cur; \ } while (0) ! #else #define Dynarr_add(d, el) ( \ Dynarr_verify_mod (d)->cur >= (d)->max ? Dynarr_resize ((d), (d)->cur+1) : \ (void) 0, \ ((d)->base)[(d)->cur++] = (el), \ (d)->cur > (d)->largest ? (d)->largest = (d)->cur : (int) 0) ! #endif /* The following defines will get you into real trouble if you aren't --- 1609,1637 ---- Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc); \ } while (0) ! #ifdef NEW_GC #define Dynarr_add(d, el) \ do { \ + const struct lrecord_implementation *imp = (d)->lisp_imp; \ if (Dynarr_verify_mod (d)->cur >= (d)->max) \ Dynarr_resize ((d), (d)->cur+1); \ ((d)->base)[(d)->cur] = (el); \ \ ! if (imp) \ set_lheader_implementation \ ! ((struct lrecord_header *)&(((d)->base)[(d)->cur]), imp); \ \ (d)->cur++; \ if ((d)->cur > (d)->largest) \ (d)->largest = (d)->cur; \ } while (0) ! #else /* not NEW_GC */ #define Dynarr_add(d, el) ( \ Dynarr_verify_mod (d)->cur >= (d)->max ? Dynarr_resize ((d), (d)->cur+1) : \ (void) 0, \ ((d)->base)[(d)->cur++] = (el), \ (d)->cur > (d)->largest ? (d)->largest = (d)->cur : (int) 0) ! #endif /* not NEW_GC */ /* The following defines will get you into real trouble if you aren't *************** *** 1951,1956 **** --- 1740,1746 ---- Dynarr_declare (struct face_cachel); } face_cachel_dynarr; + #ifdef NEW_GC DECLARE_LRECORD (face_cachel_dynarr, face_cachel_dynarr); #define XFACE_CACHEL_DYNARR(x) \ XRECORD (x, face_cachel_dynarr, face_cachel_dynarr) *************** *** 1958,1969 **** --- 1748,1761 ---- #define FACE_CACHEL_DYNARRP(x) RECORDP (x, face_cachel_dynarr) #define CHECK_FACE_CACHEL_DYNARR(x) CHECK_RECORD (x, face_cachel_dynarr) #define CONCHECK_FACE_CACHEL_DYNARR(x) CONCHECK_RECORD (x, face_cachel_dynarr) + #endif /* NEW_GC */ typedef struct { Dynarr_declare (struct glyph_cachel); } glyph_cachel_dynarr; + #ifdef NEW_GC DECLARE_LRECORD (glyph_cachel_dynarr, glyph_cachel_dynarr); #define XGLYPH_CACHEL_DYNARR(x) \ XRECORD (x, glyph_cachel_dynarr, glyph_cachel_dynarr) *************** *** 1972,1977 **** --- 1764,1770 ---- #define CHECK_GLYPH_CACHEL_DYNARR(x) CHECK_RECORD (x, glyph_cachel_dynarr) #define CONCHECK_GLYPH_CACHEL_DYNARR(x) \ CONCHECK_RECORD (x, glyph_cachel_dynarr) + #endif /* NEW_GC */ typedef struct { *************** *** 1989,1995 **** { Dynarr_declare (Lisp_Object *); } Lisp_Object_ptr_dynarr; - #endif /* NEW_GC */ /*------------------------------ unbound -------------------------------*/ --- 1782,1787 ---- *************** *** 2038,2050 **** #define CHECK_CONS(x) CHECK_RECORD (x, cons) #define CONCHECK_CONS(x) CONCHECK_RECORD (x, cons) ! #ifdef MC_ALLOC #define CONS_MARKED_P(c) MARKED_P (&((c)->lheader)) #define MARK_CONS(c) MARK (&((c)->lheader)) ! #else /* not MC_ALLOC */ #define CONS_MARKED_P(c) MARKED_RECORD_HEADER_P(&((c)->lheader)) #define MARK_CONS(c) MARK_RECORD_HEADER (&((c)->lheader)) ! #endif /* not MC_ALLOC */ extern MODULE_API Lisp_Object Qnil; --- 1830,1842 ---- #define CHECK_CONS(x) CHECK_RECORD (x, cons) #define CONCHECK_CONS(x) CONCHECK_RECORD (x, cons) ! #ifdef NEW_GC #define CONS_MARKED_P(c) MARKED_P (&((c)->lheader)) #define MARK_CONS(c) MARK (&((c)->lheader)) ! #else /* not NEW_GC */ #define CONS_MARKED_P(c) MARKED_RECORD_HEADER_P(&((c)->lheader)) #define MARK_CONS(c) MARK_RECORD_HEADER (&((c)->lheader)) ! #endif /* not NEW_GC */ extern MODULE_API Lisp_Object Qnil; *************** *** 2637,2656 **** /* WARNING: Everything before ascii_begin must agree exactly with struct lrecord_header */ unsigned int type :8; ! #ifdef MC_ALLOC unsigned int lisp_readonly :1; unsigned int free :1; /* Number of chars at beginning of string that are one byte in length (byte_ascii_p) */ unsigned int ascii_begin :22; ! #else /* not MC_ALLOC */ unsigned int mark :1; unsigned int c_readonly :1; unsigned int lisp_readonly :1; /* Number of chars at beginning of string that are one byte in length (byte_ascii_p) */ unsigned int ascii_begin :21; ! #endif /* not MC_ALLOC */ } v; } u; #ifdef NEW_GC --- 2429,2448 ---- /* WARNING: Everything before ascii_begin must agree exactly with struct lrecord_header */ unsigned int type :8; ! #ifdef NEW_GC unsigned int lisp_readonly :1; unsigned int free :1; /* Number of chars at beginning of string that are one byte in length (byte_ascii_p) */ unsigned int ascii_begin :22; ! #else /* not NEW_GC */ unsigned int mark :1; unsigned int c_readonly :1; unsigned int lisp_readonly :1; /* Number of chars at beginning of string that are one byte in length (byte_ascii_p) */ unsigned int ascii_begin :21; ! #endif /* not NEW_GC */ } v; } u; #ifdef NEW_GC *************** *** 2664,2674 **** }; typedef struct Lisp_String Lisp_String; ! #ifdef MC_ALLOC #define MAX_STRING_ASCII_BEGIN ((1 << 22) - 1) ! #else #define MAX_STRING_ASCII_BEGIN ((1 << 21) - 1) ! #endif DECLARE_MODULE_API_LRECORD (string, Lisp_String); #define XSTRING(x) XRECORD (x, string, Lisp_String) --- 2456,2466 ---- }; typedef struct Lisp_String Lisp_String; ! #ifdef NEW_GC #define MAX_STRING_ASCII_BEGIN ((1 << 22) - 1) ! #else /* not NEW_GC */ #define MAX_STRING_ASCII_BEGIN ((1 << 21) - 1) ! #endif /* not NEW_GC */ DECLARE_MODULE_API_LRECORD (string, Lisp_String); #define XSTRING(x) XRECORD (x, string, Lisp_String) *************** *** 2683,2688 **** --- 2475,2481 ---- /* Operations on Lisp_String *'s; only ones left */ #ifdef NEW_GC + #define set_lispstringp_direct(s) ((s)->indirect = 0) #define set_lispstringp_indirect(s) ((s)->indirect = 1) #define set_lispstringp_length(s, len) XSET_STRING_DATA_SIZE (s, len) #define set_lispstringp_data(s, ptr) XSET_STRING_DATA_DATA (s, ptr) *************** *** 3185,3196 **** /*--------------------------- readonly objects -------------------------*/ ! #ifndef MC_ALLOC #define CHECK_C_WRITEABLE(obj) \ do { if (c_readonly (obj)) c_write_error (obj); } while (0) #define C_READONLY(obj) (C_READONLY_RECORD_HEADER_P(XRECORD_LHEADER (obj))) ! #endif /* not MC_ALLOC */ #define CHECK_LISP_WRITEABLE(obj) \ do { if (lisp_readonly (obj)) lisp_write_error (obj); } while (0) --- 2978,2989 ---- /*--------------------------- readonly objects -------------------------*/ ! #ifndef NEW_GC #define CHECK_C_WRITEABLE(obj) \ do { if (c_readonly (obj)) c_write_error (obj); } while (0) #define C_READONLY(obj) (C_READONLY_RECORD_HEADER_P(XRECORD_LHEADER (obj))) ! #endif /* not NEW_GC */ #define CHECK_LISP_WRITEABLE(obj) \ do { if (lisp_readonly (obj)) lisp_write_error (obj); } while (0) *************** *** 3432,3438 **** /* Can't be const, because then subr->doc is read-only and Snarf_documentation chokes */ ! #ifdef MC_ALLOC #define DEFUN(lname, Fname, min_args, max_args, prompt, arglist) \ Lisp_Object Fname (EXFUN_##max_args); \ static struct Lisp_Subr MC_ALLOC_S##Fname = \ --- 3225,3231 ---- /* Can't be const, because then subr->doc is read-only and Snarf_documentation chokes */ ! #ifdef NEW_GC #define DEFUN(lname, Fname, min_args, max_args, prompt, arglist) \ Lisp_Object Fname (EXFUN_##max_args); \ static struct Lisp_Subr MC_ALLOC_S##Fname = \ *************** *** 3474,3480 **** DOESNT_RETURN_TYPE (Lisp_Object) Fname (DEFUN_##max_args arglist) #define GET_DEFUN_LISP_OBJECT(Fname) \ wrap_subr (S##Fname); ! #else /* not MC_ALLOC */ #define DEFUN(lname, Fname, min_args, max_args, prompt, arglist) \ Lisp_Object Fname (EXFUN_##max_args); \ static struct Lisp_Subr S##Fname = \ --- 3267,3273 ---- DOESNT_RETURN_TYPE (Lisp_Object) Fname (DEFUN_##max_args arglist) #define GET_DEFUN_LISP_OBJECT(Fname) \ wrap_subr (S##Fname); ! #else /* not NEW_GC */ #define DEFUN(lname, Fname, min_args, max_args, prompt, arglist) \ Lisp_Object Fname (EXFUN_##max_args); \ static struct Lisp_Subr S##Fname = \ *************** *** 3516,3522 **** DOESNT_RETURN_TYPE (Lisp_Object) Fname (DEFUN_##max_args arglist) #define GET_DEFUN_LISP_OBJECT(Fname) \ wrap_subr (&S##Fname); ! #endif /* not MC_ALLOC */ /* Heavy ANSI C preprocessor hackery to get DEFUN to declare a prototype that matches max_args, and add the obligatory --- 3309,3315 ---- DOESNT_RETURN_TYPE (Lisp_Object) Fname (DEFUN_##max_args arglist) #define GET_DEFUN_LISP_OBJECT(Fname) \ wrap_subr (&S##Fname); ! #endif /* not NEW_GC */ /* Heavy ANSI C preprocessor hackery to get DEFUN to declare a prototype that matches max_args, and add the obligatory *************** *** 4021,4027 **** #endif ! #ifdef MC_ALLOC extern Lisp_Object_dynarr *mcpros; #ifdef DEBUG_XEMACS /* Help debug crashes gc-marking a mcpro'ed object. */ --- 3814,3820 ---- #endif ! #ifdef NEW_GC extern Lisp_Object_dynarr *mcpros; #ifdef DEBUG_XEMACS /* Help debug crashes gc-marking a mcpro'ed object. */ *************** *** 4031,4037 **** /* Call mcpro (&var) to protect mc variable `var'. */ MODULE_API void mcpro (Lisp_Object); #endif /* not DEBUG_XEMACS */ ! #endif /* MC_ALLOC */ void register_post_gc_action (void (*fun) (void *), void *arg); int begin_gc_forbidden (void); --- 3824,3830 ---- /* Call mcpro (&var) to protect mc variable `var'. */ MODULE_API void mcpro (Lisp_Object); #endif /* not DEBUG_XEMACS */ ! #endif /* NEW_GC */ void register_post_gc_action (void (*fun) (void *), void *arg); int begin_gc_forbidden (void); *************** *** 4089,4097 **** MODULE_API EXFUN (Fmake_vector, 2); MODULE_API EXFUN (Fvector, MANY); ! #ifndef MC_ALLOC void release_breathing_space (void); ! #endif /* not MC_ALLOC */ Lisp_Object noseeum_cons (Lisp_Object, Lisp_Object); MODULE_API Lisp_Object make_vector (Elemcount, Lisp_Object); MODULE_API Lisp_Object vector1 (Lisp_Object); --- 3882,3890 ---- MODULE_API EXFUN (Fmake_vector, 2); MODULE_API EXFUN (Fvector, MANY); ! #ifndef NEW_GC void release_breathing_space (void); ! #endif /* not NEW_GC */ Lisp_Object noseeum_cons (Lisp_Object, Lisp_Object); MODULE_API Lisp_Object make_vector (Elemcount, Lisp_Object); MODULE_API Lisp_Object vector1 (Lisp_Object); diff -c 'xemacs-21.5.25/src/lrecord.h' 'xemacs-21.5.26/src/lrecord.h' Index: ./src/lrecord.h *** ./src/lrecord.h Sun Nov 27 19:51:25 2005 --- ./src/lrecord.h Tue Feb 28 01:29:27 2006 *************** *** 26,32 **** #ifndef INCLUDED_lrecord_h_ #define INCLUDED_lrecord_h_ ! #ifdef MC_ALLOC /* The "lrecord" type of Lisp object is used for all object types other than a few simple ones (like char and int). This allows many types to be implemented but only a few bits required in a Lisp --- 26,32 ---- #ifndef INCLUDED_lrecord_h_ #define INCLUDED_lrecord_h_ ! #ifdef NEW_GC /* The "lrecord" type of Lisp object is used for all object types other than a few simple ones (like char and int). This allows many types to be implemented but only a few bits required in a Lisp *************** *** 45,51 **** could contain Lisp_Objects in it), you may well be able to use the opaque type. */ ! #else /* not MC_ALLOC */ /* The "lrecord" type of Lisp object is used for all object types other than a few simple ones. This allows many types to be implemented but only a few bits required in a Lisp object for type --- 45,51 ---- could contain Lisp_Objects in it), you may well be able to use the opaque type. */ ! #else /* not NEW_GC */ /* The "lrecord" type of Lisp object is used for all object types other than a few simple ones. This allows many types to be implemented but only a few bits required in a Lisp object for type *************** *** 79,87 **** could contain Lisp_Objects in it), you may well be able to use the opaque type. --ben */ ! #endif /* not MC_ALLOC */ ! #ifdef MC_ALLOC #define ALLOC_LCRECORD_TYPE alloc_lrecord_type #define COPY_SIZED_LCRECORD copy_sized_lrecord #define COPY_LCRECORD copy_lrecord --- 79,87 ---- could contain Lisp_Objects in it), you may well be able to use the opaque type. --ben */ ! #endif /* not NEW_GC */ ! #ifdef NEW_GC #define ALLOC_LCRECORD_TYPE alloc_lrecord_type #define COPY_SIZED_LCRECORD copy_sized_lrecord #define COPY_LCRECORD copy_lrecord *************** *** 91,97 **** #define LCRECORD_HEADER lrecord_header #define BASIC_ALLOC_LCRECORD alloc_lrecord #define FREE_LCRECORD free_lrecord ! #else #define ALLOC_LCRECORD_TYPE old_alloc_lcrecord_type #define COPY_SIZED_LCRECORD old_copy_sized_lcrecord #define COPY_LCRECORD old_copy_lcrecord --- 91,97 ---- #define LCRECORD_HEADER lrecord_header #define BASIC_ALLOC_LCRECORD alloc_lrecord #define FREE_LCRECORD free_lrecord ! #else /* not NEW_GC */ #define ALLOC_LCRECORD_TYPE old_alloc_lcrecord_type #define COPY_SIZED_LCRECORD old_copy_sized_lcrecord #define COPY_LCRECORD old_copy_lcrecord *************** *** 100,106 **** #define LCRECORD_HEADER old_lcrecord_header #define BASIC_ALLOC_LCRECORD old_basic_alloc_lcrecord #define FREE_LCRECORD old_free_lcrecord ! #endif BEGIN_C_DECLS --- 100,106 ---- #define LCRECORD_HEADER old_lcrecord_header #define BASIC_ALLOC_LCRECORD old_basic_alloc_lcrecord #define FREE_LCRECORD old_free_lcrecord ! #endif /* not NEW_GC */ BEGIN_C_DECLS *************** *** 111,117 **** field. */ unsigned int type :8; ! #ifdef MC_ALLOC /* 1 if the object is readonly from lisp */ unsigned int lisp_readonly :1; --- 111,117 ---- field. */ unsigned int type :8; ! #ifdef NEW_GC /* 1 if the object is readonly from lisp */ unsigned int lisp_readonly :1; *************** *** 125,131 **** anyway. (The bits are used for strings, though.) */ unsigned int uid :22; ! #else /* not MC_ALLOC */ /* If `mark' is 0 after the GC mark phase, the object will be freed during the GC sweep phase. There are 2 ways that `mark' can be 1: - by being referenced from other objects during the GC mark phase --- 125,131 ---- anyway. (The bits are used for strings, though.) */ unsigned int uid :22; ! #else /* not NEW_GC */ /* If `mark' is 0 after the GC mark phase, the object will be freed during the GC sweep phase. There are 2 ways that `mark' can be 1: - by being referenced from other objects during the GC mark phase *************** *** 145,158 **** anyway. (The bits are used for strings, though.) */ unsigned int uid :21; ! #endif /* not MC_ALLOC */ }; struct lrecord_implementation; int lrecord_type_index (const struct lrecord_implementation *implementation); extern int lrecord_uid_counter; ! #ifdef MC_ALLOC #define set_lheader_implementation(header,imp) do { \ struct lrecord_header* SLI_header = (header); \ SLI_header->type = (imp)->lrecord_type_index; \ --- 145,158 ---- anyway. (The bits are used for strings, though.) */ unsigned int uid :21; ! #endif /* not NEW_GC */ }; struct lrecord_implementation; int lrecord_type_index (const struct lrecord_implementation *implementation); extern int lrecord_uid_counter; ! #ifdef NEW_GC #define set_lheader_implementation(header,imp) do { \ struct lrecord_header* SLI_header = (header); \ SLI_header->type = (imp)->lrecord_type_index; \ *************** *** 160,166 **** SLI_header->free = 0; \ SLI_header->uid = lrecord_uid_counter++; \ } while (0) ! #else /* not MC_ALLOC */ #define set_lheader_implementation(header,imp) do { \ struct lrecord_header* SLI_header = (header); \ SLI_header->type = (imp)->lrecord_type_index; \ --- 160,166 ---- SLI_header->free = 0; \ SLI_header->uid = lrecord_uid_counter++; \ } while (0) ! #else /* not NEW_GC */ #define set_lheader_implementation(header,imp) do { \ struct lrecord_header* SLI_header = (header); \ SLI_header->type = (imp)->lrecord_type_index; \ *************** *** 169,177 **** SLI_header->lisp_readonly = 0; \ SLI_header->uid = lrecord_uid_counter++; \ } while (0) ! #endif /* not MC_ALLOC */ ! #ifndef MC_ALLOC struct old_lcrecord_header { struct lrecord_header lheader; --- 169,177 ---- SLI_header->lisp_readonly = 0; \ SLI_header->uid = lrecord_uid_counter++; \ } while (0) ! #endif /* not NEW_GC */ ! #ifndef NEW_GC struct old_lcrecord_header { struct lrecord_header lheader; *************** *** 209,215 **** struct old_lcrecord_header lcheader; Lisp_Object chain; }; ! #endif /* not MC_ALLOC */ enum lrecord_type { --- 209,215 ---- struct old_lcrecord_header lcheader; Lisp_Object chain; }; ! #endif /* not NEW_GC */ enum lrecord_type { *************** *** 226,234 **** lrecord_type_cons, lrecord_type_vector, lrecord_type_string, ! #ifndef MC_ALLOC lrecord_type_lcrecord_list, ! #endif /* not MC_ALLOC */ lrecord_type_compiled_function, lrecord_type_weak_list, lrecord_type_bit_vector, --- 226,234 ---- lrecord_type_cons, lrecord_type_vector, lrecord_type_string, ! #ifndef NEW_GC lrecord_type_lcrecord_list, ! #endif /* not NEW_GC */ lrecord_type_compiled_function, lrecord_type_weak_list, lrecord_type_bit_vector, *************** *** 297,306 **** lrecord_type_bignum, lrecord_type_ratio, lrecord_type_bigfloat, ! #ifndef MC_ALLOC lrecord_type_free, /* only used for "free" lrecords */ lrecord_type_undefined, /* only used for debugging */ ! #endif /* not MC_ALLOC */ #ifdef NEW_GC lrecord_type_string_indirect_data, lrecord_type_string_direct_data, --- 297,306 ---- lrecord_type_bignum, lrecord_type_ratio, lrecord_type_bigfloat, ! #ifndef NEW_GC lrecord_type_free, /* only used for "free" lrecords */ lrecord_type_undefined, /* only used for debugging */ ! #endif /* not NEW_GC */ #ifdef NEW_GC lrecord_type_string_indirect_data, lrecord_type_string_direct_data, *************** *** 400,424 **** int (*remprop) (Lisp_Object obj, Lisp_Object prop); Lisp_Object (*plist) (Lisp_Object obj); ! #ifdef MC_ALLOC /* Only one of `static_size' and `size_in_bytes_method' is non-0. */ ! #else /* not MC_ALLOC */ /* Only one of `static_size' and `size_in_bytes_method' is non-0. If both are 0, this type is not instantiable by old_basic_alloc_lcrecord(). */ ! #endif /* not MC_ALLOC */ Bytecount static_size; Bytecount (*size_in_bytes_method) (const void *header); /* The (constant) index into lrecord_implementations_table */ enum lrecord_type lrecord_type_index; ! #ifndef MC_ALLOC /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. one that does not have an old_lcrecord_header at the front and which is (usually) allocated in frob blocks. */ unsigned int basic_p :1; ! #endif /* not MC_ALLOC */ }; /* All the built-in lisp object types are enumerated in `enum lrecord_type'. --- 400,424 ---- int (*remprop) (Lisp_Object obj, Lisp_Object prop); Lisp_Object (*plist) (Lisp_Object obj); ! #ifdef NEW_GC /* Only one of `static_size' and `size_in_bytes_method' is non-0. */ ! #else /* not NEW_GC */ /* Only one of `static_size' and `size_in_bytes_method' is non-0. If both are 0, this type is not instantiable by old_basic_alloc_lcrecord(). */ ! #endif /* not NEW_GC */ Bytecount static_size; Bytecount (*size_in_bytes_method) (const void *header); /* The (constant) index into lrecord_implementations_table */ enum lrecord_type lrecord_type_index; ! #ifndef NEW_GC /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. one that does not have an old_lcrecord_header at the front and which is (usually) allocated in frob blocks. */ unsigned int basic_p :1; ! #endif /* not NEW_GC */ }; /* All the built-in lisp object types are enumerated in `enum lrecord_type'. *************** *** 441,447 **** extern int gc_in_progress; ! #ifdef MC_ALLOC #include "mc-alloc.h" #ifdef ALLOC_TYPE_STATS --- 441,447 ---- extern int gc_in_progress; ! #ifdef NEW_GC #include "mc-alloc.h" #ifdef ALLOC_TYPE_STATS *************** *** 453,459 **** #endif /* ALLOC_TYPE_STATS */ /* Tell mc-alloc how to call a finalizer. */ - #ifdef NEW_GC #define MC_ALLOC_CALL_FINALIZER(ptr) \ { \ Lisp_Object MCACF_obj = wrap_pointer_1 (ptr); \ --- 453,458 ---- *************** *** 470,490 **** } \ } \ } while (0) - #else /* not NEW_GC */ - #define MC_ALLOC_CALL_FINALIZER(ptr) \ - { \ - Lisp_Object MCACF_obj = wrap_pointer_1 (ptr); \ - struct lrecord_header *MCACF_lheader = XRECORD_LHEADER (MCACF_obj); \ - if (XRECORD_LHEADER (MCACF_obj) && LRECORDP (MCACF_obj) \ - && !LRECORD_FREE_P (MCACF_lheader) ) \ - { \ - const struct lrecord_implementation *MCACF_implementation \ - = LHEADER_IMPLEMENTATION (MCACF_lheader); \ - if (MCACF_implementation && MCACF_implementation->finalizer) \ - MCACF_implementation->finalizer (ptr, 0); \ - } \ - } while (0) - #endif /* not NEW_GC */ /* Tell mc-alloc how to call a finalizer for disksave. */ #define MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE(ptr) \ --- 469,474 ---- *************** *** 521,527 **** #define MARK_LRECORD_AS_LISP_READONLY(ptr) \ ((void) (((struct lrecord_header *) ptr)->lisp_readonly = 1)) ! #else /* not MC_ALLOC */ #define LRECORD_FREE_P(ptr) \ (((struct lrecord_header *) ptr)->type == lrecord_type_free) --- 505,511 ---- #define MARK_LRECORD_AS_LISP_READONLY(ptr) \ ((void) (((struct lrecord_header *) ptr)->lisp_readonly = 1)) ! #else /* not NEW_GC */ #define LRECORD_FREE_P(ptr) \ (((struct lrecord_header *) ptr)->type == lrecord_type_free) *************** *** 544,550 **** } while (0) #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ ((void) ((lheader)->lisp_readonly = 1)) ! #endif /* not MC_ALLOC */ #ifdef USE_KKCC #define RECORD_DESCRIPTION(lheader) lrecord_memory_descriptions[(lheader)->type] --- 528,534 ---- } while (0) #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ ((void) ((lheader)->lisp_readonly = 1)) ! #endif /* not NEW_GC */ #ifdef USE_KKCC #define RECORD_DESCRIPTION(lheader) lrecord_memory_descriptions[(lheader)->type] *************** *** 1054,1067 **** XD_FLAG_NO_PDUMP = 2, /* Indicates that this is a "default" entry in a union map. */ XD_FLAG_UNION_DEFAULT_ENTRY = 4, ! #ifndef MC_ALLOC /* Indicates that this is a free Lisp object we're marking. Only relevant for ERROR_CHECK_GC. This occurs when we're marking lcrecord-lists, where the objects have had their type changed to lrecord_type_free and also have had their free bit set, but we mark them as normal. */ XD_FLAG_FREE_LISP_OBJECT = 8 ! #endif /* not MC_ALLOC */ #if 0 , /* Suggestions for other possible flags: */ --- 1038,1051 ---- XD_FLAG_NO_PDUMP = 2, /* Indicates that this is a "default" entry in a union map. */ XD_FLAG_UNION_DEFAULT_ENTRY = 4, ! #ifndef NEW_GC /* Indicates that this is a free Lisp object we're marking. Only relevant for ERROR_CHECK_GC. This occurs when we're marking lcrecord-lists, where the objects have had their type changed to lrecord_type_free and also have had their free bit set, but we mark them as normal. */ XD_FLAG_FREE_LISP_OBJECT = 8 ! #endif /* not NEW_GC */ #if 0 , /* Suggestions for other possible flags: */ *************** *** 1188,1208 **** #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) ! #ifdef MC_ALLOC #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ const struct lrecord_implementation lrecord_##c_name = \ { name, dumpable, marker, printer, nuker, equal, hash, desc, \ getprop, putprop, remprop, plist, size, sizer, \ lrecord_type_##c_name } ! #else /* not MC_ALLOC */ #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ const struct lrecord_implementation lrecord_##c_name = \ { name, dumpable, marker, printer, nuker, equal, hash, desc, \ getprop, putprop, remprop, plist, size, sizer, \ lrecord_type_##c_name, basic_p } ! #endif /* not MC_ALLOC */ #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) --- 1172,1192 ---- #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) ! #ifdef NEW_GC #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ const struct lrecord_implementation lrecord_##c_name = \ { name, dumpable, marker, printer, nuker, equal, hash, desc, \ getprop, putprop, remprop, plist, size, sizer, \ lrecord_type_##c_name } ! #else /* not NEW_GC */ #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ const struct lrecord_implementation lrecord_##c_name = \ { name, dumpable, marker, printer, nuker, equal, hash, desc, \ getprop, putprop, remprop, plist, size, sizer, \ lrecord_type_##c_name, basic_p } ! #endif /* not NEW_GC */ #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) *************** *** 1216,1222 **** #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) ! #ifdef MC_ALLOC #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ int lrecord_type_##c_name; \ --- 1200,1206 ---- #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) ! #ifdef NEW_GC #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ int lrecord_type_##c_name; \ *************** *** 1224,1230 **** { name, dumpable, marker, printer, nuker, equal, hash, desc, \ getprop, putprop, remprop, plist, size, sizer, \ lrecord_type_last_built_in_type } ! #else /* not MC_ALLOC */ #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ int lrecord_type_##c_name; \ --- 1208,1214 ---- { name, dumpable, marker, printer, nuker, equal, hash, desc, \ getprop, putprop, remprop, plist, size, sizer, \ lrecord_type_last_built_in_type } ! #else /* not NEW_GC */ #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ int lrecord_type_##c_name; \ *************** *** 1232,1238 **** { name, dumpable, marker, printer, nuker, equal, hash, desc, \ getprop, putprop, remprop, plist, size, sizer, \ lrecord_type_last_built_in_type, basic_p } ! #endif /* not MC_ALLOC */ #ifdef USE_KKCC extern MODULE_API const struct memory_description *lrecord_memory_descriptions[]; --- 1216,1222 ---- { name, dumpable, marker, printer, nuker, equal, hash, desc, \ getprop, putprop, remprop, plist, size, sizer, \ lrecord_type_last_built_in_type, basic_p } ! #endif /* not NEW_GC */ #ifdef USE_KKCC extern MODULE_API const struct memory_description *lrecord_memory_descriptions[]; *************** *** 1588,1594 **** dead_wrong_type_argument (predicate, x); \ } while (0) ! #ifndef MC_ALLOC /*-------------------------- lcrecord-list -----------------------------*/ struct lcrecord_list --- 1572,1578 ---- dead_wrong_type_argument (predicate, x); \ } while (0) ! #ifndef NEW_GC /*-------------------------- lcrecord-list -----------------------------*/ struct lcrecord_list *************** *** 1723,1729 **** #define old_zero_lcrecord(lcr) old_zero_sized_lcrecord (lcr, sizeof (*(lcr))) ! #else /* MC_ALLOC */ /* How to allocate a lrecord: --- 1707,1713 ---- #define old_zero_lcrecord(lcr) old_zero_sized_lcrecord (lcr, sizeof (*(lcr))) ! #else /* NEW_GC */ /* How to allocate a lrecord: *************** *** 1767,1773 **** #define copy_lrecord(dst, src) copy_sized_lrecord (dst, src, sizeof (*(dst))) ! #endif /* MC_ALLOC */ #define zero_sized_lrecord(lcr, size) \ memset ((char *) (lcr) + sizeof (struct lrecord_header), 0, \ --- 1751,1757 ---- #define copy_lrecord(dst, src) copy_sized_lrecord (dst, src, sizeof (*(dst))) ! #endif /* NEW_GC */ #define zero_sized_lrecord(lcr, size) \ memset ((char *) (lcr) + sizeof (struct lrecord_header), 0, \ *************** *** 1886,1897 **** #ifdef PDUMP #include "dumper.h" ! #ifdef MC_ALLOC #define DUMPEDP(adr) 0 ! #else /* not MC_ALLOC */ #define DUMPEDP(adr) ((((Rawbyte *) (adr)) < pdump_end) && \ (((Rawbyte *) (adr)) >= pdump_start)) ! #endif /* not MC_ALLOC */ #else #define DUMPEDP(adr) 0 #endif --- 1870,1881 ---- #ifdef PDUMP #include "dumper.h" ! #ifdef NEW_GC #define DUMPEDP(adr) 0 ! #else /* not NEW_GC */ #define DUMPEDP(adr) ((((Rawbyte *) (adr)) < pdump_end) && \ (((Rawbyte *) (adr)) >= pdump_start)) ! #endif /* not NEW_GC */ #else #define DUMPEDP(adr) 0 #endif diff -c 'xemacs-21.5.25/src/lstream.c' 'xemacs-21.5.26/src/lstream.c' Index: ./src/lstream.c *** ./src/lstream.c Tue Oct 25 17:32:48 2005 --- ./src/lstream.c Tue Feb 28 01:29:27 2006 *************** *** 180,190 **** } } ! #ifndef MC_ALLOC static const Lstream_implementation *lstream_types[32]; static Lisp_Object Vlstream_free_list[32]; static int lstream_type_count; ! #endif /* not MC_ALLOC */ /* Allocate and return a new Lstream. This function is not really meant to be called directly; rather, each stream type should --- 180,190 ---- } } ! #ifndef NEW_GC static const Lstream_implementation *lstream_types[32]; static Lisp_Object Vlstream_free_list[32]; static int lstream_type_count; ! #endif /* not NEW_GC */ /* Allocate and return a new Lstream. This function is not really meant to be called directly; rather, each stream type should *************** *** 196,206 **** Lstream_new (const Lstream_implementation *imp, const char *mode) { Lstream *p; ! #ifdef MC_ALLOC p = XLSTREAM (wrap_pointer_1 (alloc_lrecord (aligned_sizeof_lstream (imp->size), &lrecord_lstream))); ! #else /* not MC_ALLOC */ int i; for (i = 0; i < lstream_type_count; i++) --- 196,206 ---- Lstream_new (const Lstream_implementation *imp, const char *mode) { Lstream *p; ! #ifdef NEW_GC p = XLSTREAM (wrap_pointer_1 (alloc_lrecord (aligned_sizeof_lstream (imp->size), &lrecord_lstream))); ! #else /* not NEW_GC */ int i; for (i = 0; i < lstream_type_count; i++) *************** *** 220,226 **** } p = XLSTREAM (alloc_managed_lcrecord (Vlstream_free_list[i])); ! #endif /* not MC_ALLOC */ /* Zero it out, except the header. */ memset ((char *) p + sizeof (p->header), '\0', aligned_sizeof_lstream (imp->size) - sizeof (p->header)); --- 220,226 ---- } p = XLSTREAM (alloc_managed_lcrecord (Vlstream_free_list[i])); ! #endif /* not NEW_GC */ /* Zero it out, except the header. */ memset ((char *) p + sizeof (p->header), '\0', aligned_sizeof_lstream (imp->size) - sizeof (p->header)); *************** *** 296,309 **** void Lstream_delete (Lstream *lstr) { ! #ifndef MC_ALLOC int i; ! #endif /* not MC_ALLOC */ Lisp_Object val = wrap_lstream (lstr); ! #ifdef MC_ALLOC free_lrecord (val); ! #else /* not MC_ALLOC */ for (i = 0; i < lstream_type_count; i++) { if (lstream_types[i] == lstr->imp) --- 296,309 ---- void Lstream_delete (Lstream *lstr) { ! #ifndef NEW_GC int i; ! #endif /* not NEW_GC */ Lisp_Object val = wrap_lstream (lstr); ! #ifdef NEW_GC free_lrecord (val); ! #else /* not NEW_GC */ for (i = 0; i < lstream_type_count; i++) { if (lstream_types[i] == lstr->imp) *************** *** 314,320 **** } ABORT (); ! #endif /* not MC_ALLOC */ } #define Lstream_internal_error(reason, lstr) \ --- 314,320 ---- } ABORT (); ! #endif /* not NEW_GC */ } #define Lstream_internal_error(reason, lstr) \ *************** *** 1865,1871 **** LSTREAM_HAS_METHOD (lisp_buffer, marker); } ! #ifndef MC_ALLOC void reinit_vars_of_lstream (void) { --- 1865,1871 ---- LSTREAM_HAS_METHOD (lisp_buffer, marker); } ! #ifndef NEW_GC void reinit_vars_of_lstream (void) { *************** *** 1877,1883 **** staticpro_nodump (&Vlstream_free_list[i]); } } ! #endif /* not MC_ALLOC */ void vars_of_lstream (void) --- 1877,1883 ---- staticpro_nodump (&Vlstream_free_list[i]); } } ! #endif /* not NEW_GC */ void vars_of_lstream (void) diff -c 'xemacs-21.5.25/src/marker.c' 'xemacs-21.5.26/src/marker.c' Index: ./src/marker.c *** ./src/marker.c Tue Oct 25 20:16:26 2005 --- ./src/marker.c Tue Feb 28 01:29:27 2006 *************** *** 104,110 **** { XD_END } }; ! #ifdef MC_ALLOC static void finalize_marker (void *header, int for_disksave) { --- 104,110 ---- { XD_END } }; ! #ifdef NEW_GC static void finalize_marker (void *header, int for_disksave) { *************** *** 121,133 **** finalize_marker, marker_equal, marker_hash, marker_description, Lisp_Marker); ! #else /* not MC_ALLOC */ DEFINE_BASIC_LRECORD_IMPLEMENTATION ("marker", marker, 1, /*dumpable-flag*/ mark_marker, print_marker, 0, marker_equal, marker_hash, marker_description, Lisp_Marker); ! #endif /* not MC_ALLOC */ /* Operations on markers. */ --- 121,133 ---- finalize_marker, marker_equal, marker_hash, marker_description, Lisp_Marker); ! #else /* not NEW_GC */ DEFINE_BASIC_LRECORD_IMPLEMENTATION ("marker", marker, 1, /*dumpable-flag*/ mark_marker, print_marker, 0, marker_equal, marker_hash, marker_description, Lisp_Marker); ! #endif /* not NEW_GC */ /* Operations on markers. */ *************** *** 512,522 **** for (m = BUF_MARKERS (b); m; m = m->next) total += sizeof (Lisp_Marker); ovstats->was_requested += total; ! #ifdef MC_ALLOC overhead = mc_alloced_storage_size (total, 0); ! #else /* not MC_ALLOC */ overhead = fixed_type_block_overhead (total); ! #endif /* not MC_ALLOC */ /* #### claiming this is all malloc overhead is not really right, but it has to go somewhere. */ ovstats->malloc_overhead += overhead; --- 512,522 ---- for (m = BUF_MARKERS (b); m; m = m->next) total += sizeof (Lisp_Marker); ovstats->was_requested += total; ! #ifdef NEW_GC overhead = mc_alloced_storage_size (total, 0); ! #else /* not NEW_GC */ overhead = fixed_type_block_overhead (total); ! #endif /* not NEW_GC */ /* #### claiming this is all malloc overhead is not really right, but it has to go somewhere. */ ovstats->malloc_overhead += overhead; diff -c 'xemacs-21.5.25/src/mc-alloc.c' 'xemacs-21.5.26/src/mc-alloc.c' Index: ./src/mc-alloc.c *** ./src/mc-alloc.c Sat Jan 21 22:34:21 2006 --- ./src/mc-alloc.c Mon Mar 27 00:24:26 2006 *************** *** 403,413 **** /* Number of mark bits: minimum 1, maximum 8. */ - #ifdef NEW_GC #define N_MARK_BITS 2 - #else /* not NEW_GC */ - #define N_MARK_BITS 1 - #endif /* not NEW_GC */ --- 403,409 ---- *************** *** 415,420 **** --- 411,418 ---- /* MC Allocator */ /************************************************************************/ + /* Set to 1 if memory becomes short. */ + EMACS_INT memory_shortage; /*--- misc functions ---------------------------------------------------*/ *************** *** 434,443 **** /* Visits all pages (page_headers) hooked into the used heap pages list and executes f with the current page header as ! argument. Needed for sweep. */ ! static void ! visit_all_used_page_headers (void (*f) (page_header *ph)) { EMACS_INT i; for (i = 0; i < N_USED_PAGE_LISTS; i++) if (PLH_FIRST (USED_HEAP_PAGES (i))) --- 432,442 ---- /* Visits all pages (page_headers) hooked into the used heap pages list and executes f with the current page header as ! argument. Needed for sweep. Returns number of processed pages. */ ! static EMACS_INT ! visit_all_used_page_headers (EMACS_INT (*f) (page_header *ph)) { + EMACS_INT number_of_pages_processed = 0; EMACS_INT i; for (i = 0; i < N_USED_PAGE_LISTS; i++) if (PLH_FIRST (USED_HEAP_PAGES (i))) *************** *** 446,456 **** while (PH_NEXT (ph)) { page_header *next = PH_NEXT (ph); /* in case f removes the page */ ! f (ph); ph = next; } ! f (ph); } } --- 445,456 ---- while (PH_NEXT (ph)) { page_header *next = PH_NEXT (ph); /* in case f removes the page */ ! number_of_pages_processed += f (ph); ph = next; } ! number_of_pages_processed += f (ph); } + return number_of_pages_processed; } *************** *** 773,783 **** assert (ph && PH_ON_USED_LIST_P (ph)); if (ph) { - #ifdef NEW_GC if (value == BLACK) if (!PH_BLACK_BIT (ph)) PH_BLACK_BIT (ph) = 1; - #endif /* NEW_GC */ SET_BIT (ph, get_mark_bit_index (ptr, ph), value); } } --- 773,781 ---- *************** *** 1140,1148 **** void *real_start; /* determine number of pages the heap should grow */ ! n_pages = needed_pages + (HEAP_SIZE / (PAGE_SIZE * HEAP_GROWTH_DIVISOR)); ! if (n_pages < MIN_HEAP_INCREASE) ! n_pages = MIN_HEAP_INCREASE; /* get the real values */ real_size = (n_pages * PAGE_SIZE) + PAGE_SIZE; --- 1138,1149 ---- void *real_start; /* determine number of pages the heap should grow */ ! if (memory_shortage) ! n_pages = needed_pages; ! else ! n_pages = max (MIN_HEAP_INCREASE, ! needed_pages ! + (HEAP_SIZE / (PAGE_SIZE * HEAP_GROWTH_DIVISOR))); /* get the real values */ real_size = (n_pages * PAGE_SIZE) + PAGE_SIZE; *************** *** 1271,1280 **** { page_list_header *plh = PH_PLH (ph); - #ifdef NEW_GC if (gc_in_progress && PH_PROTECTION_BIT (ph)) ABORT(); /* cleanup: remove memory protection, zero page_header bits. */ - #endif /* not NEW_GC */ #ifdef MEMORY_USAGE_STATS PLH_TOTAL_CELLS (plh) -= PH_CELLS_ON_PAGE (ph); --- 1272,1279 ---- *************** *** 1482,1548 **** free_link *fl = PH_FREE_LIST (ph); while (fl) { - #ifdef NEW_GC SET_BIT (ph, get_mark_bit_index (fl, ph), BLACK); - #else /* not NEW_GC */ - SET_BIT (ph, get_mark_bit_index (fl, ph), 1); - #endif /* not NEW_GC */ fl = NEXT_FREE (fl); } } - /* Finalize a page. You have to tell mc-alloc how to call your - object's finalizer. Therefore, you have to define the macro - MC_ALLOC_CALL_FINALIZER(ptr). This macro should do nothing else - then test if there is a finalizer and call it on the given - argument, which is the heap address of the object. */ - static void - finalize_page (page_header *ph) - { - EMACS_INT heap_space = (EMACS_INT) PH_HEAP_SPACE (ph); - EMACS_INT heap_space_step = PH_CELL_SIZE (ph); - EMACS_INT mark_bit = 0; - EMACS_INT mark_bit_max_index = PH_CELLS_ON_PAGE (ph); - unsigned int bit = 0; - - mark_free_list (ph); - - #ifdef NEW_GC - /* ARRAY_BIT_HACK */ - if (PH_ARRAY_BIT (ph)) - for (mark_bit = 0; mark_bit < mark_bit_max_index; mark_bit++) - { - GET_BIT (bit, ph, mark_bit * N_MARK_BITS); - if (bit) - { - return; - } - } - #endif /* NEW_GC */ - - for (mark_bit = 0; mark_bit < mark_bit_max_index; mark_bit++) - { - GET_BIT (bit, ph, mark_bit * N_MARK_BITS); - #ifdef NEW_GC - if (bit == WHITE) - #else /* not NEW_GC */ - if (bit == 0) - #endif /* not NEW_GC */ - { - EMACS_INT ptr = (heap_space + (heap_space_step * mark_bit)); - MC_ALLOC_CALL_FINALIZER ((void *) ptr); - } - } - } - /* Finalize a page for disksave. XEmacs calls this routine before it dumps the heap image. You have to tell mc-alloc how to call your object's finalizer for disksave. Therefore, you have to define the macro MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE(ptr). This macro should do nothing else then test if there is a finalizer and call it on ! the given argument, which is the heap address of the object. */ ! static void finalize_page_for_disksave (page_header *ph) { EMACS_INT heap_space = (EMACS_INT) PH_HEAP_SPACE (ph); --- 1481,1500 ---- free_link *fl = PH_FREE_LIST (ph); while (fl) { SET_BIT (ph, get_mark_bit_index (fl, ph), BLACK); fl = NEXT_FREE (fl); } } /* Finalize a page for disksave. XEmacs calls this routine before it dumps the heap image. You have to tell mc-alloc how to call your object's finalizer for disksave. Therefore, you have to define the macro MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE(ptr). This macro should do nothing else then test if there is a finalizer and call it on ! the given argument, which is the heap address of the object. ! Returns number of processed pages. */ ! static EMACS_INT finalize_page_for_disksave (page_header *ph) { EMACS_INT heap_space = (EMACS_INT) PH_HEAP_SPACE (ph); *************** *** 1555,1583 **** EMACS_INT ptr = (heap_space + (heap_space_step * mark_bit)); MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE ((void *) ptr); } } ! /* Finalizes the heap. */ ! void ! mc_finalize (void) ! { ! visit_all_used_page_headers (finalize_page); ! } ! ! ! /* Finalizes the heap for disksave. */ ! void mc_finalize_for_disksave (void) { ! visit_all_used_page_headers (finalize_page_for_disksave); } ! /* Sweeps a page: all the non-marked cells are freed. If the page is empty ! in the end, it is removed. If some cells are free, it is moved to the ! front of its page header list. Full pages stay where they are. */ ! static void sweep_page (page_header *ph) { Rawbyte *heap_space = (Rawbyte *) PH_HEAP_SPACE (ph); --- 1507,1530 ---- EMACS_INT ptr = (heap_space + (heap_space_step * mark_bit)); MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE ((void *) ptr); } + return 1; } ! /* Finalizes the heap for disksave. Returns number of processed ! pages. */ ! EMACS_INT mc_finalize_for_disksave (void) { ! return visit_all_used_page_headers (finalize_page_for_disksave); } ! /* Sweeps a page: all the non-marked cells are freed. If the page is ! empty in the end, it is removed. If some cells are free, it is ! moved to the front of its page header list. Full pages stay where ! they are. Returns number of processed pages.*/ ! static EMACS_INT sweep_page (page_header *ph) { Rawbyte *heap_space = (Rawbyte *) PH_HEAP_SPACE (ph); *************** *** 1588,1594 **** mark_free_list (ph); - #ifdef NEW_GC /* ARRAY_BIT_HACK */ if (PH_ARRAY_BIT (ph)) for (mark_bit = 0; mark_bit < mark_bit_max_index; mark_bit++) --- 1535,1540 ---- *************** *** 1598,1620 **** { zero_mark_bits (ph); PH_BLACK_BIT (ph) = 0; ! return; } } - #endif /* NEW_GC */ for (mark_bit = 0; mark_bit < mark_bit_max_index; mark_bit++) { GET_BIT (bit, ph, mark_bit * N_MARK_BITS); - #ifdef NEW_GC if (bit == WHITE) - #else /* not NEW_GC */ - if (bit == 0) - #endif /* not NEW_GC */ { - #ifdef NEW_GC GC_STAT_FREED; - #endif /* NEW_GC */ remove_cell (heap_space + (heap_space_step * mark_bit), ph); } } --- 1544,1559 ---- { zero_mark_bits (ph); PH_BLACK_BIT (ph) = 0; ! return 1; } } for (mark_bit = 0; mark_bit < mark_bit_max_index; mark_bit++) { GET_BIT (bit, ph, mark_bit * N_MARK_BITS); if (bit == WHITE) { GC_STAT_FREED; remove_cell (heap_space + (heap_space_step * mark_bit), ph); } } *************** *** 1624,1668 **** remove_page_from_used_list (ph); else if (PH_CELLS_USED (ph) < PH_CELLS_ON_PAGE (ph)) move_page_header_to_front (ph); } ! /* Sweeps the heap. */ ! void mc_sweep (void) { ! visit_all_used_page_headers (sweep_page); } /* Frees the cell pointed to by ptr. */ void ! mc_free (void *ptr) { ! page_header *ph; ! ! #ifdef NEW_GC ! /* Do not allow manual freeing while a gc is running. Data is going ! to be freed next gc cycle. */ ! if (write_barrier_enabled || gc_in_progress) ! return; ! #endif /* NEW_GC */ ! ! ph = get_page_header (ptr); ! assert (ph); ! assert (PH_PLH (ph)); ! assert (PLH_LIST_TYPE (PH_PLH (ph)) != FREE_LIST); ! ! #ifdef NEW_GC ! if (PH_ON_USED_LIST_P (ph)) ! SET_BIT (ph, get_mark_bit_index (ptr, ph), WHITE); ! #endif /* NEW_GC */ ! remove_cell (ptr, ph); ! ! if (PH_CELLS_USED (ph) == 0) ! remove_page_from_used_list (ph); ! else if (PH_CELLS_USED (ph) < PH_CELLS_ON_PAGE (ph)) ! move_page_header_to_front (ph); } --- 1563,1587 ---- remove_page_from_used_list (ph); else if (PH_CELLS_USED (ph) < PH_CELLS_ON_PAGE (ph)) move_page_header_to_front (ph); + + return 1; } ! /* Sweeps the heap. Returns number of processed pages. */ ! EMACS_INT mc_sweep (void) { ! return visit_all_used_page_headers (sweep_page); } /* Frees the cell pointed to by ptr. */ void ! mc_free (void *UNUSED (ptr)) { ! /* Manual frees are not allowed with asynchronous finalization */ ! return; } *************** *** 1871,1877 **** } - #ifdef NEW_GC /*--- incremental garbage collector ----------------------------------*/ /* access dirty bit of page header */ --- 1790,1795 ---- *************** *** 1955,1962 **** /* Protect the heap page of given page header ph if black objects are ! on the page. */ ! static void protect_heap_page (page_header *ph) { if (PH_BLACK_BIT (ph)) --- 1873,1880 ---- /* Protect the heap page of given page header ph if black objects are ! on the page. Returns number of processed pages. */ ! static EMACS_INT protect_heap_page (page_header *ph) { if (PH_BLACK_BIT (ph)) *************** *** 1965,1984 **** EMACS_INT heap_space_size = PH_N_PAGES (ph) * PAGE_SIZE; vdb_protect ((void *) heap_space, heap_space_size); PH_PROTECTION_BIT (ph) = 1; } } ! /* Protect all heap pages with black objects. */ ! void protect_heap_pages (void) { ! visit_all_used_page_headers (protect_heap_page); } /* Remove protection (if there) of heap page of given page header ! ph. */ ! static void unprotect_heap_page (page_header *ph) { if (PH_PROTECTION_BIT (ph)) --- 1883,1905 ---- EMACS_INT heap_space_size = PH_N_PAGES (ph) * PAGE_SIZE; vdb_protect ((void *) heap_space, heap_space_size); PH_PROTECTION_BIT (ph) = 1; + return 1; } + return 0; } ! /* Protect all heap pages with black objects. Returns number of ! processed pages.*/ ! EMACS_INT protect_heap_pages (void) { ! return visit_all_used_page_headers (protect_heap_page); } /* Remove protection (if there) of heap page of given page header ! ph. Returns number of processed pages. */ ! static EMACS_INT unprotect_heap_page (page_header *ph) { if (PH_PROTECTION_BIT (ph)) *************** *** 1987,2000 **** EMACS_INT heap_space_size = PH_N_PAGES (ph) * PAGE_SIZE; vdb_unprotect (heap_space, heap_space_size); PH_PROTECTION_BIT (ph) = 0; } } ! /* Remove protection for all heap pages which are protected. */ ! void unprotect_heap_pages (void) { ! visit_all_used_page_headers (unprotect_heap_page); } /* Remove protection and mark page dirty. */ --- 1908,1924 ---- EMACS_INT heap_space_size = PH_N_PAGES (ph) * PAGE_SIZE; vdb_unprotect (heap_space, heap_space_size); PH_PROTECTION_BIT (ph) = 0; + return 1; } + return 0; } ! /* Remove protection for all heap pages which are protected. Returns ! number of processed pages. */ ! EMACS_INT unprotect_heap_pages (void) { ! return visit_all_used_page_headers (unprotect_heap_page); } /* Remove protection and mark page dirty. */ *************** *** 2062,2066 **** page_header *ph = get_page_header_internal (ptr); return (ph && PH_ON_USED_LIST_P (ph)); } - - #endif /* NEW_GC */ --- 1986,1988 ---- diff -c 'xemacs-21.5.25/src/mc-alloc.h' 'xemacs-21.5.26/src/mc-alloc.h' Index: ./src/mc-alloc.h *** ./src/mc-alloc.h Fri Nov 25 10:42:05 2005 --- ./src/mc-alloc.h Mon Mar 27 00:24:27 2006 *************** *** 27,32 **** --- 27,34 ---- BEGIN_C_DECLS + /* Set to 1 if memory becomes short. */ + extern EMACS_INT memory_shortage; /* Internal Allocator Functions: */ *************** *** 72,78 **** /* Garbage collection related functions and macros: */ - #ifdef NEW_GC enum mark_bit_colors { WHITE = 0, --- 74,79 ---- *************** *** 103,133 **** #define MARKED_WHITE_P(ptr) (get_mark_bit (ptr) == WHITE) #define MARKED_GREY_P(ptr) (get_mark_bit (ptr) == GREY) #define MARKED_BLACK_P(ptr) (get_mark_bit (ptr) == BLACK) - #else /* not NEW_GC */ - /* Set the mark bit of the object pointed to by ptr to value.*/ - void set_mark_bit (void *ptr, EMACS_INT value); - - /* Return the mark bit of the object pointed to by ptr. */ - EMACS_INT get_mark_bit (void *ptr); - - /* mark bit macros */ - /* Returns true if the mark bit of the object pointed to by ptr is set. */ - #define MARKED_P(ptr) (get_mark_bit (ptr) == 1) - - /* Marks the object pointed to by ptr (sets the mark bit to 1). */ - #define MARK(ptr) set_mark_bit (ptr, 1) - - /* Unmarks the object pointed to by ptr (sets the mark bit to 0). */ - #define UNMARK(ptr) set_mark_bit (ptr, 0) - #endif /* not NEW_GC */ /* The finalizer of every not marked object is called. The macro MC_ALLOC_CALL_FINALIZER has to be defined and call the finalizer of ! the object. */ ! void mc_finalize (void); ! /* All not marked objects of the used heap are freed. */ ! void mc_sweep (void); --- 104,118 ---- #define MARKED_WHITE_P(ptr) (get_mark_bit (ptr) == WHITE) #define MARKED_GREY_P(ptr) (get_mark_bit (ptr) == GREY) #define MARKED_BLACK_P(ptr) (get_mark_bit (ptr) == BLACK) /* The finalizer of every not marked object is called. The macro MC_ALLOC_CALL_FINALIZER has to be defined and call the finalizer of ! the object. Returns number of processed pages. */ ! EMACS_INT mc_finalize (void); ! /* All not marked objects of the used heap are freed. Returns number ! of processed pages. */ ! EMACS_INT mc_sweep (void); *************** *** 135,142 **** /* The finalizer for disksave of every object is called to shrink the dump image. The macro MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE has to ! be defined and call the finalizer for disksave of the object. */ ! void mc_finalize_for_disksave (void); --- 120,128 ---- /* The finalizer for disksave of every object is called to shrink the dump image. The macro MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE has to ! be defined and call the finalizer for disksave of the object. ! Returns number of processed pages. */ ! EMACS_INT mc_finalize_for_disksave (void); *************** *** 150,156 **** #endif /* MEMORY_USAGE_STATS */ - #ifdef NEW_GC /* Incremental Garbage Collector / Write Barrier Support: */ /* Return the PAGESIZE the allocator uses. Generally equals to the --- 136,141 ---- *************** *** 160,171 **** /* Is the fault at ptr on a protected page? */ EMACS_INT fault_on_protected_page (void *ptr); ! /* Remove protection (if there) of heap page of given page header ! ph. */ ! void protect_heap_pages (void); ! ! /* Remove protection for all heap pages which are protected. */ ! void unprotect_heap_pages (void); /* Remove protection and mark page dirty. */ void unprotect_page_and_mark_dirty (void *ptr); --- 145,157 ---- /* Is the fault at ptr on a protected page? */ EMACS_INT fault_on_protected_page (void *ptr); ! /* Remove protection (if there) of heap page of given page header ph. ! Returns number of processed pages. */ ! EMACS_INT protect_heap_pages (void); ! ! /* Remove protection for all heap pages which are protected. Returns ! number of processed pages. */ ! EMACS_INT unprotect_heap_pages (void); /* Remove protection and mark page dirty. */ void unprotect_page_and_mark_dirty (void *ptr); *************** *** 179,186 **** /* Only for debugging---not used anywhere in the sources. */ EMACS_INT object_on_heap_p (void *ptr); - - #endif /* NEW_GC */ END_C_DECLS --- 165,170 ---- diff -c 'xemacs-21.5.25/src/objects-x.c' 'xemacs-21.5.26/src/objects-x.c' Index: ./src/objects-x.c *** ./src/objects-x.c Sat Jan 21 02:50:46 2006 --- ./src/objects-x.c Fri Mar 17 23:30:45 2006 *************** *** 794,800 **** struct device *d = XDEVICE (f->device); Display *dpy = DEVICE_X_DISPLAY (d); Extbyte *nameext; - char* xlfd; /* #### restructure this so that we return a valid truename at the end, and otherwise only return when we return something desperate that --- 794,799 ---- *************** *** 827,835 **** if (NILP (FONT_INSTANCE_TRUENAME (f)) && FONT_INSTANCE_X_FONT (f)) { ! nameext = &xlfd[0]; ! LISP_STRING_TO_EXTERNAL (f->name, nameext, Qx_font_name_encoding); ! FONT_INSTANCE_TRUENAME (f) = x_font_truename (dpy, nameext, FONT_INSTANCE_X_FONT (f)); } --- 826,832 ---- if (NILP (FONT_INSTANCE_TRUENAME (f)) && FONT_INSTANCE_X_FONT (f)) { ! nameext = NEW_LISP_STRING_TO_EXTERNAL (f->name, Qx_font_name_encoding); FONT_INSTANCE_TRUENAME (f) = x_font_truename (dpy, nameext, FONT_INSTANCE_X_FONT (f)); } diff -c 'xemacs-21.5.25/src/opaque.c' 'xemacs-21.5.26/src/opaque.c' Index: ./src/opaque.c *** ./src/opaque.c Mon Oct 24 19:07:39 2005 --- ./src/opaque.c Tue Feb 28 01:29:28 2006 *************** *** 38,46 **** #include "lisp.h" #include "opaque.h" ! #ifndef MC_ALLOC Lisp_Object Vopaque_ptr_free_list; ! #endif /* not MC_ALLOC */ /* Should never, ever be called. (except by an external debugger) */ static void --- 38,46 ---- #include "lisp.h" #include "opaque.h" ! #ifndef NEW_GC Lisp_Object Vopaque_ptr_free_list; ! #endif /* not NEW_GC */ /* Should never, ever be called. (except by an external debugger) */ static void *************** *** 162,174 **** Lisp_Object make_opaque_ptr (void *val) { ! #ifdef MC_ALLOC Lisp_Object res = wrap_pointer_1 (alloc_lrecord_type (Lisp_Opaque_Ptr, &lrecord_opaque_ptr)); ! #else /* not MC_ALLOC */ Lisp_Object res = alloc_managed_lcrecord (Vopaque_ptr_free_list); ! #endif /* not MC_ALLOC */ set_opaque_ptr (res, val); return res; } --- 162,174 ---- Lisp_Object make_opaque_ptr (void *val) { ! #ifdef NEW_GC Lisp_Object res = wrap_pointer_1 (alloc_lrecord_type (Lisp_Opaque_Ptr, &lrecord_opaque_ptr)); ! #else /* not NEW_GC */ Lisp_Object res = alloc_managed_lcrecord (Vopaque_ptr_free_list); ! #endif /* not NEW_GC */ set_opaque_ptr (res, val); return res; } *************** *** 179,192 **** void free_opaque_ptr (Lisp_Object ptr) { ! #ifdef MC_ALLOC free_lrecord (ptr); ! #else /* not MC_ALLOC */ free_managed_lcrecord (Vopaque_ptr_free_list, ptr); ! #endif /* not MC_ALLOC */ } ! #ifndef MC_ALLOC void reinit_opaque_early (void) { --- 179,192 ---- void free_opaque_ptr (Lisp_Object ptr) { ! #ifdef NEW_GC free_lrecord (ptr); ! #else /* not NEW_GC */ free_managed_lcrecord (Vopaque_ptr_free_list, ptr); ! #endif /* not NEW_GC */ } ! #ifndef NEW_GC void reinit_opaque_early (void) { *************** *** 194,200 **** &lrecord_opaque_ptr); staticpro_nodump (&Vopaque_ptr_free_list); } ! #endif /* not MC_ALLOC */ void init_opaque_once_early (void) --- 194,200 ---- &lrecord_opaque_ptr); staticpro_nodump (&Vopaque_ptr_free_list); } ! #endif /* not NEW_GC */ void init_opaque_once_early (void) *************** *** 202,208 **** INIT_LRECORD_IMPLEMENTATION (opaque); INIT_LRECORD_IMPLEMENTATION (opaque_ptr); ! #ifndef MC_ALLOC reinit_opaque_early (); ! #endif /* not MC_ALLOC */ } --- 202,208 ---- INIT_LRECORD_IMPLEMENTATION (opaque); INIT_LRECORD_IMPLEMENTATION (opaque_ptr); ! #ifndef NEW_GC reinit_opaque_early (); ! #endif /* not NEW_GC */ } diff -c 'xemacs-21.5.25/src/print.c' 'xemacs-21.5.26/src/print.c' Index: ./src/print.c *** ./src/print.c Fri Nov 25 10:42:06 2005 --- ./src/print.c Tue Feb 28 01:29:28 2006 *************** *** 1458,1476 **** if (print_readably) printing_unreadable_object ("#<%s 0x%x>", ! #ifdef MC_ALLOC LHEADER_IMPLEMENTATION (header)->name, ! #else /* not MC_ALLOC */ LHEADER_IMPLEMENTATION (&header->lheader)->name, ! #endif /* not MC_ALLOC */ header->uid); write_fmt_string (printcharfun, "#<%s 0x%x>", ! #ifdef MC_ALLOC LHEADER_IMPLEMENTATION (header)->name, ! #else /* not MC_ALLOC */ LHEADER_IMPLEMENTATION (&header->lheader)->name, ! #endif /* not MC_ALLOC */ header->uid); } --- 1458,1476 ---- if (print_readably) printing_unreadable_object ("#<%s 0x%x>", ! #ifdef NEW_GC LHEADER_IMPLEMENTATION (header)->name, ! #else /* not NEW_GC */ LHEADER_IMPLEMENTATION (&header->lheader)->name, ! #endif /* not NEW_GC */ header->uid); write_fmt_string (printcharfun, "#<%s 0x%x>", ! #ifdef NEW_GC LHEADER_IMPLEMENTATION (header)->name, ! #else /* not NEW_GC */ LHEADER_IMPLEMENTATION (&header->lheader)->name, ! #endif /* not NEW_GC */ header->uid); } *************** *** 1692,1698 **** } } ! #ifndef MC_ALLOC if (lheader->type == lrecord_type_free) { printing_major_badness (printcharfun, "freed lrecord", 0, --- 1692,1698 ---- } } ! #ifndef NEW_GC if (lheader->type == lrecord_type_free) { printing_major_badness (printcharfun, "freed lrecord", 0, *************** *** 1705,1711 **** lheader, BADNESS_NO_TYPE); break; } ! #endif /* not MC_ALLOC */ else if ((int) (lheader->type) >= lrecord_type_count) { printing_major_badness (printcharfun, "illegal lrecord type", --- 1705,1711 ---- lheader, BADNESS_NO_TYPE); break; } ! #endif /* not NEW_GC */ else if ((int) (lheader->type) >= lrecord_type_count) { printing_major_badness (printcharfun, "illegal lrecord type", *************** *** 2222,2240 **** debug_out ("<< bad object type=%d 0x%lx>>", header->type, (EMACS_INT) header); else ! #ifdef MC_ALLOC debug_out ("#<%s addr=0x%lx uid=0x%lx>", LHEADER_IMPLEMENTATION (header)->name, (EMACS_INT) header, (EMACS_INT) ((struct lrecord_header *) header)->uid); ! #else /* not MC_ALLOC */ debug_out ("#<%s addr=0x%lx uid=0x%lx>", LHEADER_IMPLEMENTATION (header)->name, (EMACS_INT) header, (EMACS_INT) (LHEADER_IMPLEMENTATION (header)->basic_p ? ((struct lrecord_header *) header)->uid : ((struct old_lcrecord_header *) header)->uid)); ! #endif /* not MC_ALLOC */ } inhibit_non_essential_conversion_operations = 0; --- 2222,2240 ---- debug_out ("<< bad object type=%d 0x%lx>>", header->type, (EMACS_INT) header); else ! #ifdef NEW_GC debug_out ("#<%s addr=0x%lx uid=0x%lx>", LHEADER_IMPLEMENTATION (header)->name, (EMACS_INT) header, (EMACS_INT) ((struct lrecord_header *) header)->uid); ! #else /* not NEW_GC */ debug_out ("#<%s addr=0x%lx uid=0x%lx>", LHEADER_IMPLEMENTATION (header)->name, (EMACS_INT) header, (EMACS_INT) (LHEADER_IMPLEMENTATION (header)->basic_p ? ((struct lrecord_header *) header)->uid : ((struct old_lcrecord_header *) header)->uid)); ! #endif /* not NEW_GC */ } inhibit_non_essential_conversion_operations = 0; diff -c 'xemacs-21.5.25/src/profile.h' 'xemacs-21.5.26/src/profile.h' Index: ./src/profile.h *** ./src/profile.h Tue Oct 25 20:16:27 2005 --- ./src/profile.h Wed Mar 15 04:31:43 2006 *************** *** 113,118 **** --- 113,119 ---- RETURN_EXIT_PROFILING (tag, Lisp_Object, expr) #define RETURN_UNGCPRO_EXIT_PROFILING(tag, expr) \ + do \ { \ Lisp_Object ret_ungc_val = (expr); \ UNGCPRO; \ diff -c 'xemacs-21.5.25/src/ralloc.c' 'xemacs-21.5.26/src/ralloc.c' Index: ./src/ralloc.c *** ./src/ralloc.c Tue Oct 25 20:16:27 2005 --- ./src/ralloc.c Tue Feb 28 01:29:28 2006 *************** *** 61,69 **** #include "getpagesize.h" #include ! #ifndef MC_ALLOC void refill_memory_reserve (void); ! #endif /* not MC_ALLOC */ #else /* Not emacs. */ --- 61,69 ---- #include "getpagesize.h" #include ! #ifndef NEW_GC void refill_memory_reserve (void); ! #endif /* not NEW_GC */ #else /* Not emacs. */ *************** *** 986,994 **** *ptr = 0; #ifdef emacs ! #ifndef MC_ALLOC refill_memory_reserve (); ! #endif /* not MC_ALLOC */ #endif } --- 986,994 ---- *ptr = 0; #ifdef emacs ! #ifndef NEW_GC refill_memory_reserve (); ! #endif /* not NEW_GC */ #endif } diff -c 'xemacs-21.5.25/src/regex.c' 'xemacs-21.5.26/src/regex.c' Index: ./src/regex.c *** ./src/regex.c Wed Mar 9 13:59:31 2005 --- ./src/regex.c Sat Mar 25 20:27:49 2006 *************** *** 1314,1320 **** when matching. If this number is exceeded, we allocate more space, so it is not a hard limit. */ #ifndef INIT_FAILURE_ALLOC ! #define INIT_FAILURE_ALLOC 5 #endif /* Roughly the maximum number of failure points on the stack. Would be --- 1314,1320 ---- when matching. If this number is exceeded, we allocate more space, so it is not a hard limit. */ #ifndef INIT_FAILURE_ALLOC ! #define INIT_FAILURE_ALLOC 20 #endif /* Roughly the maximum number of failure points on the stack. Would be *************** *** 1324,1332 **** #if defined (MATCH_MAY_ALLOCATE) /* 4400 was enough to cause a crash on Alpha OSF/1, whose default stack limit is 2mb. */ ! int re_max_failures = 20000; #else ! int re_max_failures = 2000; #endif union fail_stack_elt --- 1324,1332 ---- #if defined (MATCH_MAY_ALLOCATE) /* 4400 was enough to cause a crash on Alpha OSF/1, whose default stack limit is 2mb. */ ! int re_max_failures = 40000; #else ! int re_max_failures = 4000; #endif union fail_stack_elt diff -c 'xemacs-21.5.25/src/sound.c' 'xemacs-21.5.26/src/sound.c' Index: ./src/sound.c *** ./src/sound.c Wed Nov 16 16:22:46 2005 --- ./src/sound.c Tue Mar 28 02:40:59 2006 *************** *** 70,81 **** --- 70,94 ---- #define USED_IF_HAVE_ANY(decl) UNUSED (decl) #endif + #ifdef HAVE_ALSA_SOUND + extern int alsa_play_sound_file (const Extbyte *file, int vol); + extern int alsa_play_sound_data (const Binbyte *data, int length, int vol); + # define DEVICE_CONNECTED_TO_ALSA_P(x) 1 /* #### better check */ + #endif + #ifdef HAVE_ESD_SOUND extern int esd_play_sound_file (Extbyte *file, int vol); extern int esd_play_sound_data (Binbyte *data, size_t length, int vol); # define DEVICE_CONNECTED_TO_ESD_P(x) 1 /* #### better check */ #endif + #ifdef HAVE_NAS_SOUND + extern int nas_play_sound_file (Extbyte *name, int volume); + extern int nas_play_sound_data (Binbyte *data, int length, int volume); + extern int nas_wait_for_sounds (void); + extern Extbyte *nas_init_play (Display *); + #endif + Fixnum bell_volume; Fixnum bell_inhibit_time; Lisp_Object Vsound_alist; *************** *** 84,97 **** Lisp_Object Q_volume, Q_pitch, Q_duration, Q_sound; Lisp_Object Qsound_error; - - #ifdef HAVE_NAS_SOUND - extern int nas_play_sound_file (Extbyte *name, int volume); - extern int nas_play_sound_data (Binbyte *data, int length, int volume); - extern int nas_wait_for_sounds (void); - extern Extbyte *nas_init_play (Display *); - #endif - DOESNT_RETURN report_sound_error (const Ascbyte *string, Lisp_Object data) { --- 97,102 ---- *************** *** 110,117 **** { /* This function can call lisp */ int vol; ! #if defined (HAVE_NATIVE_SOUND) || defined (HAVE_NAS_SOUND) \ ! || defined (HAVE_ESD_SOUND) struct device *d = decode_device (device); #endif struct gcpro gcpro1; --- 115,122 ---- { /* This function can call lisp */ int vol; ! #if defined (HAVE_NATIVE_SOUND) || defined (HAVE_ALSA_SOUND) || \ ! defined (HAVE_NAS_SOUND) || defined (HAVE_ESD_SOUND) struct device *d = decode_device (device); #endif struct gcpro gcpro1; *************** *** 148,153 **** --- 153,170 ---- } UNGCPRO; + #ifdef HAVE_ALSA_SOUND + if (DEVICE_CONNECTED_TO_ALSA_P (d)) + { + Extbyte *fileext; + + LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name); + /* #### ALSA code should allow specification of a device. */ + if (alsa_play_sound_file (fileext, vol)) + return Qnil; + } + #endif + #ifdef HAVE_NAS_SOUND if (DEVICE_CONNECTED_TO_NAS_P (d)) { *************** *** 355,364 **** pit = (INT_OR_FLOATP (pitch) ? (int) XFLOATINT (pitch) : -1); dur = (INT_OR_FLOATP (duration) ? (int) XFLOATINT (duration) : -1); ! /* If the sound is a string, and we're connected to Nas, do that. ! Else if the sound is a string, and we're on console, play it natively. ! Else just beep. */ #ifdef HAVE_NAS_SOUND if (DEVICE_CONNECTED_TO_NAS_P (d) && STRINGP (sound)) { --- 372,395 ---- pit = (INT_OR_FLOATP (pitch) ? (int) XFLOATINT (pitch) : -1); dur = (INT_OR_FLOATP (duration) ? (int) XFLOATINT (duration) : -1); ! /* If the sound is a string, and we're connected to ALSA, NAS, or ESD, do ! that. Else if the sound is a string, and we're on console, play it ! natively. Else just beep. */ + #ifdef HAVE_ALSA_SOUND + if (DEVICE_CONNECTED_TO_ALSA_P (d) && STRINGP (sound)) + { + Binbyte *soundext; + Bytecount soundextlen; + + TO_EXTERNAL_FORMAT (LISP_STRING, sound, + ALLOCA, (soundext, soundextlen), + Qbinary); + if (alsa_play_sound_data (soundext, soundextlen, vol)) + return Qnil; + } + #endif /* HAVE_ALSA_SOUND */ + #ifdef HAVE_NAS_SOUND if (DEVICE_CONNECTED_TO_NAS_P (d) && STRINGP (sound)) { *************** *** 423,428 **** --- 454,463 ---- */ (USED_IF_HAVE_NATIVE_OR_NAS (device))) { + #ifdef HAVE_ALSA_SOUND + if (DEVICE_CONNECTED_TO_ALSA_P (decode_device (device))) + return Qt; + #endif #ifdef HAVE_NAS_SOUND if (DEVICE_CONNECTED_TO_NAS_P (decode_device (device))) return Qt; *************** *** 654,659 **** --- 689,697 ---- void vars_of_sound (void) { + #ifdef HAVE_ALSA_SOUND + Fprovide (intern ("alsa-sound")); + #endif #ifdef HAVE_NATIVE_SOUND Fprovide (intern ("native-sound")); #endif diff -c 'xemacs-21.5.25/src/specifier.c' 'xemacs-21.5.26/src/specifier.c' Index: ./src/specifier.c *** ./src/specifier.c Fri Nov 25 10:42:06 2005 --- ./src/specifier.c Tue Feb 28 01:29:28 2006 *************** *** 295,300 **** --- 295,301 ---- write_fmt_string (printcharfun, " 0x%x>", sp->header.uid); } + #ifndef NEW_GC static void finalize_specifier (void *header, int for_disksave) { *************** *** 302,315 **** /* don't be snafued by the disksave finalization. */ if (!for_disksave && !GHOST_SPECIFIER_P(sp) && sp->caching) { - #ifdef NEW_GC - mc_free (sp->caching); - #else /* not NEW_GC */ xfree (sp->caching, struct specifier_caching *); - #endif /* not NEW_GC */ sp->caching = 0; } } static int specifier_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) --- 303,313 ---- /* don't be snafued by the disksave finalization. */ if (!for_disksave && !GHOST_SPECIFIER_P(sp) && sp->caching) { xfree (sp->caching, struct specifier_caching *); sp->caching = 0; } } + #endif /* not NEW_GC */ static int specifier_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) *************** *** 438,443 **** --- 436,450 ---- 0, specifier_empty_extra_description_1 }; + #ifdef NEW_GC + DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier, + 1, /*dumpable-flag*/ + mark_specifier, print_specifier, + 0, specifier_equal, specifier_hash, + specifier_description, + sizeof_specifier, + Lisp_Specifier); + #else /* not NEW_GC */ DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier, 1, /*dumpable-flag*/ mark_specifier, print_specifier, *************** *** 446,451 **** --- 453,459 ---- specifier_description, sizeof_specifier, Lisp_Specifier); + #endif /* not NEW_GC */ /************************************************************************/ /* Creating specifiers */ diff -c 'xemacs-21.5.25/src/symbols.c' 'xemacs-21.5.26/src/symbols.c' Index: ./src/symbols.c *** ./src/symbols.c Tue Oct 25 17:32:49 2005 --- ./src/symbols.c Tue Feb 28 01:29:28 2006 *************** *** 3252,3258 **** Lisp_Object Qnull_pointer; #endif ! #ifndef MC_ALLOC /* some losing systems can't have static vars at function scope... */ static const struct symbol_value_magic guts_of_unbound_marker = { /* struct symbol_value_magic */ --- 3252,3258 ---- Lisp_Object Qnull_pointer; #endif ! #ifndef NEW_GC /* some losing systems can't have static vars at function scope... */ static const struct symbol_value_magic guts_of_unbound_marker = { /* struct symbol_value_magic */ *************** *** 3270,3276 **** 0, /* value */ SYMVAL_UNBOUND_MARKER }; ! #endif /* not MC_ALLOC */ void init_symbols_once_early (void) --- 3270,3276 ---- 0, /* value */ SYMVAL_UNBOUND_MARKER }; ! #endif /* not NEW_GC */ void init_symbols_once_early (void) *************** *** 3302,3308 **** { /* Required to get around a GCC syntax error on certain architectures */ ! #ifdef MC_ALLOC struct symbol_value_magic *tem = (struct symbol_value_magic *) mc_alloc (sizeof (struct symbol_value_magic)); MARK_LRECORD_AS_LISP_READONLY (tem); --- 3302,3308 ---- { /* Required to get around a GCC syntax error on certain architectures */ ! #ifdef NEW_GC struct symbol_value_magic *tem = (struct symbol_value_magic *) mc_alloc (sizeof (struct symbol_value_magic)); MARK_LRECORD_AS_LISP_READONLY (tem); *************** *** 3315,3323 **** inc_lrecord_stats (sizeof (struct symbol_value_magic), (const struct lrecord_header *) tem); #endif /* ALLOC_TYPE_STATS */ ! #else /* not MC_ALLOC */ const struct symbol_value_magic *tem = &guts_of_unbound_marker; ! #endif /* not MC_ALLOC */ Qunbound = wrap_symbol_value_magic (tem); } --- 3315,3323 ---- inc_lrecord_stats (sizeof (struct symbol_value_magic), (const struct lrecord_header *) tem); #endif /* ALLOC_TYPE_STATS */ ! #else /* not NEW_GC */ const struct symbol_value_magic *tem = &guts_of_unbound_marker; ! #endif /* not NEW_GC */ Qunbound = wrap_symbol_value_magic (tem); } *************** *** 3454,3460 **** #endif #ifdef HAVE_SHLIB ! #ifndef MC_ALLOC /* * If we are not in a pure undumped Emacs, we need to make a duplicate of * the subr. This is because the only time this function will be called --- 3454,3460 ---- #endif #ifdef HAVE_SHLIB ! #ifndef NEW_GC /* * If we are not in a pure undumped Emacs, we need to make a duplicate of * the subr. This is because the only time this function will be called *************** *** 3514,3520 **** subr = newsubr; \ } \ } while (0) ! #else /* MC_ALLOC */ /* * If we have the new allocator enabled, we do not need to make a * duplicate of the subr. The new allocator already does allocate all --- 3514,3520 ---- subr = newsubr; \ } \ } while (0) ! #else /* NEW_GC */ /* * If we have the new allocator enabled, we do not need to make a * duplicate of the subr. The new allocator already does allocate all *************** *** 3552,3558 **** signal_ferror (Qdll_error, "Attempt to redefine %s", subr_name (subr)); \ } \ } while (0) ! #endif /* MC_ALLOC */ #else /* ! HAVE_SHLIB */ #define check_module_subr(subr) #endif --- 3552,3558 ---- signal_ferror (Qdll_error, "Attempt to redefine %s", subr_name (subr)); \ } \ } while (0) ! #endif /* NEW_GC */ #else /* ! HAVE_SHLIB */ #define check_module_subr(subr) #endif diff -c 'xemacs-21.5.25/src/symeval.h' 'xemacs-21.5.26/src/symeval.h' Index: ./src/symeval.h *** ./src/symeval.h Tue Oct 25 17:32:49 2005 --- ./src/symeval.h Tue Feb 28 01:29:29 2006 *************** *** 277,283 **** DEFUN ("name, Fname, ...); // at top level in foo.c DEFSUBR (Fname); // in syms_of_foo(); */ ! #ifdef MC_ALLOC MODULE_API void defsubr (Lisp_Subr *); #define DEFSUBR_MC_ALLOC(Fname) \ S##Fname= (struct Lisp_Subr *) mc_alloc (sizeof (struct Lisp_Subr)); \ --- 277,283 ---- DEFUN ("name, Fname, ...); // at top level in foo.c DEFSUBR (Fname); // in syms_of_foo(); */ ! #ifdef NEW_GC MODULE_API void defsubr (Lisp_Subr *); #define DEFSUBR_MC_ALLOC(Fname) \ S##Fname= (struct Lisp_Subr *) mc_alloc (sizeof (struct Lisp_Subr)); \ *************** *** 309,315 **** defsubr_macro (S##Fname); \ } while (0) ! #else /* not MC_ALLOC */ /* To define a Lisp primitive function using a C function `Fname', do this: DEFUN ("name, Fname, ...); // at top level in foo.c DEFSUBR (Fname); // in syms_of_foo(); --- 309,315 ---- defsubr_macro (S##Fname); \ } while (0) ! #else /* not NEW_GC */ /* To define a Lisp primitive function using a C function `Fname', do this: DEFUN ("name, Fname, ...); // at top level in foo.c DEFSUBR (Fname); // in syms_of_foo(); *************** *** 323,329 **** */ MODULE_API void defsubr_macro (Lisp_Subr *); #define DEFSUBR_MACRO(Fname) defsubr_macro (&S##Fname) ! #endif /* not MC_ALLOC */ MODULE_API void defsymbol_massage_name (Lisp_Object *location, const char *name); --- 323,329 ---- */ MODULE_API void defsubr_macro (Lisp_Subr *); #define DEFSUBR_MACRO(Fname) defsubr_macro (&S##Fname) ! #endif /* not NEW_GC */ MODULE_API void defsymbol_massage_name (Lisp_Object *location, const char *name); *************** *** 396,402 **** MODULE_API void defvar_magic (const char *symbol_name, const struct symbol_value_forward *magic); ! #ifdef MC_ALLOC #define DEFVAR_SYMVAL_FWD(lname, c_location, forward_type, magic_fun) \ do \ { \ --- 396,402 ---- MODULE_API void defvar_magic (const char *symbol_name, const struct symbol_value_forward *magic); ! #ifdef NEW_GC #define DEFVAR_SYMVAL_FWD(lname, c_location, forward_type, magic_fun) \ do \ { \ *************** *** 413,419 **** \ defvar_magic ((lname), I_hate_C); \ } while (0) ! #else /* not MC_ALLOC */ #define DEFVAR_SYMVAL_FWD(lname, c_location, forward_type, magicfun) \ do \ { \ --- 413,419 ---- \ defvar_magic ((lname), I_hate_C); \ } while (0) ! #else /* not NEW_GC */ #define DEFVAR_SYMVAL_FWD(lname, c_location, forward_type, magicfun) \ do \ { \ *************** *** 439,445 **** }; \ defvar_magic ((lname), &I_hate_C); \ } while (0) ! #endif /* not MC_ALLOC */ #define DEFVAR_SYMVAL_FWD_INT(lname, c_location, forward_type, magicfun) \ do \ { \ --- 439,445 ---- }; \ defvar_magic ((lname), &I_hate_C); \ } while (0) ! #endif /* not NEW_GC */ #define DEFVAR_SYMVAL_FWD_INT(lname, c_location, forward_type, magicfun) \ do \ { \ diff -c 'xemacs-21.5.25/src/symsinit.h' 'xemacs-21.5.26/src/symsinit.h' Index: ./src/symsinit.h *** ./src/symsinit.h Sat Nov 26 20:46:10 2005 --- ./src/symsinit.h Tue Feb 28 01:29:29 2006 *************** *** 140,148 **** void syms_of_lread (void); void syms_of_macros (void); void syms_of_marker (void); ! #ifdef MC_ALLOC void syms_of_mc_alloc (void); ! #endif /* MC_ALLOC */ void syms_of_md5 (void); void syms_of_menubar (void); void syms_of_menubar_mswindows (void); --- 140,148 ---- void syms_of_lread (void); void syms_of_macros (void); void syms_of_marker (void); ! #ifdef NEW_GC void syms_of_mc_alloc (void); ! #endif /* NEW_GC */ void syms_of_md5 (void); void syms_of_menubar (void); void syms_of_menubar_mswindows (void); diff -c 'xemacs-21.5.25/src/tests.c' 'xemacs-21.5.26/src/tests.c' Index: ./src/tests.c *** ./src/tests.c Sat Apr 9 08:11:33 2005 --- ./src/tests.c Tue Feb 28 01:29:29 2006 *************** *** 479,485 **** ! #ifdef MC_ALLOC #define TESTS_DEFSUBR(Fname) do { \ DEFSUBR_MC_ALLOC (Fname); \ defsubr (S##Fname); \ --- 479,485 ---- ! #ifdef NEW_GC #define TESTS_DEFSUBR(Fname) do { \ DEFSUBR_MC_ALLOC (Fname); \ defsubr (S##Fname); \ *************** *** 487,500 **** Fcons (intern (subr_name (S##Fname)), \ Vtest_function_list); \ } while (0) ! #else /* not MC_ALLOC */ #define TESTS_DEFSUBR(Fname) do { \ DEFSUBR (Fname); \ Vtest_function_list = \ Fcons (intern (subr_name (&S##Fname)), \ Vtest_function_list); \ } while (0) ! #endif /* not MC_ALLOC */ void syms_of_tests (void) --- 487,500 ---- Fcons (intern (subr_name (S##Fname)), \ Vtest_function_list); \ } while (0) ! #else /* not NEW_GC */ #define TESTS_DEFSUBR(Fname) do { \ DEFSUBR (Fname); \ Vtest_function_list = \ Fcons (intern (subr_name (&S##Fname)), \ Vtest_function_list); \ } while (0) ! #endif /* not NEW_GC */ void syms_of_tests (void) diff -c 'xemacs-21.5.25/src/vdb-posix.c' 'xemacs-21.5.26/src/vdb-posix.c' Index: ./src/vdb-posix.c *** ./src/vdb-posix.c Fri Nov 25 10:42:07 2005 --- ./src/vdb-posix.c Tue Mar 28 00:20:31 2006 *************** *** 118,124 **** } #ifdef USE_SIGACTION ! memset(&act, sizeof(struct sigaction), 0); act.sa_sigaction = vdb_fault_handler; sigemptyset (&act.sa_mask); act.sa_flags = SA_SIGINFO; --- 118,124 ---- } #ifdef USE_SIGACTION ! memset(&act, 0, sizeof(struct sigaction)); act.sa_sigaction = vdb_fault_handler; sigemptyset (&act.sa_mask); act.sa_flags = SA_SIGINFO; diff -c 'xemacs-21.5.25/src/vdb.c' 'xemacs-21.5.26/src/vdb.c' Index: ./src/vdb.c *** ./src/vdb.c Fri Nov 25 10:42:08 2005 --- ./src/vdb.c Sun Mar 26 23:05:30 2006 *************** *** 38,45 **** void vdb_start_dirty_bits_recording (void) { page_fault_table = Dynarr_new2 (void_ptr_dynarr, void *); ! protect_heap_pages (); } /* Remove heap protection. */ --- 38,46 ---- void vdb_start_dirty_bits_recording (void) { + Elemcount protected_pages = (Elemcount) protect_heap_pages (); page_fault_table = Dynarr_new2 (void_ptr_dynarr, void *); ! Dynarr_resize (page_fault_table, protected_pages); } /* Remove heap protection. */ diff -c 'xemacs-21.5.25/src/xemacs.def.in.in' 'xemacs-21.5.26/src/xemacs.def.in.in' Index: ./src/xemacs.def.in.in *** ./src/xemacs.def.in.in Wed Nov 30 20:28:58 2005 --- ./src/xemacs.def.in.in Tue Feb 28 01:29:29 2006 *************** *** 9,15 **** EXPORTS /* Exported functions */ acons ! #ifdef MC_ALLOC alloc_lrecord /* alloc_lrecord_type */ lrecord_subr /* DEFSUBR */ lrecord_symbol_value_forward /* DEFVAR_SYMVAL_FWD */ --- 9,15 ---- EXPORTS /* Exported functions */ acons ! #ifdef NEW_GC alloc_lrecord /* alloc_lrecord_type */ lrecord_subr /* DEFSUBR */ lrecord_symbol_value_forward /* DEFVAR_SYMVAL_FWD */ *************** *** 17,25 **** mcpro_1 /* mcpro */ #endif mc_alloc /* DEFSUBR */ ! #else /* not MC_ALLOC */ alloc_automanaged_lcrecord /* old_alloc_lcrecord_type */ ! #endif /* not MC_ALLOC */ apply1 #ifdef USE_ASSERTIONS assert_failed /* abort(), assert(), etc. */ --- 17,25 ---- mcpro_1 /* mcpro */ #endif mc_alloc /* DEFSUBR */ ! #else /* not NEW_GC */ alloc_automanaged_lcrecord /* old_alloc_lcrecord_type */ ! #endif /* not NEW_GC */ apply1 #ifdef USE_ASSERTIONS assert_failed /* abort(), assert(), etc. */ diff -c 'xemacs-21.5.25/tests/ChangeLog' 'xemacs-21.5.26/tests/ChangeLog' Index: ./tests/ChangeLog *** ./tests/ChangeLog Sun Feb 26 22:14:12 2006 --- ./tests/ChangeLog Sat Apr 1 03:46:16 2006 *************** *** 1,3 **** --- 1,7 ---- + 2006-03-31 Stephen J. Turnbull + + * XEmacs 21.5.26 "endive" is released. + 2006-02-26 Stephen J. Turnbull * XEmacs 21.5.25 "eggplant" is released. *************** *** 384,390 **** 2002-03-12 Ben Wing ! * The Great Mule Merge: placeholder. 2002-03-05 Stephen J. Turnbull --- 388,395 ---- 2002-03-12 Ben Wing ! * The Great Mule Merge of March 2002: ! see node by that name in the Internals Manual. 2002-03-05 Stephen J. Turnbull diff -c 'xemacs-21.5.25/version.sh' 'xemacs-21.5.26/version.sh' Index: ./version.sh *** ./version.sh Sun Feb 26 22:14:12 2006 --- ./version.sh Sat Apr 1 03:46:16 2006 *************** *** 2,12 **** emacs_is_beta=t emacs_major_version=21 emacs_minor_version=5 ! emacs_beta_version=25 ! xemacs_codename="eggplant" emacs_kit_version= infodock_major_version=4 infodock_minor_version=0 infodock_build_version=8 xemacs_extra_name="" ! xemacs_release_date="2006-02-26" --- 2,12 ---- emacs_is_beta=t emacs_major_version=21 emacs_minor_version=5 ! emacs_beta_version=26 ! xemacs_codename="endive" emacs_kit_version= infodock_major_version=4 infodock_minor_version=0 infodock_build_version=8 xemacs_extra_name="" ! xemacs_release_date="2006-04-01" #### End of Patch data #### #### ApplyPatch data follows #### # Data version : 1.0 # Date generated : Tue May 16 13:00:22 2006 # Generated by : makepatch 2.00_12* # Recurse directories : Yes # Excluded files : (\A|/).*\~\Z # (\A|/).*\.a\Z # (\A|/).*\.bak\Z # (\A|/).*\.BAK\Z # (\A|/).*\.elc\Z # (\A|/).*\.exe\Z # (\A|/).*\.gz\Z # (\A|/).*\.ln\Z # (\A|/).*\.o\Z # (\A|/).*\.obj\Z # (\A|/).*\.olb\Z # (\A|/).*\.old\Z # (\A|/).*\.orig\Z # (\A|/).*\.rej\Z # (\A|/).*\.so\Z # (\A|/).*\.Z\Z # (\A|/)\.del\-.*\Z # (\A|/)\.make\.state\Z # (\A|/)\.nse_depinfo\Z # (\A|/)core\Z # (\A|/)tags\Z # (\A|/)TAGS\Z # r './README.ben-separate-stderr' 534 0 # r './README.ben-mule-21-5' 78722 0 # r './CHANGES-msw' 3114 0 # r './CHANGES-ben-mule' 21925 0 # p './CHANGES-beta' 93547 1143827438 0100644 # p './ChangeLog' 179319 1143830775 0100644 # p './MANIFEST' 48265 1147669723 0100644 # p './aclocal.m4' 16227 1143561349 0100644 # p './configure' 1252878 1143830775 0100755 # p './configure.ac' 223252 1143742277 0100644 # p './etc/ChangeLog' 48194 1143830775 0100644 # p './info/internals.info' 13765 1143831923 0100644 # p './info/internals.info-1' 298225 1143831923 0100644 # p './info/internals.info-2' 300254 1143831923 0100644 # p './info/internals.info-3' 295432 1143831923 0100644 # p './info/internals.info-4' 284450 1143831923 0100644 # p './info/internals.info-5' 181017 1143831923 0100644 # p './info/xemacs.info' 12014 1143831930 0100644 # p './info/xemacs.info-3' 300563 1143831930 0100644 # p './info/xemacs.info-4' 266772 1143831930 0100644 # p './lib-src/ChangeLog' 53688 1143830775 0100644 # p './lisp/ChangeLog' 813346 1143830775 0100644 # p './lisp/auto-autoloads.el' 138427 1143831481 0100644 # p './lisp/custom-load.el' 41596 1143831893 0100644 # p './lisp/diagnose.el' 12912 1143794350 0100644 # p './lisp/lisp-mode.el' 46128 1140964148 0100644 # p './lisp/mule/custom-load.el' 3914 1143831898 0100644 # p './lisp/newcomment.el' 44723 1142615107 0100644 # p './lisp/next-error.el' 11369 1143285651 0100644 # p './lisp/occur.el' 19658 1143285651 0100644 # p './lisp/register.el' 12386 1142614500 0100644 # p './lisp/setup-paths.el' 12662 1142294943 0100644 # p './lisp/wid-edit.el' 138216 1142614204 0100644 # p './lwlib/ChangeLog' 32720 1143830775 0100644 # p './man/ChangeLog' 193378 1143830775 0100644 # p './man/internals/internals.texi' 1269726 1143827489 0100644 # p './man/xemacs/building.texi' 29554 1140964114 0100644 # p './modules/ChangeLog' 13353 1143830775 0100644 # p './netinstall/ChangeLog' 14059 1143830775 0100644 # p './nt/ChangeLog' 69125 1143830775 0100644 # p './nt/config.inc.samp' 11499 1142294949 0100644 # p './nt/installer/Wise/ChangeLog' 2601 1143830775 0100644 # p './nt/xemacs.mak' 55055 1142294949 0100644 # p './src/ChangeLog' 1572659 1143830776 0100644 # p './src/Makefile.in.in' 34185 1141057761 0100644 # p './src/alloc.c' 150671 1143386666 0100644 # c './src/alsaplay.c' 0 1143481258 0100644 # p './src/buffer.c' 99662 1141057762 0100644 # p './src/bytecode.c' 67868 1141057762 0100644 # p './src/bytecode.h' 6529 1141057762 0100644 # p './src/config.h.in' 33924 1143481258 0100644 # p './src/console-stream.c' 11385 1141057763 0100644 # p './src/console.c' 48824 1141057763 0100644 # p './src/depend' 42991 1143496288 0100644 # p './src/dumper.c' 79498 1141057763 0100644 # p './src/dumper.h' 1223 1141057763 0100644 # p './src/dynarr.c' 11862 1142889628 0100644 # p './src/elhash.c' 56723 1141057763 0100644 # p './src/emacs.c' 146981 1141057763 0100644 # p './src/eval.c' 200441 1141057764 0100644 # p './src/event-msw.c' 148658 1141057764 0100644 # p './src/event-stream.c' 175123 1141057764 0100644 # p './src/extents.c' 243350 1141057765 0100644 # p './src/faces.h' 16514 1141057765 0100644 # p './src/file-coding.c' 151708 1143378317 0100644 # p './src/gc.c' 58699 1143567833 0100644 # p './src/gc.h' 5707 1143567834 0100644 # p './src/glyphs.h' 46961 1141057766 0100644 # p './src/gui.c' 21326 1141057766 0100644 # p './src/lisp.h' 216522 1143760238 0100644 # p './src/lrecord.h' 76302 1141057767 0100644 # p './src/lstream.c' 52774 1141057767 0100644 # p './src/marker.c' 15469 1141057767 0100644 # p './src/mc-alloc.c' 56916 1143386666 0100644 # p './src/mc-alloc.h' 6353 1143386667 0100644 # p './src/objects-x.c' 50853 1142605845 0100644 # p './src/opaque.c' 5682 1141057768 0100644 # p './src/print.c' 72423 1141057768 0100644 # p './src/profile.h' 4373 1142364703 0100644 # p './src/ralloc.c' 58678 1141057768 0100644 # p './src/regex.c' 223964 1143286069 0100644 # p './src/sound.c' 20964 1143481259 0100644 # p './src/specifier.c' 113013 1141057768 0100644 # p './src/symbols.c' 118609 1141057768 0100644 # p './src/symeval.h' 20195 1141057769 0100644 # p './src/symsinit.h' 19289 1141057769 0100644 # p './src/tests.c' 16495 1141057769 0100644 # p './src/vdb-posix.c' 4133 1143472831 0100644 # p './src/vdb.c' 4319 1143381930 0100644 # p './src/xemacs.def.in.in' 6304 1141057769 0100644 # p './tests/ChangeLog' 23384 1143830776 0100644 # p './version.sh' 268 1143830776 0100644 #### End of ApplyPatch data #### #### End of Patch kit [created: Tue May 16 13:00:22 2006] #### #### Patch checksum: 37573 1660498 49836 #### #### Checksum: 37607 1661707 18928 ####