# This is a patch for xemacs-21.5.18 to update it to xemacs-21.5.19 # # 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 './src/xemacs.dmp' rm -f './src/nt.h' rm -f './src/m/gec63.h' rm -f './src/dump-size' rm -f './modules/postgresql/Makefile.in' rm -f './modules/postgresql/GNUmakefile' rm -f './man/internals/index.texi' rm -f './etc/sink.xbm' rm -f './etc/ms-kermit-7bit' rm -f './etc/ms-kermit' rm -f './etc/gnu.xpm' rm -f './etc/gnu.xbm' rm -f './etc/check_cygwin_setup.sh' rm -f './etc/aliases.ksh' rm -f './etc/TERMS' rm -f './etc/SERVICE' rm -f './etc/README.OO-BROWSER' rm -f './etc/README.HYPERBOLE' rm -f './etc/PACKAGES' rm -f './etc/ORDERS.JAPAN' rm -f './etc/ORDERS.EUROPE' rm -f './etc/ORDERS' rm -f './etc/MOTIVATION' rm -f './etc/MORE.STUFF' rm -f './etc/MAILINGLISTS' rm -f './etc/MACHINES' rm -f './etc/LPF' rm -f './etc/GNU' rm -f './etc/FTP' rm -f './etc/DISTRIB' rm -f './etc/DEBUG' rm -f './etc/COPYING.LIB' rm -f './etc/CODINGS' rm -f './etc/CODING-STANDARDS' rm -f './etc/CHARSETS' rm -f './etc/BETA' rm -f './README.packages' rm -f './GETTING.GNU.SOFTWARE' rm -f './BUGS' touch './lisp/easy-mmode.el' chmod 0644 './lisp/easy-mmode.el' touch './lisp/regexp-opt.el' chmod 0644 './lisp/regexp-opt.el' touch './man/beta.texi' chmod 0644 './man/beta.texi' touch './modules/postgresql/configure' chmod 0755 './modules/postgresql/configure' touch './tests/automated/os-tests.el' chmod 0644 './tests/automated/os-tests.el' # # This command terminates the shell and need not be executed manually. exit # #### End of Preamble #### #### Patch data follows #### diff --text -u 'xemacs-21.5.18/CHANGES-beta' 'xemacs-21.5.19/CHANGES-beta' Index: ./CHANGES-beta --- ./CHANGES-beta Fri Oct 22 11:14:14 2004 +++ ./CHANGES-beta Fri Feb 18 13:53:56 2005 @@ -1,3 +1,129 @@ +to 21.5.19 "chives" + +Major Features + +-- Improve: major reorganization of source tree docs. (Ben Wing) +-- Improve: behaviors get new code and many new implementations. (Ben Wing) + +User-Visible Bug Fixes and Minor Improvements + +-- Fix: security hole (CAN-2005-0100) in movemail. (Vin Shelton) +-- Fix: data truncation in i.c. (Ben Wing) +-- Fix: region deletion bug. (Stephen Turnbull) +-- Fix: crash in Frecord_buffer. (Yoshiki Hayashi) +-- Fix: Metacity maximize bug. (Stephen Turnbull) +-- Fix: data truncation bugs in unix_send_process. (David Evers, Jerry James) +-- Fix: recognise AltGr as a valid modifier in GTK. (Malcolm Purvis) +-- Fix: recognize ISO keysyms. (Ville Skyttä) +-- New: on Windows, dump Unicode tables to allow non-ASCII invocation. + (Ben Wing) +-- New: splash screen. (Ben Wing) +-- New: support treating shortcuts under Windows as symbolic links. (Ben Wing) +-- Improve: GNU-compatible coding system aliases. (Aidan Kehoe) +-- Improve: help system. (Ben Wing) +-- Improve: mouse-track. (Ben Wing) +-- Improve: support ISO 8859/16 by default. (Aidan Kehoe) + +Build Infrastructure + +-- Fix: copy BUGS, README, COPYING and Installation on installation on + Windows. (Ben Wing) +-- Fix: installation for Cygwin. (Marcus Crestani) +-- Fix: various build problems. (Ben Wing) +-- Fix: various things in configure. (Ben Wing) +-- New: default pdump on for Cygwin. (Marcus Crestani) +-- New: support NetBSD sound via Linux API. (Aidan Kehoe) +-- Improve: generation of CFLAGS (Jerry James, Ben Wing) +-- Improve: parallel build support. (Malcolm Purvis) +-- Improve: support --package-prefix as simple interface to --package-path + facility. (Ben Wing) +-- Improve: support mmdf and pop arguments to --mail-locking. (Ben Wing) + +Documentation + +-- Fix: beta.texi. (Stephen Turnbull, Robert Royar) +-- Fix: typos. (Alexey Mahotkin, Andreas Eder) +-- New: "Future Work -- Better Rendering Support". (Stephen turnbull) +-- New: "Future Work" collects feature proposals in Internals. (Ben Wing) +-- New: empty ChangeLog entry. (Ben Wing) +-- New: personal photos. (Malcolm Purvis) +-- Improve: Lispref (Shyamal Prasad, Stephen Turnbull, Aidan Kehoe) +-- Improve: Users' Guide. (Ben Wing) +-- Improve: about.el. (Malcolm Purvis, Ben Wing) +-- Improve: docstrings. (Ben Wing, Stephen Turnbull, Adrian Aichner, + Aidan Kehoe) +-- Improve: gnuserv docs. (Stephen J. Turnbull) +-- Improve: incorporate source tree docs in FAQ. (Ben Wing) +-- Improve: major overhauls of FAQ, Internals. (Ben Wing) +-- Improve: various comments. (Ben Wing) + +Lisp API + +-- Improve: sync bytecomp-runtime.el (make-obsolete, make-obsolete-variable). + (Ville Skyttä) +-- Improve: sync paragraphs.el, custom.el, subr.el, newcomment.el, + fill.el, page.el, register.el. (Ben Wing) +-- New: move regexp-opt.el and easy-mmode.el from packages to core. (Ben Wing) +-- New: next/previous-single-char-property-change and make + next/previous-single-property-change work like in FSF. (Ben Wing) +-- New: xemacs-font-lock-c-keywords and friends. (Ben Wing) + +Internal API and Implementation + +-- Fix: ^M brokenness in res.rc. (Ben Wing) +-- Fix: adapt to recent changes in Cygwin. (Ben Wing) +-- Fix: byte-char conversion, should speed up Mule if there are + non-ASCII characters in the buffer. (Ben Wing) +-- Fix: coding cookie recognition in .elc. (Ben Wing) +-- Fix: data-in-executable problems. (Olivier Galibert, Ben Wing) +-- Fix: find-coding-system-magic-cookie-in-file. (Ben Wing) +-- Fix: leaking process handles. (Ben Wing) +-- Fix: only call device method compute_scrollbar_instance_usage() if it + is defined. (Zajcev Evgeny) +-- Fix: protect callers of MSFT syscalls from MSFT API randomization. + (Ben Wing) +-- Fix: typos. (Robert Royar) +-- Fix: warnings. (Aidan Kehoe, Ben Wing) +-- New: Hashcode type. (Ben Wing) +-- New: color API. (Ben Wing) +-- New: rename abort() macro to ABORT() to placate VC 7. (Ben Wing) +-- Improve: GCPRO macros. (Ben Wing) +-- Improve: Mule-ize various things. (Ben Wing) +-- Improve: Suppress aliasing warning in free_hook; Jerry says not a fix? + (Ben Wing) +-- Improve: UNUSED parameter marking, UNO support. (Malcolm Purvis, + Jerry James) +-- Improve: Unicode-ize various things. (Ben Wing) +-- Improve: critical section protection. (Ben Wing) +-- Improve: debug info on attempt to throw outside of a function where + call_trapping_problems() has been used. (Ben Wing) +-- Improve: menubar support. (Ben Wing) +-- Improve: more orthogonality in emacs-root-finding. (Mike Sperber) +-- Improve: move etc/aliases.ksh to xemacs-builds CVS module. (Ben Wing) +-- Improve: move etc/chr.png, etc/chrm.png to etc/photos/ (Ben Wing) +-- Improve: partially rework Unicode support. (Ben Wing) +-- Improve: path handling correctness. (Ben Wing) +-- Improve: rangetabs get different types of ranges (open/closed start + and end). Change default to be start-closed, end-open. (Ben Wing) +-- Improve: refactor Initialization changes: (Ben Wing) +-- Improve: refer to init.el not .emacs in menus. (Stephen Turnbull) +-- Improve: s&m files by removing autodetected stuff. (Ben Wing) +-- Improve: support dumping bignums. (Jerry James, Olivier Galibert) +-- Improve: support for crashing gently. (Ben Wing) +-- Improve: type and keyword pedantry. (Jerry James, Ben Wing) +-- Improve: update etags from upstream. (Jerry James) +-- Remove: EXTERNAL_LIST_LOOP because it can infloop. (Ben Wing) +-- Remove: etc/gnu.xpm, etc/gnu.xbm, etc/sink.xbm, etc/ms-kermit, + etc/ms-kermit-7bit (Ben Wing) +-- Remove: unneeded/unused code. (Ben Wing, Stephen Turnbull) + +Quality Assurance Infrastructure + +-- Fix: conflict with builtin in .gdbinit. (Golubev I. N.) +-- New: regexp tests. (Stephen Turnbull, Vin Shelton) +-- New: os-tests.el. (Stephen Turnbull) +-- Improve: profiling support. (Ben Wing) + to 21.5.18 "chestnut" Major Features diff --text -u 'xemacs-21.5.18/ChangeLog' 'xemacs-21.5.19/ChangeLog' Index: ./ChangeLog --- ./ChangeLog Fri Oct 22 14:10:31 2004 +++ ./ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,101 @@ +2005-02-18 Stephen J. Turnbull + + * XEmacs 21.5.19 "chives" is released. + +2005-02-17 Stephen J. Turnbull + + * CHANGES-beta: Update. + +2005-02-03 Ben Wing + + * BUGS, README.packages: Delete, incorporate into FAQ. + * README: Incorporate into FAQ. Delete everything but text + pointing to FAQ. + +2005-02-03 Jerry James + + * configure.in: g++ 3.4.2 doesn't like -Wmissing-prototypes or + -Wstrict-prototypes. + +2005-01-31 Ben Wing + + * GETTING.GNU.SOFTWARE: Delete. + * Makefile.in.in (SOURCES): + Delete GETTING.GNU.SOFTWARE from SOURCES. + * PROBLEMS: + Delete reference to check_cygwin_setup.sh. + +2005-01-26 Ben Wing + + * configure.in (AC_INIT_PARSE_ARGS): + * configure.in (CANONICALIZE_PATH): + * configure.in (TAB): + * configure.usage: + Add --with-optimization, cflags-optimization, + cflags-debugging. Separate out optimization and debugging arguments. + Document. + +2005-01-21 Aidan Kehoe + + * configure: + * configure.in (XE_COMPUTE_RUNPATH): + NetBSD can use Linux's sound API, but it needs an extra library at + link time to do so. + +2004-12-07 Malcolm Purvis + + * INSTALL: A POSIX compatible Make is no longer required for builds. + * Makefile.in.in (RECURSIVE_MAKE): Removed. + * Makefile.in.in (RECURSIVE_MAKE_ARGS): New. + * configure.in (RECURSIVE_MAKE): Removed. + * configure.in (RECURSIVE_MAKE_ARGS): New. + Always refer to make as $(MAKE) and use $(RECURSIVE_MAKE_ARGS) for + other parameters. This allows -j to work in GNU Make while + removing need for POSIX compatible make on all systems. + +2004-12-05 Ben Wing + + * README.packages: + Fix error in specifying standard package location. + Document --package-prefix. + +2004-12-05 Ben Wing + + * configure.usage: + * configure.in (AC_INIT_PARSE_ARGS): + * configure.in (TAB): + * configure.in (XE_COMPUTE_RUNPATH): + * configure: + Support --package-prefix and mmdf and pop arguments to --mail-locking. + Document in configure.usage. + +2004-11-12 Marcus Crestani + + * configure: + * configure.in: Make pdump default for Cygwin. + +2004-11-12 Marcus Crestani + + * Makefile.in.in (install-arch-dep): Fix installation for Cygwin. + +2004-10-26 Ben Wing + + * configure.in (AC_INIT_NOTICE): + * configure.in (TAB): + * configure.in (XE_COMPUTE_RUNPATH): + Turn off -Winline and -Wchar-subscripts. + Use the right set of cflags when compiling modules. + Rewrite ldap configuration to separate the inclusion of lber + (needed in recent Cygwin) from the basic checks for the + needed libraries. + add a function for MAKE_JUNK_C; initially code was added to + generate xemacs.def using this, but it will need to be rewritten. + add an rm -f for junk.c to avoid weird Cygwin bug with cp -f onto + an existing file. + Sort list of auto-detected functions and eliminate unused checks for + stpcpy, setlocale and getwd. + Add autodetection of Cygwin scanf problems + 2004-10-22 Stephen J. Turnbull * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/INSTALL' 'xemacs-21.5.19/INSTALL' Index: ./INSTALL --- ./INSTALL Tue Sep 21 03:00:39 2004 +++ ./INSTALL Tue Dec 7 21:52:31 2004 @@ -45,11 +45,10 @@ on-line documentation. The exact amount depends greatly on the number of extra Lisp packages that are installed. -XEmacs requires an ANSI C compiler, such as GCC, and a POSIX compatible -make, such as GNU Make. If you wish to build the documentation -yourself, you will need at least version 1.68 of makeinfo (GNU -texinfo-3.11). GNU Texinfo 4.2 is recommended; it is necessary for -building Lisp packages, and we may move to it for the core. +XEmacs requires an ANSI C compiler, such as GCC. If you wish to build the +documentation yourself, you will need at least version 1.68 of makeinfo (GNU +texinfo-3.11). GNU Texinfo 4.2 is recommended; it is necessary for building +Lisp packages, and we may move to it for the core. A note on terminology: unfortunately the terms "library" and "package" are heavily overloaded. In the following, "library" refers to an diff --text -u 'xemacs-21.5.18/Makefile.in.in' 'xemacs-21.5.19/Makefile.in.in' Index: ./Makefile.in.in --- ./Makefile.in.in Fri Sep 10 20:58:08 2004 +++ ./Makefile.in.in Tue Feb 1 05:01:50 2005 @@ -55,10 +55,10 @@ #include "src/config.h" #ifdef USE_GNU_MAKE -RECURSIVE_MAKE=$(MAKE) +RECURSIVE_MAKE_ARGS= #else @SET_MAKE@ -RECURSIVE_MAKE=@RECURSIVE_MAKE@ +RECURSIVE_MAKE_ARGS=@RECURSIVE_MAKE_ARGS@ #endif SHELL = /bin/sh @@ -275,13 +275,13 @@ cd ${srcdir} && $(SHELL) lib-src/config.values.sh depend ${srcdir}/src/depend: - +cd ./src && $(RECURSIVE_MAKE) depend + cd ./src && $(MAKE) $(RECURSIVE_MAKE_ARGS) depend check: - +cd ./src && $(RECURSIVE_MAKE) $@ + cd ./src && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@ check-features: all - +cd ./src && $(RECURSIVE_MAKE) $@ + cd ./src && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@ ## We have to force the building of Emacs.ad.h as well in order to get it ## updated correctly when VPATH is being used. Since we use move-if-change, @@ -310,14 +310,14 @@ FRC.lisp.finder-inf.el: ${SUBDIR}: ${SUBDIR_MAKEFILES} ${GENERATED_HEADERS} FRC - +cd ./$@ && $(RECURSIVE_MAKE) all + cd ./$@ && $(MAKE) $(RECURSIVE_MAKE_ARGS) all ## Building modules depends on ellcc, found in lib-src. modules/sample modules/ldap modules/zlib modules/base64 modules/postgresql: lib-src Makefile: ${srcdir}/Makefile.in.in config.status ./config.status - $(RECURSIVE_MAKE) all + $(MAKE) $(RECURSIVE_MAKE_ARGS) all src/Makefile: ${srcdir}/src/Makefile.in.in ${srcdir}/src/depend config.status ./config.status @@ -375,7 +375,7 @@ install-arch-dep: mkdir for subdir in ${INSTALL_ARCH_DEP_SUBDIR}; do \ - (cd ./$${subdir} && $(RECURSIVE_MAKE) install prefix=${prefix} \ + (cd ./$${subdir} && $(MAKE) $(RECURSIVE_MAKE_ARGS) install prefix=${prefix} \ exec_prefix=${exec_prefix} bindir=${bindir} libdir=${libdir} \ archlibdir=${archlibdir}) ; done if test "`(cd ${archlibdir} && $(pwd))`" != \ @@ -395,11 +395,13 @@ ${INSTALL_PROGRAM} src/${PROGNAME} ${bindir}/${PROGNAME} -chmod 0755 ${bindir}/${PROGNAME} #else - ${INSTALL_PROGRAM} src/${PROGNAME} ${bindir}/${PROGNAME}-${version} - -chmod 0755 ${bindir}/${PROGNAME}-${version} # ifdef CYGWIN + ${INSTALL_PROGRAM} src/${PROGNAME} ${bindir}/${PROGNAME}-${version}.exe + -chmod 0755 ${bindir}/${PROGNAME}-${version}.exe cd ${bindir} && $(RM) ./${PROGNAME} && ${LN_S} ${PROGNAME}-${version}.exe ./${PROGNAME} # else + ${INSTALL_PROGRAM} src/${PROGNAME} ${bindir}/${PROGNAME}-${version} + -chmod 0755 ${bindir}/${PROGNAME}-${version} cd ${bindir} && $(RM) ./${PROGNAME} && ${LN_S} ${PROGNAME}-${version} ./${PROGNAME} # endif /* CYGWIN */ #endif /* WIN32_NATIVE */ @@ -490,7 +492,7 @@ #### would be extremely dangerous for anyone to use it. ##uninstall: ## (cd ./lib-src; \ -## $(RECURSIVE_MAKE) uninstall \ +## $(MAKE) $(RECURSIVE_MAKE_ARGS) uninstall \ ## prefix=${prefix} exec_prefix=${exec_prefix} \ ## bindir=${bindir} libdir=${libdir} archlibdir=${archlibdir}) ## for dir in ${lispdir} ${etcdir} ; do \ @@ -524,7 +526,7 @@ ## target for GCC does not delete `libgcc.a', because recompiling it ## is rarely necessary and takes a lot of time. mostlyclean: FRC.mostlyclean - +for d in $(SUBDIR); do (cd ./$$d && $(RECURSIVE_MAKE) $@); done + for d in $(SUBDIR); do (cd ./$$d && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@); done $(RM) core ## `clean' @@ -540,7 +542,7 @@ ## when they don't work right. (beta can't depend on distclean, which ## removes necessary files generated by configure.) clean: FRC.clean - +for d in $(SUBDIR); do (cd ./$$d && $(RECURSIVE_MAKE) $@); done + for d in $(SUBDIR); do (cd ./$$d && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@); done $(RM) core lisp/auto-autoloads.el* lisp/custom-load.el* $(RM) lisp/mule/auto-autoloads.el* lisp/mule/custom-load.el* $(RM) modules/auto-autoloads.el* modules/custom-load.el* @@ -558,7 +560,7 @@ $(RM) -r site-packages xemacs-packages mule-packages site-lisp distclean: FRC.distclean - +for d in $(SUBDIR); do (cd ./$$d && $(RECURSIVE_MAKE) $@); done + for d in $(SUBDIR); do (cd ./$$d && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@); done -${top_distclean} ## `realclean' @@ -573,7 +575,7 @@ ## anything that needs to exist in order to run `configure' and then ## begin to build the program. realclean: FRC.realclean - +for d in $(SUBDIR); do (cd ./$$d && $(RECURSIVE_MAKE) $@); done + for d in $(SUBDIR); do (cd ./$$d && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@); done -${top_distclean} $(RM) TAGS @@ -582,7 +584,7 @@ ## the coding standards seem to come from. It's like distclean, but ## it deletes backup and autosave files too. extraclean: - +for d in $(SUBDIR); do (cd ./$$d && $(RECURSIVE_MAKE) $@); done + for d in $(SUBDIR); do (cd ./$$d && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@); done $(RM) *~ \#* -${top_distclean} @@ -596,7 +598,7 @@ ## Note: it's no disaster if these productions miss a file or two; tar ## and VC will swiftly let you know if this happens, and it is easily ## corrected. -SOURCES = ChangeLog GETTING.GNU.SOFTWARE INSTALL Makefile.in.in PROBLEMS \ +SOURCES = ChangeLog INSTALL Makefile.in.in PROBLEMS \ README build-install.in configure make-dist move-if-change .PHONY: unlock relock TAGS tags dist info dvi mcs @@ -604,7 +606,7 @@ unlock: chmod u+w $(SOURCES) cpp/* -cd ./elisp && chmod u+w Makefile README *.texi - for d in src etc lib-src lisp; do (cd ./$$d && $(RECURSIVE_MAKE) $@); done + for d in src etc lib-src lisp; do (cd ./$$d && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@); done cd ./lisp/term && chmod u+w README *.el cd ./man && chmod u+w *texi* ChangeLog split-man cd ./lwlib && chmod u+w *.[ch] Makefile.in.in @@ -612,7 +614,7 @@ relock: chmod u-w $(SOURCES) cpp/* -cd ./elisp && chmod u-w Makefile README *.texi - for d in src etc lib-src lisp; do (cd ./$$d && $(RECURSIVE_MAKE) $@); done + for d in src etc lib-src lisp; do (cd ./$$d && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@); done cd ./lisp/term && chmod u+w README *.el cd ./man && chmod u+w *texi* ChangeLog split-man cd ./lwlib && chmod u+w *.[ch] Makefile.in.in @@ -633,10 +635,10 @@ xargs etags -a -l none -r "/^(def\\(var\\|un\\|alias\\|const\\|macro\\|subst\\|struct\\|face\\|group\\|custom\\|ine-\\(function\\|compiler-macro\\|[a-z-]+alias\\)\\)[ ]+'?\\([^ ]+\\)/\\3/" info: FRC.info - +cd ${srcdir}/man && $(RECURSIVE_MAKE) $@ + cd ${srcdir}/man && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@ dvi: - +cd ${srcdir}/man && $(RECURSIVE_MAKE) $@ + cd ${srcdir}/man && $(MAKE) $(RECURSIVE_MAKE_ARGS) $@ ## Fix up version information in executables (Solaris-only) mcs: diff --text -u 'xemacs-21.5.18/PROBLEMS' 'xemacs-21.5.19/PROBLEMS' Index: ./PROBLEMS --- ./PROBLEMS Sat Sep 20 01:24:33 2003 +++ ./PROBLEMS Tue Feb 1 05:01:49 2005 @@ -783,12 +783,6 @@ Try configuring with pdump or without system malloc. -*** In general use etc/check_cygwin_setup.sh to trap environment problems. - -The script etc/check_cygwin_setup.sh will attempt to detect whether -you have a suitable environment for building. This script may not work -correctly if you are using ash instead of bash (see below). - *** Syntax errors running configure scripts, make failing with exit code 127 in inexplicable situations, etc. @@ -1004,7 +998,7 @@ or in /usr/openwin/lib/. If you keep yours in a different place, set the environment variable $XKEYSYMDB to point to it before starting emacs. If you still have the problem after doing that, perhaps your version of X is -too old. There is a copy of the MIT X11R5 XKeysymDB file in the emacs `etc' +too old. There is a copy of the MIT X11R6 XKeysymDB file in the emacs `etc' directory. Try using that one. *** My X resources used to work, and now some of them are being ignored. diff --text -u 'xemacs-21.5.18/README' 'xemacs-21.5.19/README' Index: ./README --- ./README Tue Aug 20 15:31:26 2002 +++ ./README Fri Feb 4 12:04:05 2005 @@ -1,245 +1,15 @@ This directory tree holds version 21.5 of XEmacs. +The information in this file has been superseded by the XEmacs FAQ. + +The easiest way to read the FAQ is to go to + +http://www.xemacs.org/Documentation/21.5/html/xemacs-faq_1.html + +You can also the local copy of the FAQ inside XEmacs by using +use Help->XEmacs FAQ from the menu, or `C-h F'. + +If you don't have XEmacs running and can't access the web, +look directly at `man/xemacs-faq.texi' or `info/xemacs-faq.info'. -*** What is XEmacs? -XEmacs is a powerful, highly customizable open source text editor and -application development system, with full GUI support. It is protected -under the GNU Public License and related to other versions of Emacs, in -particular GNU Emacs. Its emphasis is on modern graphical user -interface support and an open software development model, similar to -Linux. XEmacs has an active development community numbering in the -hundreds (and thousands of active beta testers on top of this), and runs -on all versions of MS Windows, on Linux, and on nearly every other -version of Unix in existence. Support for XEmacs has been supplied by -Sun Microsystems, University of Illinois, Lucid, ETL/Electrotechnical -Laboratory, Amdahl Corporation, BeOpen, and others, as well as the -unpaid time of a great number of individual developers. - - - -*** What platforms does it run on? - - -- MS Windows (It has been tested on NT, 2000, 95, 98, and ME; you - can also compile Cygwin and MinGW versions.) - -- Unix (It is regularly tested on Linux, Solaris, SunOS, HP/UX, - FreeBSD, OpenBSD, BSD/OS aka BSDI, Tru64 aka DEC/OSF, SCO5, - and probably others. It should work on all versions of Unix - created in the last 10 years or so, perhaps with a bit of - work on more obscure platforms to correct bit-rot. It uses - a sophisticated configuration system to auto-detect zillions - of features that are implemented differently in different - versions of Unix, so it will probably work on your vendor's - version, possibly with a bit of tweaking, even if we've - never heard of it.) - -- MacOS/X (As an X Windows application. Unfortunately there is no - support currently for MacOS-specific features.) - - There is also a port of XEmacs 19.14 (an older version, circa 1996) - for all versions of MacOS, with extensive support for MacOS-specific - features. See the FAQ for more details. - - There are rumors of an in-progress port to OS/2. See the FAQ. - - XEmacs will probably never work on MS/DOS or Windows 3.1, and we're - not particularly interested in patches for these platforms, as they - would introduce huge amounts of code clutter due to the woefully - underfeatured nature of these systems. (See GNU Emacs for a port to - MS/DOS.) - - - -*** Where's the FAQ? - -Look at `man/xemacs-faq.texi'. - -For the very latest version, see -http://cvs.xemacs.org/cgi-bin/cvswebxe/xemacs/man/xemacs-faq.texi. - - - -*** Where's the latest version? - -For up-to-date information on XEmacs, see http://www.xemacs.org. - -To download XEmacs, see http://ftp.xemacs.org/ or -ftp://ftp.xemacs.org/pub/xemacs/. - -For the latest experimental sources, see http://cvs.xemacs.org/, which -gives instructions on how to get started with CVS access. - -There are numerous mailing lists for discussion of XEmacs. The -current description of these lists can be found at -http://www.xemacs.org/Lists/, or see `etc/MAILINGLISTS'. General -discussion of bugs, new features, etc. takes place on -xemacs-beta@xemacs.org. - - - -*** How do I build and install XEmacs? - -See the file `etc/NEWS' for information on new features and other -user-visible changes since the last version of XEmacs. - -The file `INSTALL' in this directory says how to bring up XEmacs on -Unix and Cygwin, once you have loaded the entire subtree of this -directory. - -See the file `nt/README' for instructions on building XEmacs for -Microsoft Windows. - -The file 'README.packages' will guide you in the installation of -(essential) add on packages. - - - -*** How do I deal with bugs or with problems building, installing, or running? - -The file `PROBLEMS' contains information on many common problems that -occur in building, installing and running XEmacs. - -Reports of bugs in XEmacs should be sent to xemacs-beta@xemacs.org. -You can also post to the newsgroup comp.emacs.xemacs (or equivalentlt, -send to the mailing list xemacs@xemacs.org), but it is less likely -that the developers will see it in a timely fashion. See the "Bugs" -section of the XEmacs manual for more information on how to report -bugs. (The file `BUGS' in this directory explains how you can find -and read that section using the Info files that come with XEmacs.) -See `etc/MAILINGLISTS' for more information on mailing lists relating -to XEmacs. - - -*** How do I get started developing XEmacs? - -First, get yourself set up under CVS so that you can access the CVS -repositories containing the XEmacs sources and the XEmacs packages. - -Next, set up your layout. This is important, as a good layout will -facilitate getting things done efficiently, while a bad layout will could -lead to disaster, as you can't figure out which code is the most recent, -which can be thrown away, etc. We suggest the following layout: (feel free -to make changes) - --- Everything goes under /src/xemacs (use a different directory if you - want). From now, instead of saying /src/xemacs, we use , to - make it easier in case someone picked a different directory. - --- Package source is in /package-src. - --- Installed packages go under /xemacs-packages, and - /mule-packages. - --- A "workspace" is a complete copy of the sources, in which you do work of - a particular kind. Workspaces can be differentiated by which branch of - the source tree they extend off of -- usually either the stable or - experimental, unless other branches have been created (for example, Ben - created a branch for his Mule work because (1) the project was long-term - and involved an enormous number of changes, (2) people wanted to be able - to look at what his work in progress, and (3) he wanted to be able to - check things in and in general use source-code control, since it was a - long-term project). Workspaces are also differentiated in what their - purpose is -- general working workspace, workspace for particular - projects, workspace keeping the latest copy of the code in one of the - branches without mods, etc. - --- Various workspaces are subdirectories under , e.g.: - - -- /working (the workspace you're actively working on, - periodically synched up with the latest trunk) - - -- /stable (for making changes to the stable version of - XEmacs, which sits on a branch) - - -- /unsigned-removal (a workspace for a specific, difficult - task that's going to affect lots of source and take a long time, and - so best done in its own workspace without the interference of other - work you're doing. Also, you can commit just this one large change, - separate from all the other changes). - - -- /latest (a copy of the latest sources on the trunk, - i.e. the experimental version of XEmacs, with no patches in it; - either update it periodically, by hand, or set up a cron job to do it - automatically). Set it up so it can be built, and build it so you - have a working XEmacs. (Building it might also go into the cron job.) - - This workspace serves a number of purposes: - -- 1. You always have a recent version of XEmacs you can compare - against when something you're working on breaks. It's true - that you can do this with cvs diff, but when you need to do - some serious investigation, this method just fails. - -- 2. You (almost) always have a working, up-to-date executable that - can be used when your executable is crashing and you need to - keep developing it, or when you need an `xemacs' to build - packages, etc. - -- 3. When creating new workspaces, you can just copy the `latest' - workspace using GNU cp -a. You have all the .elc's built, - everything else probably configured, any spare files in place - (e.g. some annoying xpm.dll under Windows, etc.). - - -- /latest-stable/ (equivalent to /latest/, but - for the Stable branch of XEmacs, rather than the Experimental branch - of XEmacs). This may or may not be necessary depending on how much - development you do of the stable branch. - --- /xemacsweb is a workspace for working on the XEmacs web site. - --- /in-patches for patches received from email and saved to files. - --- /out-patches for locally-generated patches to be sent to - xemacs-patches@xemacs.org. Less useful now that the patcher util has been - developed. - --- /build, for build trees when compiling and testing XEmacs with - various configuration options turned off and on. The scripts in - xemacs-builds/ben (see below) can be used to automate building XEmacs - workspaces with many different configuration options and automatically - filtering out the normal output so that you see only the abnormal - output. - --- /xemacs-builds, for the xemacs-builds module, which you need - to check out separately in CVS. This contains scripts used for building - XEmacs, automating and simplifying using CVS, etc. Under various - people's directories are their own build and other scripts. The - currently most-maintained scripts are under ben/, where there are easily - configurable scripts that can be used to easily build any workspace - (esp. if you've more or less followed the layout presented above) - unattended, with one or more configuration states (there's a - pre-determined list of the most useful, but it's easy to change). The - output is filtered and split up in various ways so that you can identify - which output came from where, and you can see the output either full or - with all "normal" output except occasional status messages filtered so - that you only see the abnormal ones. - -*** What's the basic layout of the code? - -The file `configure' is a shell script to acclimate XEmacs to the -oddities of your processor and operating system. It will create a -file named `Makefile' (a script for the `make' program), which helps -automate the process of building and installing emacs. See INSTALL -for more detailed information. - -The file `configure.in' is the input used by the autoconf program to -construct the `configure' script. Since XEmacs has configuration -requirements that autoconf can't meet, `configure.in' uses an unholy -marriage of custom-baked configuration code and autoconf macros; it -may be wise to avoid rebuilding `configure' from `configure.in' when -possible. - -The file `Makefile.in' is a template used by `configure' to create -`Makefile'. - -There are several subdirectories: - -`src' holds the C code for XEmacs (the XEmacs Lisp interpreter and its - primitives, the redisplay code, and some basic editing functions). -`lisp' holds the XEmacs Lisp code for XEmacs (most everything else). -`lib-src' holds the source code for some utility programs for use by - or with XEmacs, like movemail and etags. -`etc' holds miscellaneous architecture-independent data files - XEmacs uses, like the tutorial text and the Zippy the Pinhead quote - database. The contents of the `lisp', `info' and `man' - subdirectories are architecture-independent too. -`lwlib' holds the C code for the X toolkit objects used by XEmacs. -`info' holds the Info documentation tree for XEmacs. -`man' holds the source code for the XEmacs online documentation. -`nt' holds files used compiling XEmacs under Microsoft Windows. diff --text -u 'xemacs-21.5.18/configure' 'xemacs-21.5.19/configure' Index: ./configure --- ./configure Fri Oct 22 14:16:35 2004 +++ ./configure Fri Feb 18 14:22:08 2005 @@ -6,7 +6,7 @@ #### Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. #### Copyright (C) 1993-1995 Board of Trustees, University of Illinois. #### Copyright (C) 1996, 1997 Sun Microsystems, Inc. -#### Copyright (C) 1995, 1996, 2002, 2003 Ben Wing. +#### Copyright (C) 1995, 1996, 2002, 2003, 2004 Ben Wing. #### Copyright (C) 2000, 2001 Martin Buchholz. #### Copyright (C) 1998, 1999 J. Kean Johnston. @@ -366,6 +366,7 @@ with_dnet | \ with_infodock | \ with_netinstall | \ + with_optimization | \ with_ipv6_cname | \ external_widget | \ use_kkcc | \ @@ -394,6 +395,8 @@ xemacs_compiler | \ cflags | \ cflags_warning | \ + cflags_optimization | \ + cflags_debugging | \ cpp | \ cppflags | \ libs | \ @@ -532,9 +535,11 @@ flock ) val=flock ;; file | dot ) val=file ;; locking ) val=locking ;; + mmdf ) val=mmdf ;; + pop ) val=pop ;; * ) (echo "$progname: Usage error:" echo " " "The \`--$optname' option must have one of these values: - \`lockf', \`flock', \`file', \`locking', or \`mmdf'." + \`lockf', \`flock', \`file', \`dot', \`locking', \`mmdf', or \`pop'." echo " Use \`$progname --help' to show usage.") >&2 && exit 1 ;; esac eval "$opt=\"$val\"" @@ -618,7 +623,7 @@ prefix | exec_prefix | bindir | datadir | statedir | libdir | \ mandir | infodir | infopath | lispdir | etcdir | \ - archlibdir | docdir | package_path | moduledir ) + archlibdir | docdir | package_path | package_prefix | moduledir ) if test "$valomitted" = "yes"; then if test "$#" = 0; then (echo "$progname: Usage error:" @@ -686,6 +691,14 @@ EOF } ;; + package_prefix ) { test "$extra_verbose" = "yes" && cat << \EOF + Defining PACKAGE_PATH_USER_DEFINED +EOF +cat >> confdefs.h <<\EOF +#define PACKAGE_PATH_USER_DEFINED 1 +EOF +} + ;; package_path ) { test "$extra_verbose" = "yes" && cat << \EOF Defining PACKAGE_PATH_USER_DEFINED EOF @@ -849,7 +862,7 @@ fi echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:853: checking whether ln -s works" >&5 +echo "configure:866: checking whether ln -s works" >&5 rm -f conftestdata if ln -s X conftestdata 2>/dev/null @@ -1135,7 +1148,7 @@ echo $ac_n "checking "host system type"""... $ac_c" 1>&6 -echo "configure:1139: checking "host system type"" >&5 +echo "configure:1152: checking "host system type"" >&5 internal_configuration=`echo $configuration | sed 's/-\(workshop\)//'` canonical=`${CONFIG_SHELL-/bin/sh} $srcdir/config.sub "$internal_configuration"` configuration=`echo "$configuration" | sed 's/^\([^-][^-]*-[^-][^-]*-[^-][^-]*\)-.*$/\1/'` @@ -1575,7 +1588,7 @@ if test -z "$pdump"; then case "$opsys" in - linux* ) pdump=yes ;; darwin ) pdump=yes ;; * ) pdump=no ;; + linux* ) pdump=yes ;; darwin ) pdump=yes ;; cygwin* ) pdump=yes ;; * ) pdump=no ;; esac fi @@ -1668,12 +1681,22 @@ else cflags_warning_specified=no; fi +if test "${cflags_optimization-unset}" != unset + then cflags_optimization_specified=yes; + else cflags_optimization_specified=no; +fi + +if test "${cflags_debugging-unset}" != unset + then cflags_debugging_specified=yes; + else cflags_debugging_specified=no; +fi + xe_save_CFLAGS="$CFLAGS" # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1677: checking for $ac_word" >&5 +echo "configure:1700: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1700,7 +1723,7 @@ # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1704: checking for $ac_word" >&5 +echo "configure:1727: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1748,7 +1771,7 @@ # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1752: checking for $ac_word" >&5 +echo "configure:1775: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1777,7 +1800,7 @@ fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1781: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1804: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c xe_cppflags='$CPPFLAGS $c_switch_site $c_switch_machine $c_switch_system $c_switch_x_site $X_CFLAGS' @@ -1790,12 +1813,12 @@ cat > conftest.$ac_ext << EOF -#line 1794 "configure" +#line 1817 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:1799: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1822: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1823,19 +1846,19 @@ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1827: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1850: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1832: checking whether we are using GNU C" >&5 +echo "configure:1855: checking whether we are using GNU C" >&5 cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1862: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1853,7 +1876,7 @@ ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1857: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1880: checking whether ${CC-cc} accepts -g" >&5 echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then @@ -1886,7 +1909,7 @@ # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1890: checking for $ac_word" >&5 +echo "configure:1913: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1913,7 +1936,7 @@ # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1917: checking for $ac_word" >&5 +echo "configure:1940: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1961,7 +1984,7 @@ # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1965: checking for $ac_word" >&5 +echo "configure:1988: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1990,7 +2013,7 @@ fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1994: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:2017: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c xe_cppflags='$CPPFLAGS $c_switch_site $c_switch_machine $c_switch_system $c_switch_x_site $X_CFLAGS' @@ -2003,12 +2026,12 @@ cat > conftest.$ac_ext << EOF -#line 2007 "configure" +#line 2030 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:2012: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2035: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -2036,19 +2059,19 @@ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:2040: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:2063: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:2045: checking whether we are using GNU C" >&5 +echo "configure:2068: checking whether we are using GNU C" >&5 cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2075: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -2066,7 +2089,7 @@ ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:2070: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:2093: checking whether ${CC-cc} accepts -g" >&5 echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then @@ -2099,7 +2122,7 @@ # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2103: checking for $ac_word" >&5 +echo "configure:2126: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -2126,7 +2149,7 @@ # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2130: checking for $ac_word" >&5 +echo "configure:2153: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -2174,7 +2197,7 @@ # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2178: checking for $ac_word" >&5 +echo "configure:2201: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -2203,7 +2226,7 @@ fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:2207: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:2230: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c xe_cppflags='$CPPFLAGS $c_switch_site $c_switch_machine $c_switch_system $c_switch_x_site $X_CFLAGS' @@ -2216,12 +2239,12 @@ cat > conftest.$ac_ext << EOF -#line 2220 "configure" +#line 2243 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:2225: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -2249,19 +2272,19 @@ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:2253: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:2276: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:2258: checking whether we are using GNU C" >&5 +echo "configure:2281: checking whether we are using GNU C" >&5 cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2288: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -2279,7 +2302,7 @@ ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:2283: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:2306: checking whether ${CC-cc} accepts -g" >&5 echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then @@ -2312,7 +2335,7 @@ if test "$GCC" = "yes"; then cat > conftest.$ac_ext <= 3 @@ -2322,7 +2345,7 @@ #endif } EOF -if { (eval echo configure:2326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:2349: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then : else @@ -2348,7 +2371,7 @@ test -n "$NON_GNU_CPP" -a "$GCC" != "yes" -a -z "$CPP" && CPP="$NON_GNU_CPP" echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:2352: checking how to run the C preprocessor" >&5 +echo "configure:2375: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -2361,13 +2384,13 @@ # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2371: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2394: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -2378,13 +2401,13 @@ rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2388: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2411: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -2395,13 +2418,13 @@ rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2428: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -2427,9 +2450,9 @@ echo $ac_n "checking for AIX""... $ac_c" 1>&6 -echo "configure:2431: checking for AIX" >&5 +echo "configure:2454: checking for AIX" >&5 cat > conftest.$ac_ext <&6 -echo "configure:2460: checking for GNU libc" >&5 +echo "configure:2483: checking for GNU libc" >&5 cat > conftest.$ac_ext < int main() { @@ -2470,7 +2493,7 @@ ; return 0; } EOF -if { (eval echo configure:2474: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2497: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* have_glibc=yes else @@ -2565,7 +2588,7 @@ esac cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:2608: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then : else @@ -2815,7 +2838,7 @@ fi test "$extra_verbose" = "yes" && \ - for var in libs_machine libs_system libs_termcap libs_standard objects_machine objects_system c_switch_machine c_switch_system ld_switch_machine ld_switch_system unexec ld_switch_shared ld lib_gcc ld_text_start_addr start_files ordinary_link have_terminfo mail_use_flock mail_use_lockf; do eval "echo \"$var = '\$$var'\""; done && echo "" + for var in libs_machine libs_system libs_termcap libs_standard objects_machine objects_system c_switch_machine c_switch_system ld_switch_machine ld_switch_system unexec ld_switch_shared ld lib_gcc ld_text_start_addr start_files ordinary_link have_terminfo mail_use_flock mail_use_lockf mail_using_locking; do eval "echo \"$var = '\$$var'\""; done && echo "" case "$opsys" in mingw* | cygwin*) cygwin_include=`eval "gcc -print-file-name=libc.a"` ; @@ -2835,17 +2858,17 @@ if test "$__USLC__" = yes; then echo $ac_n "checking for whether the -Kalloca compiler flag is needed""... $ac_c" 1>&6 -echo "configure:2839: checking for whether the -Kalloca compiler flag is needed" >&5 +echo "configure:2862: checking for whether the -Kalloca compiler flag is needed" >&5 need_kalloca=no cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2872: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* : else @@ -2856,14 +2879,14 @@ xe_save_c_switch_system="$c_switch_system" c_switch_system="$c_switch_system -Kalloca" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2890: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* need_kalloca=yes else @@ -2891,31 +2914,61 @@ fi -echo $ac_n "checking for preferred CFLAGS""... $ac_c" 1>&6 -echo "configure:2896: checking for preferred CFLAGS" >&5 +if test -z "$with_optimization" ; then + if test -n "$emacs_is_beta" ; then + with_optimization=no + else + with_optimization=yes + fi +fi -if test "$cflags_specified" = "no"; then - if test "$GCC" = "yes"; then - CFLAGS="-g -O3" - elif test "$__SUNPRO_C" = "yes"; then - case "$opsys" in - sol2 ) CFLAGS="-xO4" ;; - sunos4* ) CFLAGS="-xO2" ;; - esac - elif test "$__DECC" = "yes"; then - CFLAGS="-O3" - elif test "$CC" = "xlc"; then - CFLAGS="-g -O3 -qstrict -qnoansialias -qlibansi -qro -qmaxmem=20000" - elif test "$__ICC" = "yes"; then - CFLAGS="-g -O3 -Ob2" - else - CFLAGS="-O" ; fi + +echo $ac_n "checking for preferred optimization flags""... $ac_c" 1>&6 +echo "configure:2928: checking for preferred optimization flags" >&5 +if test "$with_optimization" = "yes" ; then + if test "$cflags_optimization_specified" = "no"; then + if test "$GCC" = "yes"; then + cflags_optimization="-O3" + elif test "$__SUNPRO_C" = "yes"; then + case "$opsys" in + sol2 ) cflags_optimization="-xO4" ;; + sunos4* ) cflags_optimization="-xO2" ;; + esac + elif test "$__DECC" = "yes"; then + cflags_optimization="-O3" + elif test "$CC" = "xlc"; then + cflags_optimization="-O3 -qstrict -qnoansialias -qlibansi -qmaxmem=20000" + elif test "$__ICC" = "yes"; then + cflags_optimization="-O3 -Ob2" + else + cflags_optimization="-O" ; fi + fi +else + cflags_optimization= fi -echo "$ac_t""${CFLAGS}" 1>&6 + +echo "$ac_t""${cflags_optimization}" 1>&6 + + +echo $ac_n "checking for preferred debugging flags""... $ac_c" 1>&6 +echo "configure:2955: checking for preferred debugging flags" >&5 +if test "$cflags_debugging_specified" = "no"; then + cflags_debugging="-g" + + debugging_ok_with_optimization=no + if test "$GCC" = "yes" -o "$CC" = "xlc" -o "$__ICC" = "yes"; then + debugging_ok_with_optimization=yes + fi + + if test "$with_optimization" = "yes" -a "$debugging_ok_with_optimization" = "no"; then + cflags_debugging= + fi +fi +echo "$ac_t""${cflags_debugging}" 1>&6 echo $ac_n "checking for preferred warning flags for XEMACS_CC""... $ac_c" 1>&6 -echo "configure:2919: checking for preferred warning flags for XEMACS_CC" >&5 +echo "configure:2972: checking for preferred warning flags for XEMACS_CC" >&5 xe_cflags_warning="" @@ -2927,10 +2980,9 @@ elif test "$CC" = "xlc"; then cflags_warning="-qinfo" elif test "$GCC" = "yes"; then - cflags_warning="-Wall -Wno-switch -Winline -Wmissing-prototypes" - - cflags_warning="$cflags_warning -Wsign-compare" - cflags_warning="$cflags_warning -Wundef -Wstrict-prototypes" + cflags_warning="-Wall -Wno-switch -Wundef" + + cflags_warning="$cflags_warning -Wsign-compare -Wno-char-subscripts" test "$__GCC3" = "yes" && cflags_warning="$cflags_warning -Wpacked" test "$have_glibc" != "yes" && \ cflags_warning="$cflags_warning -Wpointer-arith" @@ -2940,6 +2992,7 @@ xe_cflags_warning="$cflags_warning -Wunused-parameter" fi cflags_warning="$cflags_warning -Wshadow -Wmissing-declarations" + cflags_warning="$cflags_warning -Wmissing-prototypes -Wstrict-prototypes" elif test "$__ICC" = "yes"; then cflags_warning="-Wall -w1 -we147" fi @@ -2948,15 +3001,34 @@ echo "$ac_t""${xe_cflags_warning}" 1>&6 echo $ac_n "checking for preferred warning flags for CC""... $ac_c" 1>&6 -echo "configure:2952: checking for preferred warning flags for CC" >&5 +echo "configure:3005: checking for preferred warning flags for CC" >&5 echo "$ac_t""${cflags_warning}" 1>&6 -XE_CFLAGS="$xe_cflags_warning $CFLAGS" -CFLAGS="$cflags_warning $CFLAGS" + +echo $ac_n "checking for remaining CFLAGS""... $ac_c" 1>&6 +echo "configure:3010: checking for remaining CFLAGS" >&5 + +if test "$cflags_specified" = "no"; then + if test "$CC" = "xlc"; then + CFLAGS="-qro" + fi +fi +echo "$ac_t""${CFLAGS}" 1>&6 + + +XE_CFLAGS="$xe_cflags_warning $cflags_debugging $cflags_optimization $CFLAGS" +CFLAGS="$cflags_warning $cflags_debugging $cflags_optimization $CFLAGS" + +echo $ac_n "checking total value of XE_CFLAGS""... $ac_c" 1>&6 +echo "configure:3024: checking total value of XE_CFLAGS" >&5 +echo "$ac_t""${XE_CFLAGS}" 1>&6 +echo $ac_n "checking total value of CFLAGS""... $ac_c" 1>&6 +echo "configure:3027: checking total value of CFLAGS" >&5 +echo "$ac_t""${CFLAGS}" 1>&6 if test "$GCC" = "yes"; then echo $ac_n "checking for buggy gcc versions""... $ac_c" 1>&6 -echo "configure:2960: checking for buggy gcc versions" >&5 +echo "configure:3032: checking for buggy gcc versions" >&5 GCC_VERSION=`$CC --version` case `uname -s`:`uname -m`:$GCC_VERSION in *:sun4*:2.8.1|*:sun4*:egcs-2.90.*) @@ -3014,7 +3086,7 @@ if test "$pdump" != "yes"; then echo $ac_n "checking for \"-z nocombreloc\" linker flag""... $ac_c" 1>&6 -echo "configure:3018: checking for \"-z nocombreloc\" linker flag" >&5 +echo "configure:3090: checking for \"-z nocombreloc\" linker flag" >&5 case "`ld --help 2>&1`" in *-z\ nocombreloc* ) echo "$ac_t""yes" 1>&6 ld_switch_site="-z nocombreloc $ld_switch_site" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-z nocombreloc\" to \$ld_switch_site"; fi ;; @@ -3103,7 +3175,7 @@ fi echo $ac_n "checking for dynodump""... $ac_c" 1>&6 -echo "configure:3107: checking for dynodump" >&5 +echo "configure:3179: checking for dynodump" >&5 if test "$unexec" != "unexsol2.o"; then echo "$ac_t""no" 1>&6 else @@ -3140,12 +3212,12 @@ done echo $ac_n "checking for terminateAndUnload in -lC""... $ac_c" 1>&6 -echo "configure:3144: checking for terminateAndUnload in -lC" >&5 +echo "configure:3216: checking for terminateAndUnload in -lC" >&5 ac_lib_var=`echo C'_'terminateAndUnload | sed 'y%./+-%__p_%'` xe_check_libs=" -lC " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3232: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3198,7 +3270,7 @@ libc_version="" echo $ac_n "checking for compiler version information""... $ac_c" 1>&6 -echo "configure:3202: checking for compiler version information" >&5 +echo "configure:3274: checking for compiler version information" >&5 if test "$GCC" = "yes"; then compiler_version=`$XEMACS_CC --version | head -1` @@ -3249,7 +3321,7 @@ fi echo $ac_n "checking for standard C library version information""... $ac_c" 1>&6 -echo "configure:3253: checking for standard C library version information" >&5 +echo "configure:3325: checking for standard C library version information" >&5 case "$canonical" in *-*-linux*) @@ -3361,7 +3433,7 @@ if test "$add_runtime_path" = "yes"; then echo $ac_n "checking "for runtime libraries flag"""... $ac_c" 1>&6 -echo "configure:3365: checking "for runtime libraries flag"" >&5 +echo "configure:3437: checking "for runtime libraries flag"" >&5 case "$opsys" in sol2 ) dash_r="-R" ;; decosf* | linux* | irix*) dash_r="-rpath " ;; @@ -3383,14 +3455,14 @@ done fi cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* dash_r="$try_dash_r" else @@ -3491,10 +3563,10 @@ fi after_morecore_hook_exists=yes echo $ac_n "checking for malloc_set_state""... $ac_c" 1>&6 -echo "configure:3495: checking for malloc_set_state" >&5 +echo "configure:3567: checking for malloc_set_state" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3593: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_malloc_set_state=yes" else @@ -3537,16 +3609,16 @@ fi echo $ac_n "checking whether __after_morecore_hook exists""... $ac_c" 1>&6 -echo "configure:3541: checking whether __after_morecore_hook exists" >&5 +echo "configure:3613: checking whether __after_morecore_hook exists" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3622: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "$ac_t""yes" 1>&6 else @@ -3602,7 +3674,7 @@ # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3606: checking for $ac_word" >&5 +echo "configure:3678: checking for $ac_word" >&5 if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. @@ -3657,7 +3729,7 @@ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:3661: checking for a BSD compatible install" >&5 +echo "configure:3733: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" @@ -3711,7 +3783,7 @@ # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3715: checking for $ac_word" >&5 +echo "configure:3787: checking for $ac_word" >&5 if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. @@ -3743,15 +3815,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3747: checking for $ac_hdr" >&5 +echo "configure:3819: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3755: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3827: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3781,10 +3853,10 @@ done echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 -echo "configure:3785: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo "configure:3857: checking for sys/wait.h that is POSIX.1 compatible" >&5 cat > conftest.$ac_ext < #include @@ -3800,7 +3872,7 @@ s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF -if { (eval echo configure:3804: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3876: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -3824,10 +3896,10 @@ fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:3828: checking for ANSI C header files" >&5 +echo "configure:3900: checking for ANSI C header files" >&5 cat > conftest.$ac_ext < #include @@ -3835,7 +3907,7 @@ #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3839: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3911: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3852,7 +3924,7 @@ if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -3870,7 +3942,7 @@ if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -3888,7 +3960,7 @@ if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -3899,7 +3971,7 @@ exit (0); } EOF -if { (eval echo configure:3903: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:3975: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then : else @@ -3925,10 +3997,10 @@ fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:3929: checking whether time.h and sys/time.h may both be included" >&5 +echo "configure:4001: checking whether time.h and sys/time.h may both be included" >&5 cat > conftest.$ac_ext < #include @@ -3937,7 +4009,7 @@ struct tm *tp; ; return 0; } EOF -if { (eval echo configure:3941: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4013: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -3961,10 +4033,10 @@ fi echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6 -echo "configure:3965: checking for sys_siglist declaration in signal.h or unistd.h" >&5 +echo "configure:4037: checking for sys_siglist declaration in signal.h or unistd.h" >&5 cat > conftest.$ac_ext < #include @@ -3976,7 +4048,7 @@ char *msg = *(sys_siglist + 1); ; return 0; } EOF -if { (eval echo configure:3980: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4052: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_decl_sys_siglist=yes else @@ -4002,9 +4074,9 @@ echo $ac_n "checking for utime""... $ac_c" 1>&6 -echo "configure:4006: checking for utime" >&5 +echo "configure:4078: checking for utime" >&5 cat > conftest.$ac_ext < #include @@ -4012,7 +4084,7 @@ struct utimbuf x; x.actime = x.modtime = 0; utime ("/", &x); ; return 0; } EOF -if { (eval echo configure:4016: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4088: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 { test "$extra_verbose" = "yes" && cat << \EOF @@ -4031,10 +4103,10 @@ for ac_func in utimes do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:4035: checking for $ac_func" >&5 +echo "configure:4107: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4133: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -4089,10 +4161,10 @@ echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:4093: checking return type of signal handlers" >&5 +echo "configure:4165: checking return type of signal handlers" >&5 cat > conftest.$ac_ext < #include @@ -4109,7 +4181,7 @@ int i; ; return 0; } EOF -if { (eval echo configure:4113: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4185: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -4131,10 +4203,10 @@ echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:4135: checking for size_t" >&5 +echo "configure:4207: checking for size_t" >&5 cat > conftest.$ac_ext < #if STDC_HEADERS @@ -4165,10 +4237,10 @@ fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:4169: checking for pid_t" >&5 +echo "configure:4241: checking for pid_t" >&5 cat > conftest.$ac_ext < #if STDC_HEADERS @@ -4199,10 +4271,10 @@ fi echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:4203: checking for uid_t in sys/types.h" >&5 +echo "configure:4275: checking for uid_t in sys/types.h" >&5 cat > conftest.$ac_ext < EOF @@ -4238,10 +4310,10 @@ fi echo $ac_n "checking for mode_t""... $ac_c" 1>&6 -echo "configure:4242: checking for mode_t" >&5 +echo "configure:4314: checking for mode_t" >&5 cat > conftest.$ac_ext < #if STDC_HEADERS @@ -4272,10 +4344,10 @@ fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 -echo "configure:4276: checking for off_t" >&5 +echo "configure:4348: checking for off_t" >&5 cat > conftest.$ac_ext < #if STDC_HEADERS @@ -4306,10 +4378,10 @@ fi echo $ac_n "checking for ssize_t""... $ac_c" 1>&6 -echo "configure:4310: checking for ssize_t" >&5 +echo "configure:4382: checking for ssize_t" >&5 cat > conftest.$ac_ext < #if STDC_HEADERS @@ -4342,9 +4414,9 @@ if test "$ac_cv_header_inttypes_h" != "yes"; then echo $ac_n "checking for intptr_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:4346: checking for intptr_t in sys/types.h" >&5 +echo "configure:4418: checking for intptr_t in sys/types.h" >&5 cat > conftest.$ac_ext < intptr_t x; @@ -4353,7 +4425,7 @@ ; return 0; } EOF -if { (eval echo configure:4357: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4429: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 { test "$extra_verbose" = "yes" && cat << \EOF @@ -4374,9 +4446,9 @@ fi echo $ac_n "checking for socklen_t""... $ac_c" 1>&6 -echo "configure:4378: checking for socklen_t" >&5 +echo "configure:4450: checking for socklen_t" >&5 cat > conftest.$ac_ext < #include @@ -4386,7 +4458,7 @@ ; return 0; } EOF -if { (eval echo configure:4390: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4462: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 else @@ -4395,7 +4467,7 @@ rm -rf conftest* cat > conftest.$ac_ext < #include @@ -4405,7 +4477,7 @@ ; return 0; } EOF -if { (eval echo configure:4409: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4481: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""size_t" 1>&6 @@ -4437,9 +4509,9 @@ rm -f conftest* echo $ac_n "checking for struct timeval""... $ac_c" 1>&6 -echo "configure:4441: checking for struct timeval" >&5 +echo "configure:4513: checking for struct timeval" >&5 cat > conftest.$ac_ext < @@ -4455,7 +4527,7 @@ static struct timeval x; x.tv_sec = x.tv_usec; ; return 0; } EOF -if { (eval echo configure:4459: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4531: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 HAVE_TIMEVAL=yes @@ -4477,10 +4549,10 @@ rm -f conftest* echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:4481: checking whether struct tm is in sys/time.h or time.h" >&5 +echo "configure:4553: checking whether struct tm is in sys/time.h or time.h" >&5 cat > conftest.$ac_ext < #include @@ -4488,7 +4560,7 @@ struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:4492: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4564: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -4512,10 +4584,10 @@ fi echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6 -echo "configure:4516: checking for tm_zone in struct tm" >&5 +echo "configure:4588: checking for tm_zone in struct tm" >&5 cat > conftest.$ac_ext < #include <$ac_cv_struct_tm> @@ -4523,7 +4595,7 @@ struct tm tm; tm.tm_zone; ; return 0; } EOF -if { (eval echo configure:4527: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4599: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm_zone=yes else @@ -4546,10 +4618,10 @@ else echo $ac_n "checking for tzname""... $ac_c" 1>&6 -echo "configure:4550: checking for tzname" >&5 +echo "configure:4622: checking for tzname" >&5 cat > conftest.$ac_ext < #ifndef tzname /* For SGI. */ @@ -4559,7 +4631,7 @@ atoi(*tzname); ; return 0; } EOF -if { (eval echo configure:4563: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4635: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_var_tzname=yes else @@ -4585,10 +4657,10 @@ echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:4589: checking for working const" >&5 +echo "configure:4661: checking for working const" >&5 cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4713: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -4662,7 +4734,7 @@ echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:4666: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:4738: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` cat > conftestmake <<\EOF @@ -4687,12 +4759,12 @@ echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:4691: checking whether byte ordering is bigendian" >&5 +echo "configure:4763: checking whether byte ordering is bigendian" >&5 ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -4703,11 +4775,11 @@ #endif ; return 0; } EOF -if { (eval echo configure:4707: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4779: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -4718,7 +4790,7 @@ #endif ; return 0; } EOF -if { (eval echo configure:4722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4794: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -4735,7 +4807,7 @@ rm -f conftest* if test $ac_cv_c_bigendian = unknown; then cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:4824: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_c_bigendian=no else @@ -4775,10 +4847,10 @@ echo $ac_n "checking size of short""... $ac_c" 1>&6 -echo "configure:4779: checking size of short" >&5 +echo "configure:4851: checking size of short" >&5 cat > conftest.$ac_ext < #include @@ -4790,7 +4862,7 @@ exit(0); } EOF -if { (eval echo configure:4794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:4866: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_sizeof_short=`cat conftestval` else @@ -4818,10 +4890,10 @@ exit 1 fi echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:4822: checking size of int" >&5 +echo "configure:4894: checking size of int" >&5 cat > conftest.$ac_ext < #include @@ -4833,7 +4905,7 @@ exit(0); } EOF -if { (eval echo configure:4837: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:4909: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_sizeof_int=`cat conftestval` else @@ -4855,10 +4927,10 @@ echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:4859: checking size of long" >&5 +echo "configure:4931: checking size of long" >&5 cat > conftest.$ac_ext < #include @@ -4870,7 +4942,7 @@ exit(0); } EOF -if { (eval echo configure:4874: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:4946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_sizeof_long=`cat conftestval` else @@ -4892,10 +4964,10 @@ echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:4896: checking size of long long" >&5 +echo "configure:4968: checking size of long long" >&5 cat > conftest.$ac_ext < #include @@ -4907,7 +4979,7 @@ exit(0); } EOF -if { (eval echo configure:4911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:4983: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_sizeof_long_long=`cat conftestval` else @@ -4929,10 +5001,10 @@ echo $ac_n "checking size of void *""... $ac_c" 1>&6 -echo "configure:4933: checking size of void *" >&5 +echo "configure:5005: checking size of void *" >&5 cat > conftest.$ac_ext < #include @@ -4944,7 +5016,7 @@ exit(0); } EOF -if { (eval echo configure:4948: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:5020: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_sizeof_void_p=`cat conftestval` else @@ -4966,10 +5038,10 @@ echo $ac_n "checking size of double""... $ac_c" 1>&6 -echo "configure:4970: checking size of double" >&5 +echo "configure:5042: checking size of double" >&5 cat > conftest.$ac_ext < #include @@ -4981,7 +5053,7 @@ exit(0); } EOF -if { (eval echo configure:4985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:5057: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_sizeof_double=`cat conftestval` else @@ -5004,7 +5076,7 @@ echo $ac_n "checking for long file names""... $ac_c" 1>&6 -echo "configure:5008: checking for long file names" >&5 +echo "configure:5080: checking for long file names" >&5 ac_cv_sys_long_file_names=yes # Test for long file names in all the places we know might matter: @@ -5050,10 +5122,10 @@ echo $ac_n "checking for sin""... $ac_c" 1>&6 -echo "configure:5054: checking for sin" >&5 +echo "configure:5126: checking for sin" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5152: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_sin=yes" else @@ -5094,12 +5166,12 @@ echo "$ac_t""no" 1>&6 echo $ac_n "checking for sin in -lm""... $ac_c" 1>&6 -echo "configure:5098: checking for sin in -lm" >&5 +echo "configure:5170: checking for sin in -lm" >&5 ac_lib_var=`echo m'_'sin | sed 'y%./+-%__p_%'` xe_check_libs=" -lm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5145,14 +5217,14 @@ cat > conftest.$ac_ext < int main() { return atanh(1.0) + asinh(1.0) + acosh(1.0); ; return 0; } EOF -if { (eval echo configure:5156: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5228: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_INVERSE_HYPERBOLIC @@ -5171,10 +5243,10 @@ for ac_func in mkstemp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5175: checking for $ac_func" >&5 +echo "configure:5247: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5273: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5226,14 +5298,14 @@ echo "checking type of mail spool file locking" 1>&6 -echo "configure:5230: checking type of mail spool file locking" >&5 +echo "configure:5302: checking type of mail spool file locking" >&5 for ac_func in lockf flock do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5234: checking for $ac_func" >&5 +echo "configure:5306: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5332: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5319,7 +5391,15 @@ elif test "$mail_locking" = "pop"; then with_pop=yes mail_locking= -else mail_locking="dot-locking"; { test "$extra_verbose" = "yes" && cat << \EOF +elif test "$mail_locking" = "mmdf"; then { test "$extra_verbose" = "yes" && cat << \EOF + Defining MAIL_LOCK_MMDF +EOF +cat >> confdefs.h <<\EOF +#define MAIL_LOCK_MMDF 1 +EOF +} + +else mail_locking="file"; { test "$extra_verbose" = "yes" && cat << \EOF Defining MAIL_LOCK_DOT EOF cat >> confdefs.h <<\EOF @@ -5338,12 +5418,12 @@ case "$opsys" in decosf*) echo $ac_n "checking for cma_open in -lpthreads""... $ac_c" 1>&6 -echo "configure:5342: checking for cma_open in -lpthreads" >&5 +echo "configure:5422: checking for cma_open in -lpthreads" >&5 ac_lib_var=`echo pthreads'_'cma_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lpthreads " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5438: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5391,7 +5471,7 @@ echo $ac_n "checking whether the -xildoff compiler flag is required""... $ac_c" 1>&6 -echo "configure:5395: checking whether the -xildoff compiler flag is required" >&5 +echo "configure:5475: checking whether the -xildoff compiler flag is required" >&5 if ${CC-cc} '-###' -xildon no_such_file.c 2>&1 | grep '^[^ ]*/ild ' > /dev/null ; then if ${CC-cc} '-###' -xildoff no_such_file.c 2>&1 | grep '^[^ ]*/ild ' > /dev/null ; then echo "$ac_t""no" 1>&6; @@ -5403,7 +5483,7 @@ if test "$opsys" = "sol2"; then if test "$os_release" -ge 506; then echo $ac_n "checking for \"-z ignore\" linker flag""... $ac_c" 1>&6 -echo "configure:5407: checking for \"-z ignore\" linker flag" >&5 +echo "configure:5487: checking for \"-z ignore\" linker flag" >&5 case "`ld -h 2>&1`" in *-z\ ignore\|record* ) echo "$ac_t""yes" 1>&6 ld_switch_site="-z ignore $ld_switch_site" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-z ignore\" to \$ld_switch_site"; fi ;; @@ -5414,7 +5494,7 @@ echo "checking "for specified window system"" 1>&6 -echo "configure:5418: checking "for specified window system"" >&5 +echo "configure:5498: checking "for specified window system"" >&5 GNOME_CONFIG=no @@ -5422,7 +5502,7 @@ if test "$with_gnome" != "no"; then echo $ac_n "checking for GNOME configuration script""... $ac_c" 1>&6 -echo "configure:5426: checking for GNOME configuration script" >&5 +echo "configure:5506: checking for GNOME configuration script" >&5 for possible in gnome-config do possible_version=`${possible} --version 2> /dev/null` @@ -5453,7 +5533,7 @@ if test "$with_gtk" != "no";then echo $ac_n "checking for GTK configuration script""... $ac_c" 1>&6 -echo "configure:5457: checking for GTK configuration script" >&5 +echo "configure:5537: checking for GTK configuration script" >&5 for possible in gtk12-config gtk14-config gtk-config do possible_version=`${possible} --version 2> /dev/null` @@ -5475,18 +5555,18 @@ if test "${GTK_CONFIG}" != "no"; then echo $ac_n "checking gtk version""... $ac_c" 1>&6 -echo "configure:5479: checking gtk version" >&5 +echo "configure:5559: checking gtk version" >&5 GTK_VERSION=`${GTK_CONFIG} --version` echo "$ac_t""${GTK_VERSION}" 1>&6 echo $ac_n "checking gtk libs""... $ac_c" 1>&6 -echo "configure:5484: checking gtk libs" >&5 +echo "configure:5564: checking gtk libs" >&5 GTK_LIBS=`${GTK_CONFIG} --libs` libs_gtk="$libs_gtk ${GTK_LIBS}" && if test "$extra_verbose" = "yes"; then echo " Appending \"${GTK_LIBS}\" to \$libs_gtk"; fi echo "$ac_t""${GTK_LIBS}" 1>&6 echo $ac_n "checking gtk cflags""... $ac_c" 1>&6 -echo "configure:5490: checking gtk cflags" >&5 +echo "configure:5570: checking gtk cflags" >&5 GTK_CFLAGS=`${GTK_CONFIG} --cflags` if test "$GCC" = "yes"; then GTK_CFLAGS="${GTK_CFLAGS} -Wno-shadow" @@ -5496,19 +5576,19 @@ echo $ac_n "checking for main in -lgdk_imlib""... $ac_c" 1>&6 -echo "configure:5500: checking for main in -lgdk_imlib" >&5 +echo "configure:5580: checking for main in -lgdk_imlib" >&5 ac_lib_var=`echo gdk_imlib'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lgdk_imlib " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5530,12 +5610,12 @@ echo $ac_n "checking for Imlib_init in -lImlib""... $ac_c" 1>&6 -echo "configure:5534: checking for Imlib_init in -lImlib" >&5 +echo "configure:5614: checking for Imlib_init in -lImlib" >&5 ac_lib_var=`echo Imlib'_'Imlib_init | sed 'y%./+-%__p_%'` xe_check_libs=" -lImlib " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5630: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5569,10 +5649,10 @@ for ac_func in gdk_imlib_init do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5573: checking for $ac_func" >&5 +echo "configure:5653: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5679: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5679,15 +5759,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5683: checking for $ac_hdr" >&5 +echo "configure:5763: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5691: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5771: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5718,19 +5798,19 @@ echo $ac_n "checking for main in -lxml""... $ac_c" 1>&6 -echo "configure:5722: checking for main in -lxml" >&5 +echo "configure:5802: checking for main in -lxml" >&5 ac_lib_var=`echo xml'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lxml " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5814: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5752,19 +5832,19 @@ echo $ac_n "checking for main in -lglade""... $ac_c" 1>&6 -echo "configure:5756: checking for main in -lglade" >&5 +echo "configure:5836: checking for main in -lglade" >&5 ac_lib_var=`echo glade'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lglade " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5848: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5786,19 +5866,19 @@ echo $ac_n "checking for main in -lglade-gnome""... $ac_c" 1>&6 -echo "configure:5790: checking for main in -lglade-gnome" >&5 +echo "configure:5870: checking for main in -lglade-gnome" >&5 ac_lib_var=`echo glade-gnome'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lglade-gnome " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5882: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5819,7 +5899,7 @@ cat > conftest.$ac_ext < EOF @@ -5878,7 +5958,7 @@ # Uses ac_ vars as temps to allow command line to override cache and checks. # --without-x overrides everything else, but does not touch the cache. echo $ac_n "checking for X""... $ac_c" 1>&6 -echo "configure:5882: checking for X" >&5 +echo "configure:5962: checking for X" >&5 # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then @@ -5938,12 +6018,12 @@ # First, try using that file with no special directory specified. cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5947: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6027: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -6012,14 +6092,14 @@ ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* LIBS="$ac_save_LIBS" # We can link X programs with no special library path. @@ -6128,17 +6208,17 @@ case "`(uname -sr) 2>/dev/null`" in "SunOS 5"*) echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 -echo "configure:6132: checking whether -R must be followed by a space" >&5 +echo "configure:6212: checking whether -R must be followed by a space" >&5 ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6222: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_R_nospace=yes else @@ -6154,14 +6234,14 @@ else LIBS="$ac_xsave_LIBS -R $x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6245: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_R_space=yes else @@ -6197,12 +6277,12 @@ else echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 -echo "configure:6201: checking for dnet_ntoa in -ldnet" >&5 +echo "configure:6281: checking for dnet_ntoa in -ldnet" >&5 ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` xe_check_libs=" -ldnet " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6297: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6237,12 +6317,12 @@ if test $ac_cv_lib_dnet_dnet_ntoa = no; then echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 -echo "configure:6241: checking for dnet_ntoa in -ldnet_stub" >&5 +echo "configure:6321: checking for dnet_ntoa in -ldnet_stub" >&5 ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` xe_check_libs=" -ldnet_stub " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6282,10 +6362,10 @@ # The nsl library prevents programs from opening the X display # on Irix 5.2, according to dickey@clark.net. echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 -echo "configure:6286: checking for gethostbyname" >&5 +echo "configure:6366: checking for gethostbyname" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostbyname=yes" else @@ -6329,12 +6409,12 @@ if test $ac_cv_func_gethostbyname = no; then echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:6333: checking for gethostbyname in -lnsl" >&5 +echo "configure:6413: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` xe_check_libs=" -lnsl " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6429: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6375,10 +6455,10 @@ # -lsocket must be given before -lnsl if both are needed. # We assume that if connect needs -lnsl, so does gethostbyname. echo $ac_n "checking for connect""... $ac_c" 1>&6 -echo "configure:6379: checking for connect" >&5 +echo "configure:6459: checking for connect" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6485: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_connect=yes" else @@ -6424,12 +6504,12 @@ xe_msg_checking="for connect in -lsocket" test -n "$X_EXTRA_LIBS" && xe_msg_checking="$xe_msg_checking using extra libs $X_EXTRA_LIBS" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:6428: checking "$xe_msg_checking"" >&5 +echo "configure:6508: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` xe_check_libs=" -lsocket $X_EXTRA_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6524: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6464,10 +6544,10 @@ # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. echo $ac_n "checking for remove""... $ac_c" 1>&6 -echo "configure:6468: checking for remove" >&5 +echo "configure:6548: checking for remove" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6574: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_remove=yes" else @@ -6511,12 +6591,12 @@ if test $ac_cv_func_remove = no; then echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 -echo "configure:6515: checking for remove in -lposix" >&5 +echo "configure:6595: checking for remove in -lposix" >&5 ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` xe_check_libs=" -lposix " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6611: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6551,10 +6631,10 @@ # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. echo $ac_n "checking for shmat""... $ac_c" 1>&6 -echo "configure:6555: checking for shmat" >&5 +echo "configure:6635: checking for shmat" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6661: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_shmat=yes" else @@ -6598,12 +6678,12 @@ if test $ac_cv_func_shmat = no; then echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 -echo "configure:6602: checking for shmat in -lipc" >&5 +echo "configure:6682: checking for shmat in -lipc" >&5 ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` xe_check_libs=" -lipc " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6698: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6650,12 +6730,12 @@ xe_msg_checking="for IceConnectionNumber in -lICE" test -n "$X_EXTRA_LIBS" && xe_msg_checking="$xe_msg_checking using extra libs $X_EXTRA_LIBS" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:6654: checking "$xe_msg_checking"" >&5 +echo "configure:6734: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` xe_check_libs=" -lICE $X_EXTRA_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6750: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6712,15 +6792,15 @@ ac_safe=`echo "Xm/Xm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for Xm/Xm.h""... $ac_c" 1>&6 -echo "configure:6716: checking for Xm/Xm.h" >&5 +echo "configure:6796: checking for Xm/Xm.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6724: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6804: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -6737,12 +6817,12 @@ echo "$ac_t""yes" 1>&6 echo $ac_n "checking for XmStringFree in -lXm""... $ac_c" 1>&6 -echo "configure:6741: checking for XmStringFree in -lXm" >&5 +echo "configure:6821: checking for XmStringFree in -lXm" >&5 ac_lib_var=`echo Xm'_'XmStringFree | sed 'y%./+-%__p_%'` xe_check_libs=" -lXm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6837: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6905,7 +6985,7 @@ echo "checking for X defines extracted by xmkmf" 1>&6 -echo "configure:6909: checking for X defines extracted by xmkmf" >&5 +echo "configure:6989: checking for X defines extracted by xmkmf" >&5 rm -fr conftestdir if mkdir conftestdir; then cd conftestdir @@ -6954,15 +7034,15 @@ ac_safe=`echo "X11/Intrinsic.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Intrinsic.h""... $ac_c" 1>&6 -echo "configure:6958: checking for X11/Intrinsic.h" >&5 +echo "configure:7038: checking for X11/Intrinsic.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6966: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7046: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -6986,12 +7066,12 @@ echo $ac_n "checking for XOpenDisplay in -lX11""... $ac_c" 1>&6 -echo "configure:6990: checking for XOpenDisplay in -lX11" >&5 +echo "configure:7070: checking for XOpenDisplay in -lX11" >&5 ac_lib_var=`echo X11'_'XOpenDisplay | sed 'y%./+-%__p_%'` xe_check_libs=" -lX11 " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7027,12 +7107,12 @@ xe_msg_checking="for XGetFontProperty in -lX11" test -n "-b i486-linuxaout" && xe_msg_checking="$xe_msg_checking using extra libs -b i486-linuxaout" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:7031: checking "$xe_msg_checking"" >&5 +echo "configure:7111: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo X11'_'XGetFontProperty | sed 'y%./+-%__p_%'` xe_check_libs=" -lX11 -b i486-linuxaout" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7127: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7070,12 +7150,12 @@ echo $ac_n "checking for XShapeSelectInput in -lXext""... $ac_c" 1>&6 -echo "configure:7074: checking for XShapeSelectInput in -lXext" >&5 +echo "configure:7154: checking for XShapeSelectInput in -lXext" >&5 ac_lib_var=`echo Xext'_'XShapeSelectInput | sed 'y%./+-%__p_%'` xe_check_libs=" -lXext " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7170: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7109,12 +7189,12 @@ echo $ac_n "checking for XtOpenDisplay in -lXt""... $ac_c" 1>&6 -echo "configure:7113: checking for XtOpenDisplay in -lXt" >&5 +echo "configure:7193: checking for XtOpenDisplay in -lXt" >&5 ac_lib_var=`echo Xt'_'XtOpenDisplay | sed 'y%./+-%__p_%'` xe_check_libs=" -lXt " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7209: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7148,14 +7228,14 @@ echo $ac_n "checking the version of X11 being used""... $ac_c" 1>&6 -echo "configure:7152: checking the version of X11 being used" >&5 +echo "configure:7232: checking the version of X11 being used" >&5 cat > conftest.$ac_ext < int main(int c, char *v[]) { return c>1 ? XlibSpecificationRelease : 0; } EOF -if { (eval echo configure:7159: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:7239: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ./conftest foobar; x11_release=$? else @@ -7186,10 +7266,10 @@ for ac_func in XConvertCase do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7190: checking for $ac_func" >&5 +echo "configure:7270: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7244,15 +7324,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:7248: checking for $ac_hdr" >&5 +echo "configure:7328: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7256: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7336: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -7285,10 +7365,10 @@ for ac_func in XRegisterIMInstantiateCallback do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7289: checking for $ac_func" >&5 +echo "configure:7369: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7395: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7339,9 +7419,9 @@ done echo $ac_n "checking for standard XRegisterIMInstantiateCallback prototype""... $ac_c" 1>&6 -echo "configure:7343: checking for standard XRegisterIMInstantiateCallback prototype" >&5 +echo "configure:7423: checking for standard XRegisterIMInstantiateCallback prototype" >&5 cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7437: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 else @@ -7374,12 +7454,12 @@ test -z "$with_xmu" && { echo $ac_n "checking for XmuReadBitmapDataFromFile in -lXmu""... $ac_c" 1>&6 -echo "configure:7378: checking for XmuReadBitmapDataFromFile in -lXmu" >&5 +echo "configure:7458: checking for XmuReadBitmapDataFromFile in -lXmu" >&5 ac_lib_var=`echo Xmu'_'XmuReadBitmapDataFromFile | sed 'y%./+-%__p_%'` xe_check_libs=" -lXmu " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7474: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7429,19 +7509,19 @@ echo $ac_n "checking for main in -lXbsd""... $ac_c" 1>&6 -echo "configure:7433: checking for main in -lXbsd" >&5 +echo "configure:7513: checking for main in -lXbsd" >&5 ac_lib_var=`echo Xbsd'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lXbsd " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7525: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7478,22 +7558,22 @@ fi if test "$with_msw" != "no"; then echo "checking for MS-Windows" 1>&6 -echo "configure:7482: checking for MS-Windows" >&5 +echo "configure:7562: checking for MS-Windows" >&5 echo $ac_n "checking for main in -lgdi32""... $ac_c" 1>&6 -echo "configure:7485: checking for main in -lgdi32" >&5 +echo "configure:7565: checking for main in -lgdi32" >&5 ac_lib_var=`echo gdi32'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lgdi32 " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7577: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7544,12 +7624,12 @@ test "$with_widgets" != "no" && with_widgets=msw fi cat > conftest.$ac_ext < int main() { return (open("/dev/windows", O_RDONLY, 0) > 0)? 0 : 1; } EOF -if { (eval echo configure:7553: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:7633: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_MSG_SELECT @@ -7610,15 +7690,15 @@ if test "$with_x11" = "yes"; then ac_safe=`echo "X11/extensions/shape.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/extensions/shape.h""... $ac_c" 1>&6 -echo "configure:7614: checking for X11/extensions/shape.h" >&5 +echo "configure:7694: checking for X11/extensions/shape.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7622: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7702: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -7668,7 +7748,7 @@ esac echo "checking for WM_COMMAND option" 1>&6 -echo "configure:7672: checking for WM_COMMAND option" >&5; +echo "configure:7752: checking for WM_COMMAND option" >&5; if test "$with_wmcommand" != "no"; then { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_WMCOMMAND @@ -7683,15 +7763,15 @@ test -z "$with_xauth" && test "$window_system" = "none" && with_xauth=no test -z "$with_xauth" && { ac_safe=`echo "X11/Xauth.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Xauth.h""... $ac_c" 1>&6 -echo "configure:7687: checking for X11/Xauth.h" >&5 +echo "configure:7767: checking for X11/Xauth.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7695: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7775: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -7714,12 +7794,12 @@ } test -z "$with_xauth" && { echo $ac_n "checking for XauGetAuthByAddr in -lXau""... $ac_c" 1>&6 -echo "configure:7718: checking for XauGetAuthByAddr in -lXau" >&5 +echo "configure:7798: checking for XauGetAuthByAddr in -lXau" >&5 ac_lib_var=`echo Xau'_'XauGetAuthByAddr | sed 'y%./+-%__p_%'` xe_check_libs=" -lXau " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7814: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7781,7 +7861,7 @@ if test "$with_modules" != "no"; then echo "checking for module support" 1>&6 -echo "configure:7785: checking for module support" >&5 +echo "configure:7865: checking for module support" >&5 case "$opsys" in mingw* | cygwin* ) have_dl=yes ;; @@ -7798,15 +7878,15 @@ * ) ac_safe=`echo "dlfcn.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for dlfcn.h""... $ac_c" 1>&6 -echo "configure:7802: checking for dlfcn.h" >&5 +echo "configure:7882: checking for dlfcn.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7810: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7890: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -7823,16 +7903,16 @@ echo "$ac_t""yes" 1>&6 echo $ac_n "checking for dlopen in -lc""... $ac_c" 1>&6 -echo "configure:7827: checking for dlopen in -lc" >&5 +echo "configure:7907: checking for dlopen in -lc" >&5 cat > conftest.$ac_ext < int main() { dlopen ("", 0); ; return 0; } EOF -if { (eval echo configure:7836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* have_dl=yes else @@ -7841,18 +7921,18 @@ rm -rf conftest* echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "configure:7845: checking for dlopen in -ldl" >&5 +echo "configure:7925: checking for dlopen in -ldl" >&5 ac_save_LIBS="$LIBS" LIBS="$LIBS -ldl" cat > conftest.$ac_ext < int main() { dlopen ("", 0); ; return 0; } EOF -if { (eval echo configure:7856: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7936: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* have_dl=yes else @@ -7861,17 +7941,17 @@ rm -rf conftest* echo $ac_n "checking for dlopen in -lsvld""... $ac_c" 1>&6 -echo "configure:7865: checking for dlopen in -lsvld" >&5 +echo "configure:7945: checking for dlopen in -lsvld" >&5 LIBS="$ac_save_LIBS -lsvld" cat > conftest.$ac_ext < int main() { dlopen ("", 0); ; return 0; } EOF -if { (eval echo configure:7875: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* have_dl=yes else @@ -7901,15 +7981,15 @@ else ac_safe=`echo "dl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for dl.h""... $ac_c" 1>&6 -echo "configure:7905: checking for dl.h" >&5 +echo "configure:7985: checking for dl.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7913: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7993: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -7926,16 +8006,16 @@ echo "$ac_t""yes" 1>&6 echo $ac_n "checking for shl_load in -lc""... $ac_c" 1>&6 -echo "configure:7930: checking for shl_load in -lc" >&5 +echo "configure:8010: checking for shl_load in -lc" >&5 cat > conftest.$ac_ext < int main() { shl_load ("", 0, 0); ; return 0; } EOF -if { (eval echo configure:7939: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8019: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* have_dl=yes else @@ -7944,18 +8024,18 @@ rm -rf conftest* echo $ac_n "checking for shl_load in -ldl""... $ac_c" 1>&6 -echo "configure:7948: checking for shl_load in -ldl" >&5 +echo "configure:8028: checking for shl_load in -ldl" >&5 ac_save_LIBS="$LIBS" LIBS="$LIBS -ldld" cat > conftest.$ac_ext < int main() { shl_load ("", 0, 0); ; return 0; } EOF -if { (eval echo configure:7959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* have_dl=yes else @@ -7983,15 +8063,15 @@ else ac_safe=`echo "ltdl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ltdl.h""... $ac_c" 1>&6 -echo "configure:7987: checking for ltdl.h" >&5 +echo "configure:8067: checking for ltdl.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7995: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8075: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -8008,18 +8088,18 @@ echo "$ac_t""yes" 1>&6 echo $ac_n "checking for lt_dlinit in -lltdl""... $ac_c" 1>&6 -echo "configure:8012: checking for lt_dlinit in -lltdl" >&5 +echo "configure:8092: checking for lt_dlinit in -lltdl" >&5 ac_save_LIBS="$LIBS" LIBS="$LIBS -lltdl" cat > conftest.$ac_ext < int main() { lt_dlinit (); ; return 0; } EOF -if { (eval echo configure:8023: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* have_dl=yes else @@ -8060,7 +8140,7 @@ xealias=$internal_configuration echo "checking how to build dynamic libraries for ${xehost}" 1>&6 -echo "configure:8064: checking how to build dynamic libraries for ${xehost}" >&5 +echo "configure:8144: checking how to build dynamic libraries for ${xehost}" >&5 # Transform *-*-linux* to *-*-linux-gnu*, to support old configure scripts. case "$xehost" in *-*-linux-gnu*) ;; @@ -8088,9 +8168,9 @@ XEGCC=yes else echo $ac_n "checking checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:8092: checking checking whether we are using GNU C" >&5 +echo "configure:8172: checking checking whether we are using GNU C" >&5 cat > conftest.$ac_ext <&6 -echo "configure:8116: checking how to produce PIC code" >&5 +echo "configure:8196: checking how to produce PIC code" >&5 wl= can_build_shared=yes @@ -8216,18 +8296,18 @@ # Check to make sure the dll_cflags actually works. echo $ac_n "checking if PIC flag ${dll_cflags} really works""... $ac_c" 1>&6 -echo "configure:8220: checking if PIC flag ${dll_cflags} really works" >&5 +echo "configure:8300: checking if PIC flag ${dll_cflags} really works" >&5 save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $dll_cflags -DPIC" cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:8311: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # On HP-UX, the stripped-down bundled CC doesn't accept +Z, but also @@ -8258,7 +8338,7 @@ xldf= xcldf= echo $ac_n "checking if C compiler can produce shared libraries""... $ac_c" 1>&6 -echo "configure:8262: checking if C compiler can produce shared libraries" >&5 +echo "configure:8342: checking if C compiler can produce shared libraries" >&5 if test "$XEGCC" = yes -o "$__ICC" = yes; then case "$xehost_os" in *darwin*) @@ -8317,14 +8397,14 @@ xe_libs= ac_link='${CC-cc} -o conftest $CFLAGS '"$xe_cppflags $xe_ldflags"' conftest.$ac_ext '"$xe_libs"' 1>&5' cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8408: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* cc_produces_so=yes else @@ -8349,7 +8429,7 @@ if test "$XEGCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 -echo "configure:8353: checking for ld used by GCC" >&5 +echo "configure:8433: checking for ld used by GCC" >&5 ac_prog=`($CC -print-prog-name=ld) 2>&5` case "$ac_prog" in # Accept absolute paths. @@ -8375,7 +8455,7 @@ esac else echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 -echo "configure:8379: checking for GNU ld" >&5 +echo "configure:8459: checking for GNU ld" >&5 fi if test -z "$LTLD"; then @@ -8413,7 +8493,7 @@ # Check to see if it really is or isn't GNU ld. echo $ac_n "checking if the linker is GNU ld""... $ac_c" 1>&6 -echo "configure:8417: checking if the linker is GNU ld" >&5 +echo "configure:8497: checking if the linker is GNU ld" >&5 # I'd rather use --version here, but apparently some GNU ld's only accept -v. if $LTLD -v 2>&1 &5; then xe_gnu_ld=yes @@ -8448,7 +8528,7 @@ # OK - only NOW do we futz about with ld. # See if the linker supports building shared libraries. echo $ac_n "checking whether the linker supports shared libraries""... $ac_c" 1>&6 -echo "configure:8452: checking whether the linker supports shared libraries" >&5 +echo "configure:8532: checking whether the linker supports shared libraries" >&5 dll_ld=$CC dll_ldflags=$LDFLAGS ld_shlibs=yes @@ -8661,10 +8741,10 @@ for ac_func in dlerror _dlerror do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:8665: checking for $ac_func" >&5 +echo "configure:8745: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8771: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -8731,7 +8811,7 @@ fi if test "$with_modules" != "yes"; then MOD_CC="$XEMACS_CC" - MODCFLAGS="\$(CFLAGS) -I../../src -I\$(srcdir)/../../src" + MODCFLAGS="\$(XE_CFLAGS) -I../../src -I\$(srcdir)/../../src" INSTALLPATH="" MOD_INSTALL_PROGRAM="true" OBJECT_TO_BUILD="\$(MODNAME).o" @@ -8751,15 +8831,15 @@ for dir in "" "Tt/" "desktop/" ; do ac_safe=`echo "${dir}tt_c.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ${dir}tt_c.h""... $ac_c" 1>&6 -echo "configure:8755: checking for ${dir}tt_c.h" >&5 +echo "configure:8835: checking for ${dir}tt_c.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8763: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -8795,12 +8875,12 @@ xe_msg_checking="for tt_message_create in -ltt" test -n "$extra_libs" && xe_msg_checking="$xe_msg_checking using extra libs $extra_libs" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:8799: checking "$xe_msg_checking"" >&5 +echo "configure:8879: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo tt'_'tt_message_create | sed 'y%./+-%__p_%'` xe_check_libs=" -ltt $extra_libs" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -8865,15 +8945,15 @@ test -z "$with_cde" && { ac_safe=`echo "Dt/Dt.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for Dt/Dt.h""... $ac_c" 1>&6 -echo "configure:8869: checking for Dt/Dt.h" >&5 +echo "configure:8949: checking for Dt/Dt.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8877: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8957: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -8896,12 +8976,12 @@ } test -z "$with_cde" && { echo $ac_n "checking for DtDndDragStart in -lDtSvc""... $ac_c" 1>&6 -echo "configure:8900: checking for DtDndDragStart in -lDtSvc" >&5 +echo "configure:8980: checking for DtDndDragStart in -lDtSvc" >&5 ac_lib_var=`echo DtSvc'_'DtDndDragStart | sed 'y%./+-%__p_%'` xe_check_libs=" -lDtSvc " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8996: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -8993,7 +9073,7 @@ if test "$with_dragndrop" != "no" ; then echo $ac_n "checking if drag and drop API is needed""... $ac_c" 1>&6 -echo "configure:8997: checking if drag and drop API is needed" >&5 +echo "configure:9077: checking if drag and drop API is needed" >&5 if test -n "$dragndrop_proto" ; then with_dragndrop=yes echo "$ac_t""yes (${dragndrop_proto} )" 1>&6 @@ -9013,19 +9093,19 @@ fi echo "checking for LDAP" 1>&6 -echo "configure:9017: checking for LDAP" >&5 +echo "configure:9097: checking for LDAP" >&5 ldap_libs= test -z "$with_ldap" && { ac_safe=`echo "ldap.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ldap.h""... $ac_c" 1>&6 -echo "configure:9021: checking for ldap.h" >&5 +echo "configure:9101: checking for ldap.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9029: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9109: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9048,15 +9128,15 @@ } test -z "$with_ldap" && { ac_safe=`echo "lber.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for lber.h""... $ac_c" 1>&6 -echo "configure:9052: checking for lber.h" >&5 +echo "configure:9132: checking for lber.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9060: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9140: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9080,12 +9160,12 @@ if test "$with_ldap" != "no"; then echo $ac_n "checking for ldap_search in -lldap""... $ac_c" 1>&6 -echo "configure:9084: checking for ldap_search in -lldap" >&5 +echo "configure:9164: checking for ldap_search in -lldap" >&5 ac_lib_var=`echo ldap'_'ldap_search | sed 'y%./+-%__p_%'` xe_check_libs=" -lldap " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9180: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9110,23 +9190,22 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes" ; then echo "$ac_t""yes" 1>&6 - with_ldap_nolber=yes + with_ldap=yes else echo "$ac_t""no" 1>&6 -with_ldap_nolber=no fi - test "$with_ldap_nolber" = "no" && { + test "$with_ldap" != "yes" && { xe_msg_checking="for ldap_open in -lldap" test -n "-llber" && xe_msg_checking="$xe_msg_checking using extra libs -llber" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:9125: checking "$xe_msg_checking"" >&5 +echo "configure:9204: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo ldap'_'ldap_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lldap -llber" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9220: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9151,23 +9230,22 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes" ; then echo "$ac_t""yes" 1>&6 - with_ldap_lber=yes + with_ldap=yes with_ldap_lber=yes else echo "$ac_t""no" 1>&6 -with_ldap_lber=no fi } - test "$with_ldap_nolber" = "no" -a "$with_ldap_lber" = "no" && { + test "$with_ldap" != "yes" && { xe_msg_checking="for ldap_open in -lldap" test -n "-llber -lkrb" && xe_msg_checking="$xe_msg_checking using extra libs -llber -lkrb" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:9166: checking "$xe_msg_checking"" >&5 +echo "configure:9244: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo ldap'_'ldap_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lldap -llber -lkrb" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9260: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9192,23 +9270,22 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes" ; then echo "$ac_t""yes" 1>&6 - with_ldap_krb=yes + with_ldap=yes with_ldap_lber=yes with_ldap_krb=yes else echo "$ac_t""no" 1>&6 -with_ldap_krb=no fi } - test "$with_ldap_nolber" = "no" -a "$with_ldap_lber" = "no" -a "$with_ldap_krb" = "no" && { + test "$with_ldap" != "yes" && { xe_msg_checking="for ldap_open in -lldap" test -n "-llber -lkrb -ldes" && xe_msg_checking="$xe_msg_checking using extra libs -llber -lkrb -ldes" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:9207: checking "$xe_msg_checking"" >&5 +echo "configure:9284: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo ldap'_'ldap_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lldap -llber -lkrb -ldes" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9300: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +xe_check_libs="" + +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes" ; then + echo "$ac_t""yes" 1>&6 + with_ldap=yes with_ldap_lber=yes with_ldap_krb=yes with_ldap_des=yes +else + echo "$ac_t""no" 1>&6 +fi + + } + test "$with_ldap_lber" != "yes" && { +echo $ac_n "checking for ber_pvt_opt_on in -llber""... $ac_c" 1>&6 +echo "configure:9322: checking for ber_pvt_opt_on in -llber" >&5 +ac_lib_var=`echo lber'_'ber_pvt_opt_on | sed 'y%./+-%__p_%'` + +xe_check_libs=" -llber " +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9233,14 +9348,12 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes" ; then echo "$ac_t""yes" 1>&6 - with_ldap_krbdes=yes + with_ldap_lber=yes else echo "$ac_t""no" 1>&6 -with_ldap_krbdes=no fi } - test -z "$with_ldap" -a \( "$with_ldap_lber" = "yes" -o "$with_ldap_nolber" = "yes" -o "$with_ldap_krb" = "yes" -o "$with_ldap_krbdes" = "yes" \) && with_ldap=yes fi if test "$with_ldap" = "yes"; then { test "$extra_verbose" = "yes" && cat << \EOF @@ -9251,27 +9364,24 @@ EOF } - if test "$with_ldap_nolber" = "yes" ; then - ldap_libs="-lldap $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lldap\" to \$ldap_libs"; fi - else - if test "$with_ldap_krb" = "yes" ; then - ldap_libs="-lkrb $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lkrb\" to \$ldap_libs"; fi - fi - if test "$with_ldap_krbdes" = "yes" ; then - ldap_libs="-ldes $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-ldes\" to \$ldap_libs"; fi - ldap_libs="-lkrb $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lkrb\" to \$ldap_libs"; fi - fi + if test "$with_ldap_des" = "yes" ; then + ldap_libs="-ldes $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-ldes\" to \$ldap_libs"; fi + fi + if test "$with_ldap_krb" = "yes" ; then + ldap_libs="-lkrb $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lkrb\" to \$ldap_libs"; fi + fi + if test "$with_ldap_lber" = "yes" ; then ldap_libs="-llber $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-llber\" to \$ldap_libs"; fi - ldap_libs="-lldap $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lldap\" to \$ldap_libs"; fi fi + ldap_libs="-lldap $ldap_libs" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lldap\" to \$ldap_libs"; fi save_LIBS="$LIBS" LIBS="$LIBS $ldap_libs" for ac_func in ldap_set_option ldap_get_lderrno ldap_result2error ldap_parse_result do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:9272: checking for $ac_func" >&5 +echo "configure:9382: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9408: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -9333,20 +9443,20 @@ postgresql_libs= if test "$with_postgresql" != "no"; then echo "checking for PostgreSQL" 1>&6 -echo "configure:9337: checking for PostgreSQL" >&5 +echo "configure:9447: checking for PostgreSQL" >&5 for header_dir in "" "pgsql/" "postgresql/"; do ac_safe=`echo "${header_dir}libpq-fe.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ${header_dir}libpq-fe.h""... $ac_c" 1>&6 -echo "configure:9342: checking for ${header_dir}libpq-fe.h" >&5 +echo "configure:9452: checking for ${header_dir}libpq-fe.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9350: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9460: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9370,12 +9480,12 @@ test -n "$libpq_fe_h_file" && { echo $ac_n "checking for PQconnectdb in -lpq""... $ac_c" 1>&6 -echo "configure:9374: checking for PQconnectdb in -lpq" >&5 +echo "configure:9484: checking for PQconnectdb in -lpq" >&5 ac_lib_var=`echo pq'_'PQconnectdb | sed 'y%./+-%__p_%'` xe_check_libs=" -lpq " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9500: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9419,12 +9529,12 @@ echo $ac_n "checking for PQconnectStart in -lpq""... $ac_c" 1>&6 -echo "configure:9423: checking for PQconnectStart in -lpq" >&5 +echo "configure:9533: checking for PQconnectStart in -lpq" >&5 ac_lib_var=`echo pq'_'PQconnectStart | sed 'y%./+-%__p_%'` xe_check_libs=" -lpq " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9486,7 +9596,7 @@ if test "$window_system" != "none"; then echo "checking for graphics libraries" 1>&6 -echo "configure:9490: checking for graphics libraries" >&5 +echo "configure:9600: checking for graphics libraries" >&5 libpath_xpm= incpath_xpm= @@ -9512,10 +9622,10 @@ CFLAGS=""$incpath_xpm" $CFLAGS" && if test "$extra_verbose" = "yes"; then echo " Prepending \""$incpath_xpm"\" to \$CFLAGS"; fi LDFLAGS=""$libpath_xpm" $LDFLAGS" && if test "$extra_verbose" = "yes"; then echo " Prepending \""$libpath_xpm"\" to \$LDFLAGS"; fi echo $ac_n "checking for Xpm - no older than 3.4f""... $ac_c" 1>&6 -echo "configure:9516: checking for Xpm - no older than 3.4f" >&5 +echo "configure:9626: checking for Xpm - no older than 3.4f" >&5 xe_check_libs=-lXpm cat > conftest.$ac_ext < @@ -9524,7 +9634,7 @@ XpmIncludeVersion != XpmLibraryVersion() ? 1 : XpmIncludeVersion < 30406 ? 2 : 0 ;} EOF -if { (eval echo configure:9528: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:9638: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ./conftest dummy_arg; xpm_status=$?; if test "$xpm_status" = "0"; then @@ -9568,17 +9678,17 @@ libs_x="-lXpm $libs_x" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lXpm\" to \$libs_x"; fi CFLAGS=""$incpath_xpm" $CFLAGS" && if test "$extra_verbose" = "yes"; then echo " Prepending \""$incpath_xpm"\" to \$CFLAGS"; fi echo $ac_n "checking for \"FOR_MSW\" xpm""... $ac_c" 1>&6 -echo "configure:9572: checking for \"FOR_MSW\" xpm" >&5 +echo "configure:9682: checking for \"FOR_MSW\" xpm" >&5 xe_check_libs=-lXpm cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9692: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* xpm_for_msw=no else @@ -9604,15 +9714,15 @@ test -z "$with_xface" && { ac_safe=`echo "compface.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for compface.h""... $ac_c" 1>&6 -echo "configure:9608: checking for compface.h" >&5 +echo "configure:9718: checking for compface.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9616: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9726: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9635,12 +9745,12 @@ } test -z "$with_xface" && { echo $ac_n "checking for UnGenFace in -lcompface""... $ac_c" 1>&6 -echo "configure:9639: checking for UnGenFace in -lcompface" >&5 +echo "configure:9749: checking for UnGenFace in -lcompface" >&5 ac_lib_var=`echo compface'_'UnGenFace | sed 'y%./+-%__p_%'` xe_check_libs=" -lcompface " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9765: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9700,12 +9810,12 @@ if test "$with_png $with_tiff" != "no no"; then echo $ac_n "checking for inflate in -lc""... $ac_c" 1>&6 -echo "configure:9704: checking for inflate in -lc" >&5 +echo "configure:9814: checking for inflate in -lc" >&5 ac_lib_var=`echo c'_'inflate | sed 'y%./+-%__p_%'` xe_check_libs=" -lc " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9830: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9735,12 +9845,12 @@ echo "$ac_t""no" 1>&6 echo $ac_n "checking for inflate in -lz""... $ac_c" 1>&6 -echo "configure:9739: checking for inflate in -lz" >&5 +echo "configure:9849: checking for inflate in -lz" >&5 ac_lib_var=`echo z'_'inflate | sed 'y%./+-%__p_%'` xe_check_libs=" -lz " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9865: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9770,12 +9880,12 @@ echo "$ac_t""no" 1>&6 echo $ac_n "checking for inflate in -lgz""... $ac_c" 1>&6 -echo "configure:9774: checking for inflate in -lgz" >&5 +echo "configure:9884: checking for inflate in -lgz" >&5 ac_lib_var=`echo gz'_'inflate | sed 'y%./+-%__p_%'` xe_check_libs=" -lgz " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9816,15 +9926,15 @@ test -z "$with_jpeg" && { ac_safe=`echo "jpeglib.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for jpeglib.h""... $ac_c" 1>&6 -echo "configure:9820: checking for jpeglib.h" >&5 +echo "configure:9930: checking for jpeglib.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9828: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9938: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9847,12 +9957,12 @@ } test -z "$with_jpeg" && { echo $ac_n "checking for jpeg_destroy_decompress in -ljpeg""... $ac_c" 1>&6 -echo "configure:9851: checking for jpeg_destroy_decompress in -ljpeg" >&5 +echo "configure:9961: checking for jpeg_destroy_decompress in -ljpeg" >&5 ac_lib_var=`echo jpeg'_'jpeg_destroy_decompress | sed 'y%./+-%__p_%'` xe_check_libs=" -ljpeg " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9977: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9899,10 +10009,10 @@ png_problem="" test -z "$with_png" && { echo $ac_n "checking for pow""... $ac_c" 1>&6 -echo "configure:9903: checking for pow" >&5 +echo "configure:10013: checking for pow" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_pow=yes" else @@ -9946,15 +10056,15 @@ } test -z "$with_png" && { ac_safe=`echo "png.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for png.h""... $ac_c" 1>&6 -echo "configure:9950: checking for png.h" >&5 +echo "configure:10060: checking for png.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9958: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10068: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -9977,12 +10087,12 @@ } test -z "$with_png" && { echo $ac_n "checking for png_read_image in -lpng""... $ac_c" 1>&6 -echo "configure:9981: checking for png_read_image in -lpng" >&5 +echo "configure:10091: checking for png_read_image in -lpng" >&5 ac_lib_var=`echo png'_'png_read_image | sed 'y%./+-%__p_%'` xe_check_libs=" -lpng " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10107: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10016,10 +10126,10 @@ } if test -z "$with_png"; then echo $ac_n "checking for workable png version information""... $ac_c" 1>&6 -echo "configure:10020: checking for workable png version information" >&5 +echo "configure:10130: checking for workable png version information" >&5 xe_check_libs="-lpng -lz" cat > conftest.$ac_ext < int main(int c, char **v) { @@ -10027,7 +10137,7 @@ if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING) != 0) return 1; return (PNG_LIBPNG_VER < 10002) ? 2 : 0 ;} EOF -if { (eval echo configure:10031: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:10141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ./conftest dummy_arg; png_status=$?; if test "$png_status" = "0"; then @@ -10070,15 +10180,15 @@ test -z "$with_tiff" && { ac_safe=`echo "tiffio.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for tiffio.h""... $ac_c" 1>&6 -echo "configure:10074: checking for tiffio.h" >&5 +echo "configure:10184: checking for tiffio.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10082: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10192: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10101,12 +10211,12 @@ } test -z "$with_tiff" && { echo $ac_n "checking for TIFFClientOpen in -ltiff""... $ac_c" 1>&6 -echo "configure:10105: checking for TIFFClientOpen in -ltiff" >&5 +echo "configure:10215: checking for TIFFClientOpen in -ltiff" >&5 ac_lib_var=`echo tiff'_'TIFFClientOpen | sed 'y%./+-%__p_%'` xe_check_libs=" -ltiff " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10231: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10156,15 +10266,15 @@ if test "$with_gtk" = "yes"; then test -z "$with_xface" && { ac_safe=`echo "compface.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for compface.h""... $ac_c" 1>&6 -echo "configure:10160: checking for compface.h" >&5 +echo "configure:10270: checking for compface.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10168: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10278: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10187,12 +10297,12 @@ } test -z "$with_xface" && { echo $ac_n "checking for UnGenFace in -lcompface""... $ac_c" 1>&6 -echo "configure:10191: checking for UnGenFace in -lcompface" >&5 +echo "configure:10301: checking for UnGenFace in -lcompface" >&5 ac_lib_var=`echo compface'_'UnGenFace | sed 'y%./+-%__p_%'` xe_check_libs=" -lcompface " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10317: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10242,7 +10352,7 @@ if test "$with_x11" = "yes"; then echo "checking for X11 graphics libraries" 1>&6 -echo "configure:10246: checking for X11 graphics libraries" >&5 +echo "configure:10356: checking for X11 graphics libraries" >&5 fi case "$with_widgets" in @@ -10252,7 +10362,7 @@ if test "$with_x11" = "yes" -a "$detect_athena" = "yes" ; then echo "checking for the Athena widgets" 1>&6 -echo "configure:10256: checking for the Athena widgets" >&5 +echo "configure:10366: checking for the Athena widgets" >&5 case "$with_athena" in "xaw" | "") athena_variant=Xaw athena_3d=no ;; @@ -10266,12 +10376,12 @@ if test "$athena_3d" = "no"; then echo $ac_n "checking for XawScrollbarSetThumb in -l$athena_variant""... $ac_c" 1>&6 -echo "configure:10270: checking for XawScrollbarSetThumb in -l$athena_variant" >&5 +echo "configure:10380: checking for XawScrollbarSetThumb in -l$athena_variant" >&5 ac_lib_var=`echo $athena_variant'_'XawScrollbarSetThumb | sed 'y%./+-%__p_%'` xe_check_libs=" -l$athena_variant " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10298,12 +10408,12 @@ echo "$ac_t""yes" 1>&6 echo $ac_n "checking for threeDClassRec in -l$athena_variant""... $ac_c" 1>&6 -echo "configure:10302: checking for threeDClassRec in -l$athena_variant" >&5 +echo "configure:10412: checking for threeDClassRec in -l$athena_variant" >&5 ac_lib_var=`echo $athena_variant'_'threeDClassRec | sed 'y%./+-%__p_%'` xe_check_libs=" -l$athena_variant " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10428: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10345,12 +10455,12 @@ else echo $ac_n "checking for threeDClassRec in -l$athena_variant""... $ac_c" 1>&6 -echo "configure:10349: checking for threeDClassRec in -l$athena_variant" >&5 +echo "configure:10459: checking for threeDClassRec in -l$athena_variant" >&5 ac_lib_var=`echo $athena_variant'_'threeDClassRec | sed 'y%./+-%__p_%'` xe_check_libs=" -l$athena_variant " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10379,12 +10489,12 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for threeDClassRec in -lXaw""... $ac_c" 1>&6 -echo "configure:10383: checking for threeDClassRec in -lXaw" >&5 +echo "configure:10493: checking for threeDClassRec in -lXaw" >&5 ac_lib_var=`echo Xaw'_'threeDClassRec | sed 'y%./+-%__p_%'` xe_check_libs=" -lXaw " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10509: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10426,15 +10536,15 @@ if test "$athena_3d" = "no"; then ac_safe=`echo "X11/Xaw/ThreeD.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Xaw/ThreeD.h""... $ac_c" 1>&6 -echo "configure:10430: checking for X11/Xaw/ThreeD.h" >&5 +echo "configure:10540: checking for X11/Xaw/ThreeD.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10438: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10548: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10454,15 +10564,15 @@ echo "$ac_t""no" 1>&6 ac_safe=`echo "X11/Xaw/XawInit.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Xaw/XawInit.h""... $ac_c" 1>&6 -echo "configure:10458: checking for X11/Xaw/XawInit.h" >&5 +echo "configure:10568: checking for X11/Xaw/XawInit.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10466: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10576: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10488,15 +10598,15 @@ else ac_safe=`echo "X11/$athena_variant/XawInit.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/$athena_variant/XawInit.h""... $ac_c" 1>&6 -echo "configure:10492: checking for X11/$athena_variant/XawInit.h" >&5 +echo "configure:10602: checking for X11/$athena_variant/XawInit.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10500: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10610: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10513,15 +10623,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "X11/$athena_variant/ThreeD.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/$athena_variant/ThreeD.h""... $ac_c" 1>&6 -echo "configure:10517: checking for X11/$athena_variant/ThreeD.h" >&5 +echo "configure:10627: checking for X11/$athena_variant/ThreeD.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10525: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10635: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10549,15 +10659,15 @@ if test -z "$athena_h_path"; then ac_safe=`echo "$athena_variant/XawInit.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $athena_variant/XawInit.h""... $ac_c" 1>&6 -echo "configure:10553: checking for $athena_variant/XawInit.h" >&5 +echo "configure:10663: checking for $athena_variant/XawInit.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10561: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10671: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10574,15 +10684,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "$athena_variant/ThreeD.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $athena_variant/ThreeD.h""... $ac_c" 1>&6 -echo "configure:10578: checking for $athena_variant/ThreeD.h" >&5 +echo "configure:10688: checking for $athena_variant/ThreeD.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10586: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10696: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10611,15 +10721,15 @@ if test -z "$athena_h_path" -a "$athena_variant" != "Xaw3d"; then ac_safe=`echo "X11/Xaw3d/XawInit.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Xaw3d/XawInit.h""... $ac_c" 1>&6 -echo "configure:10615: checking for X11/Xaw3d/XawInit.h" >&5 +echo "configure:10725: checking for X11/Xaw3d/XawInit.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10623: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10733: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10636,15 +10746,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "X11/Xaw3d/ThreeD.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Xaw3d/ThreeD.h""... $ac_c" 1>&6 -echo "configure:10640: checking for X11/Xaw3d/ThreeD.h" >&5 +echo "configure:10750: checking for X11/Xaw3d/ThreeD.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10648: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10758: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10676,15 +10786,15 @@ if test -z "$athena_h_path" -a "$athena_variant" != "Xaw3d"; then ac_safe=`echo "Xaw3d/XawInit.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for Xaw3d/XawInit.h""... $ac_c" 1>&6 -echo "configure:10680: checking for Xaw3d/XawInit.h" >&5 +echo "configure:10790: checking for Xaw3d/XawInit.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10688: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10798: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10701,15 +10811,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "Xaw3d/ThreeD.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for Xaw3d/ThreeD.h""... $ac_c" 1>&6 -echo "configure:10705: checking for Xaw3d/ThreeD.h" >&5 +echo "configure:10815: checking for Xaw3d/ThreeD.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10713: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10823: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10741,15 +10851,15 @@ if test -z "$athena_h_path"; then ac_safe=`echo "X11/Xaw/ThreeD.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Xaw/ThreeD.h""... $ac_c" 1>&6 -echo "configure:10745: checking for X11/Xaw/ThreeD.h" >&5 +echo "configure:10855: checking for X11/Xaw/ThreeD.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10753: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10863: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10788,15 +10898,15 @@ if test "$with_x11" = "yes"; then ac_safe=`echo "Xm/Xm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for Xm/Xm.h""... $ac_c" 1>&6 -echo "configure:10792: checking for Xm/Xm.h" >&5 +echo "configure:10902: checking for Xm/Xm.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:10800: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:10910: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -10813,12 +10923,12 @@ echo "$ac_t""yes" 1>&6 echo $ac_n "checking for XmStringFree in -lXm""... $ac_c" 1>&6 -echo "configure:10817: checking for XmStringFree in -lXm" >&5 +echo "configure:10927: checking for XmStringFree in -lXm" >&5 ac_lib_var=`echo Xm'_'XmStringFree | sed 'y%./+-%__p_%'` xe_check_libs=" -lXm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:10943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10858,9 +10968,9 @@ if test "$have_motif" = "yes"; then echo $ac_n "checking for Lesstif""... $ac_c" 1>&6 -echo "configure:10862: checking for Lesstif" >&5 +echo "configure:10972: checking for Lesstif" >&5 cat > conftest.$ac_ext < #ifdef LESSTIF_VERSION @@ -11233,7 +11343,7 @@ if test "$with_mule" = "yes" ; then echo "checking for Mule-related features" 1>&6 -echo "configure:11237: checking for Mule-related features" >&5 +echo "configure:11347: checking for Mule-related features" >&5 { test "$extra_verbose" = "yes" && cat << \EOF Defining MULE EOF @@ -11247,15 +11357,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:11251: checking for $ac_hdr" >&5 +echo "configure:11361: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11259: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:11369: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11286,12 +11396,12 @@ echo $ac_n "checking for strerror in -lintl""... $ac_c" 1>&6 -echo "configure:11290: checking for strerror in -lintl" >&5 +echo "configure:11400: checking for strerror in -lintl" >&5 ac_lib_var=`echo intl'_'strerror | sed 'y%./+-%__p_%'` xe_check_libs=" -lintl " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11416: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11335,18 +11445,18 @@ echo "checking for Mule input methods" 1>&6 -echo "configure:11339: checking for Mule input methods" >&5 +echo "configure:11449: checking for Mule input methods" >&5 case "$with_xim" in "" | "yes" ) echo "checking for XIM" 1>&6 -echo "configure:11342: checking for XIM" >&5 +echo "configure:11452: checking for XIM" >&5 echo $ac_n "checking for XOpenIM in -lX11""... $ac_c" 1>&6 -echo "configure:11345: checking for XOpenIM in -lX11" >&5 +echo "configure:11455: checking for XOpenIM in -lX11" >&5 ac_lib_var=`echo X11'_'XOpenIM | sed 'y%./+-%__p_%'` xe_check_libs=" -lX11 " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11471: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11381,12 +11491,12 @@ if test "$have_motif $have_lesstif" = "yes no"; then echo $ac_n "checking for XmImMbLookupString in -lXm""... $ac_c" 1>&6 -echo "configure:11385: checking for XmImMbLookupString in -lXm" >&5 +echo "configure:11495: checking for XmImMbLookupString in -lXm" >&5 ac_lib_var=`echo Xm'_'XmImMbLookupString | sed 'y%./+-%__p_%'` xe_check_libs=" -lXm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11511: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11462,15 +11572,15 @@ if test "$with_xfs" = "yes" ; then echo "checking for XFontSet" 1>&6 -echo "configure:11466: checking for XFontSet" >&5 +echo "configure:11576: checking for XFontSet" >&5 echo $ac_n "checking for XmbDrawString in -lX11""... $ac_c" 1>&6 -echo "configure:11469: checking for XmbDrawString in -lX11" >&5 +echo "configure:11579: checking for XmbDrawString in -lX11" >&5 ac_lib_var=`echo X11'_'XmbDrawString | sed 'y%./+-%__p_%'` xe_check_libs=" -lX11 " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11595: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11521,15 +11631,15 @@ test "$with_wnn6" = "yes" && with_wnn=yes # wnn6 implies wnn support test -z "$with_wnn" && { ac_safe=`echo "wnn/jllib.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for wnn/jllib.h""... $ac_c" 1>&6 -echo "configure:11525: checking for wnn/jllib.h" >&5 +echo "configure:11635: checking for wnn/jllib.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11533: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:11643: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11552,15 +11662,15 @@ } test -z "$with_wnn" && { ac_safe=`echo "wnn/commonhd.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for wnn/commonhd.h""... $ac_c" 1>&6 -echo "configure:11556: checking for wnn/commonhd.h" >&5 +echo "configure:11666: checking for wnn/commonhd.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11564: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:11674: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11585,10 +11695,10 @@ for ac_func in crypt do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:11589: checking for $ac_func" >&5 +echo "configure:11699: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11725: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -11640,12 +11750,12 @@ test "$ac_cv_func_crypt" != "yes" && { echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 -echo "configure:11644: checking for crypt in -lcrypt" >&5 +echo "configure:11754: checking for crypt in -lcrypt" >&5 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'` xe_check_libs=" -lcrypt " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11770: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11691,12 +11801,12 @@ if test -z "$with_wnn" -o "$with_wnn" = "yes"; then echo $ac_n "checking for jl_dic_list_e in -lwnn""... $ac_c" 1>&6 -echo "configure:11695: checking for jl_dic_list_e in -lwnn" >&5 +echo "configure:11805: checking for jl_dic_list_e in -lwnn" >&5 ac_lib_var=`echo wnn'_'jl_dic_list_e | sed 'y%./+-%__p_%'` xe_check_libs=" -lwnn " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11821: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11725,12 +11835,12 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for jl_dic_list_e in -lwnn4""... $ac_c" 1>&6 -echo "configure:11729: checking for jl_dic_list_e in -lwnn4" >&5 +echo "configure:11839: checking for jl_dic_list_e in -lwnn4" >&5 ac_lib_var=`echo wnn4'_'jl_dic_list_e | sed 'y%./+-%__p_%'` xe_check_libs=" -lwnn4 " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11855: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11759,12 +11869,12 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for jl_dic_list_e in -lwnn6""... $ac_c" 1>&6 -echo "configure:11763: checking for jl_dic_list_e in -lwnn6" >&5 +echo "configure:11873: checking for jl_dic_list_e in -lwnn6" >&5 ac_lib_var=`echo wnn6'_'jl_dic_list_e | sed 'y%./+-%__p_%'` xe_check_libs=" -lwnn6 " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11889: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11793,12 +11903,12 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dic_list_e in -lwnn6_fromsrc""... $ac_c" 1>&6 -echo "configure:11797: checking for dic_list_e in -lwnn6_fromsrc" >&5 +echo "configure:11907: checking for dic_list_e in -lwnn6_fromsrc" >&5 ac_lib_var=`echo wnn6_fromsrc'_'dic_list_e | sed 'y%./+-%__p_%'` xe_check_libs=" -lwnn6_fromsrc " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11923: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11854,12 +11964,12 @@ if test "$with_wnn6" != "no"; then echo $ac_n "checking for jl_fi_dic_list in -l$libwnn""... $ac_c" 1>&6 -echo "configure:11858: checking for jl_fi_dic_list in -l$libwnn" >&5 +echo "configure:11968: checking for jl_fi_dic_list in -l$libwnn" >&5 ac_lib_var=`echo $libwnn'_'jl_fi_dic_list | sed 'y%./+-%__p_%'` xe_check_libs=" -l$libwnn " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:11984: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -11905,15 +12015,15 @@ if test "$with_canna" != "no"; then ac_safe=`echo "canna/jrkanji.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for canna/jrkanji.h""... $ac_c" 1>&6 -echo "configure:11909: checking for canna/jrkanji.h" >&5 +echo "configure:12019: checking for canna/jrkanji.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11917: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12027: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11940,15 +12050,15 @@ c_switch_site="$c_switch_site -I/usr/local/canna/include" ac_safe=`echo "canna/jrkanji.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for canna/jrkanji.h""... $ac_c" 1>&6 -echo "configure:11944: checking for canna/jrkanji.h" >&5 +echo "configure:12054: checking for canna/jrkanji.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11952: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12062: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -11976,15 +12086,15 @@ test -z "$with_canna" && { ac_safe=`echo "canna/RK.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for canna/RK.h""... $ac_c" 1>&6 -echo "configure:11980: checking for canna/RK.h" >&5 +echo "configure:12090: checking for canna/RK.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:11988: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12098: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12007,12 +12117,12 @@ } test -z "$with_canna" && { echo $ac_n "checking for RkBgnBun in -lRKC""... $ac_c" 1>&6 -echo "configure:12011: checking for RkBgnBun in -lRKC" >&5 +echo "configure:12121: checking for RkBgnBun in -lRKC" >&5 ac_lib_var=`echo RKC'_'RkBgnBun | sed 'y%./+-%__p_%'` xe_check_libs=" -lRKC " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12137: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12046,12 +12156,12 @@ } test -z "$with_canna" && { echo $ac_n "checking for jrKanjiControl in -lcanna""... $ac_c" 1>&6 -echo "configure:12050: checking for jrKanjiControl in -lcanna" >&5 +echo "configure:12160: checking for jrKanjiControl in -lcanna" >&5 ac_lib_var=`echo canna'_'jrKanjiControl | sed 'y%./+-%__p_%'` xe_check_libs=" -lcanna " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12176: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12108,12 +12218,12 @@ libs_x="-lXm $libs_x" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lXm\" to \$libs_x"; fi echo $ac_n "checking for layout_object_getvalue in -li18n""... $ac_c" 1>&6 -echo "configure:12112: checking for layout_object_getvalue in -li18n" >&5 +echo "configure:12222: checking for layout_object_getvalue in -li18n" >&5 ac_lib_var=`echo i18n'_'layout_object_getvalue | sed 'y%./+-%__p_%'` xe_check_libs=" -li18n " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12208,13 +12318,13 @@ fi -for ac_func in cbrt closedir dup2 eaccess fmod fpathconf frexp ftime getaddrinfo gethostname getnameinfo getpagesize getrlimit gettimeofday getcwd getwd link logb lrand48 matherr mkdir mktime perror poll random readlink rename res_init rint rmdir select setitimer setpgid setlocale setsid sigblock sighold sigprocmask snprintf stpcpy strerror strlwr strupr symlink tzset ulimit usleep waitpid vsnprintf fsync ftruncate umask wcslen wcscmp vlimit +for ac_func in cbrt closedir dup2 eaccess fmod fpathconf frexp fsync ftime ftruncate getaddrinfo gethostname getnameinfo getpagesize getrlimit gettimeofday getcwd link logb lrand48 matherr mkdir mktime perror poll random readlink rename res_init rint rmdir select setitimer setpgid setsid sigblock sighold sigprocmask snprintf strerror strlwr strupr symlink tzset ulimit umask usleep vlimit vsnprintf waitpid wcscmp wcslen do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:12215: checking for $ac_func" >&5 +echo "configure:12325: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12351: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -12278,10 +12388,10 @@ for ac_func in getpt _getpty grantpt unlockpt ptsname killpg tcgetpgrp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:12282: checking for $ac_func" >&5 +echo "configure:12392: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -12333,10 +12443,10 @@ echo $ac_n "checking for openpty""... $ac_c" 1>&6 -echo "configure:12337: checking for openpty" >&5 +echo "configure:12447: checking for openpty" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12473: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_openpty=yes" else @@ -12378,12 +12488,12 @@ echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6 -echo "configure:12382: checking for openpty in -lutil" >&5 +echo "configure:12492: checking for openpty in -lutil" >&5 ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'` xe_check_libs=" -lutil " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12508: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12429,15 +12539,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12433: checking for $ac_hdr" >&5 +echo "configure:12543: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12441: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12551: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12474,15 +12584,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12478: checking for $ac_hdr" >&5 +echo "configure:12588: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12486: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12596: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12515,15 +12625,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12519: checking for $ac_hdr" >&5 +echo "configure:12629: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12527: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12637: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12556,15 +12666,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12560: checking for $ac_hdr" >&5 +echo "configure:12670: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12568: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12678: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12600,15 +12710,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12604: checking for $ac_hdr" >&5 +echo "configure:12714: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12612: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12722: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12641,10 +12751,10 @@ for ac_func in isastream do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:12645: checking for $ac_func" >&5 +echo "configure:12755: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -12698,15 +12808,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12702: checking for $ac_hdr" >&5 +echo "configure:12812: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12710: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12820: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12739,10 +12849,10 @@ for ac_func in getloadavg do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:12743: checking for $ac_func" >&5 +echo "configure:12853: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -12798,15 +12908,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12802: checking for $ac_hdr" >&5 +echo "configure:12912: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12810: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:12920: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12842,12 +12952,12 @@ echo $ac_n "checking for kstat_open in -lkstat""... $ac_c" 1>&6 -echo "configure:12846: checking for kstat_open in -lkstat" >&5 +echo "configure:12956: checking for kstat_open in -lkstat" >&5 ac_lib_var=`echo kstat'_'kstat_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lkstat " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:12972: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12893,15 +13003,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:12897: checking for $ac_hdr" >&5 +echo "configure:13007: checking for $ac_hdr" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:12905: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:13015: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -12933,12 +13043,12 @@ echo $ac_n "checking for kvm_read in -lkvm""... $ac_c" 1>&6 -echo "configure:12937: checking for kvm_read in -lkvm" >&5 +echo "configure:13047: checking for kvm_read in -lkvm" >&5 ac_lib_var=`echo kvm'_'kvm_read | sed 'y%./+-%__p_%'` xe_check_libs=" -lkvm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13063: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -12983,16 +13093,16 @@ fi echo $ac_n "checking whether netdb declares h_errno""... $ac_c" 1>&6 -echo "configure:12987: checking whether netdb declares h_errno" >&5 +echo "configure:13097: checking whether netdb declares h_errno" >&5 cat > conftest.$ac_ext < int main() { return h_errno; ; return 0; } EOF -if { (eval echo configure:12996: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13106: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "$ac_t""yes" 1>&6 { test "$extra_verbose" = "yes" && cat << \EOF @@ -13012,16 +13122,16 @@ rm -f conftest* echo $ac_n "checking for sigsetjmp""... $ac_c" 1>&6 -echo "configure:13016: checking for sigsetjmp" >&5 +echo "configure:13126: checking for sigsetjmp" >&5 cat > conftest.$ac_ext < int main() { sigjmp_buf bar; sigsetjmp (bar, 0); ; return 0; } EOF -if { (eval echo configure:13025: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13135: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 { test "$extra_verbose" = "yes" && cat << \EOF @@ -13041,11 +13151,11 @@ rm -f conftest* echo $ac_n "checking whether localtime caches TZ""... $ac_c" 1>&6 -echo "configure:13045: checking whether localtime caches TZ" >&5 +echo "configure:13155: checking whether localtime caches TZ" >&5 if test "$ac_cv_func_tzset" = "yes"; then cat > conftest.$ac_ext < #if STDC_HEADERS @@ -13080,7 +13190,7 @@ exit (0); } EOF -if { (eval echo configure:13084: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:13194: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then emacs_cv_localtime_cache=no else @@ -13110,9 +13220,9 @@ if test "$HAVE_TIMEVAL" = "yes"; then echo $ac_n "checking whether gettimeofday accepts one or two arguments""... $ac_c" 1>&6 -echo "configure:13114: checking whether gettimeofday accepts one or two arguments" >&5 +echo "configure:13224: checking whether gettimeofday accepts one or two arguments" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13247: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "$ac_t""two" 1>&6 else @@ -13155,19 +13265,19 @@ echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:13159: checking for inline" >&5 +echo "configure:13269: checking for inline" >&5 ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13281: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -13204,16 +13314,16 @@ fi echo $ac_n "checking for typeof""... $ac_c" 1>&6 -echo "configure:13208: checking for typeof" >&5 +echo "configure:13318: checking for typeof" >&5 cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13327: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* typeofname="__typeof__" else @@ -13221,14 +13331,14 @@ cat conftest.$ac_ext >&5 rm -rf conftest* cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13342: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* typeofname="typeof" else @@ -13257,17 +13367,17 @@ # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:13261: checking for working alloca.h" >&5 +echo "configure:13371: checking for working alloca.h" >&5 cat > conftest.$ac_ext < int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:13271: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13381: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -13291,10 +13401,10 @@ fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:13295: checking for alloca" >&5 +echo "configure:13405: checking for alloca" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -13361,10 +13471,10 @@ echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:13365: checking whether alloca needs Cray hooks" >&5 +echo "configure:13475: checking whether alloca needs Cray hooks" >&5 cat > conftest.$ac_ext <&6 -echo "configure:13392: checking for $ac_func" >&5 +echo "configure:13502: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13528: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -13444,10 +13554,10 @@ fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:13448: checking stack direction for C alloca" >&5 +echo "configure:13558: checking stack direction for C alloca" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:13580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_c_stack_direction=1 else @@ -13495,9 +13605,9 @@ fi echo $ac_n "checking for working alloca in function calls""... $ac_c" 1>&6 -echo "configure:13499: checking for working alloca in function calls" >&5 +echo "configure:13609: checking for working alloca in function calls" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:13664: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then working_alloca_in_function_calls=yes else @@ -13572,11 +13682,51 @@ } +echo $ac_n "checking for working scanf""... $ac_c" 1>&6 +echo "configure:13687: checking for working scanf" >&5 +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +then + working_scanf=yes +else + conftest_rc="$?" + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + working_scanf=no +fi +rm -fr conftest* +echo "$ac_t""$working_scanf" 1>&6 +test "$working_scanf" != "yes" && \ + { test "$extra_verbose" = "yes" && cat << \EOF + Defining CYGWIN_SCANF_BUG +EOF +cat >> confdefs.h <<\EOF +#define CYGWIN_SCANF_BUG 1 +EOF +} + + echo $ac_n "checking for working strcoll""... $ac_c" 1>&6 -echo "configure:13577: checking for working strcoll" >&5 +echo "configure:13727: checking for working strcoll" >&5 cat > conftest.$ac_ext < main () @@ -13586,7 +13736,7 @@ strcoll ("123", "456") >= 0); } EOF -if { (eval echo configure:13590: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:13740: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_func_strcoll_works=yes else @@ -13614,10 +13764,10 @@ for ac_func in getpgrp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:13618: checking for $ac_func" >&5 +echo "configure:13768: checking for $ac_func" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -13668,10 +13818,10 @@ done echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6 -echo "configure:13672: checking whether getpgrp takes no argument" >&5 +echo "configure:13822: checking whether getpgrp takes no argument" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:13880: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then ac_cv_func_getpgrp_void=yes else @@ -13753,10 +13903,10 @@ echo $ac_n "checking for working mmap""... $ac_c" 1>&6 -echo "configure:13757: checking for working mmap" >&5 +echo "configure:13907: checking for working mmap" >&5 case "$opsys" in ultrix* ) have_mmap=no ;; *) cat > conftest.$ac_ext < #include @@ -13789,7 +13939,7 @@ return 1; } EOF -if { (eval echo configure:13793: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:13943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then have_mmap=yes else @@ -13818,9 +13968,9 @@ if test "$rel_alloc $have_mmap" = "default yes"; then if test "$doug_lea_malloc" = "yes"; then echo $ac_n "checking for M_MMAP_THRESHOLD""... $ac_c" 1>&6 -echo "configure:13822: checking for M_MMAP_THRESHOLD" >&5 +echo "configure:13972: checking for M_MMAP_THRESHOLD" >&5 cat > conftest.$ac_ext < int main() { @@ -13832,7 +13982,7 @@ ; return 0; } EOF -if { (eval echo configure:13836: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:13986: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* rel_alloc=no; echo "$ac_t""yes" 1>&6; else @@ -13857,15 +14007,15 @@ ac_safe=`echo "termios.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for termios.h""... $ac_c" 1>&6 -echo "configure:13861: checking for termios.h" >&5 +echo "configure:14011: checking for termios.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:13869: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14019: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -13908,15 +14058,15 @@ echo "$ac_t""no" 1>&6 ac_safe=`echo "termio.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for termio.h""... $ac_c" 1>&6 -echo "configure:13912: checking for termio.h" >&5 +echo "configure:14062: checking for termio.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:13920: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14070: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -13948,10 +14098,10 @@ echo $ac_n "checking for socket""... $ac_c" 1>&6 -echo "configure:13952: checking for socket" >&5 +echo "configure:14102: checking for socket" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14128: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_socket=yes" else @@ -13989,15 +14139,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "netinet/in.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for netinet/in.h""... $ac_c" 1>&6 -echo "configure:13993: checking for netinet/in.h" >&5 +echo "configure:14143: checking for netinet/in.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14001: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14151: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14014,15 +14164,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "arpa/inet.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for arpa/inet.h""... $ac_c" 1>&6 -echo "configure:14018: checking for arpa/inet.h" >&5 +echo "configure:14168: checking for arpa/inet.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14026: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14176: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14047,9 +14197,9 @@ } echo $ac_n "checking "for sun_len member in struct sockaddr_un"""... $ac_c" 1>&6 -echo "configure:14051: checking "for sun_len member in struct sockaddr_un"" >&5 +echo "configure:14201: checking "for sun_len member in struct sockaddr_un"" >&5 cat > conftest.$ac_ext < @@ -14060,7 +14210,7 @@ static struct sockaddr_un x; x.sun_len = 1; ; return 0; } EOF -if { (eval echo configure:14064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "$ac_t""yes" 1>&6; { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_SOCKADDR_SUN_LEN @@ -14078,9 +14228,9 @@ fi rm -f conftest* echo $ac_n "checking "for ip_mreq struct in netinet/in.h"""... $ac_c" 1>&6 -echo "configure:14082: checking "for ip_mreq struct in netinet/in.h"" >&5 +echo "configure:14232: checking "for ip_mreq struct in netinet/in.h"" >&5 cat > conftest.$ac_ext < @@ -14090,7 +14240,7 @@ static struct ip_mreq x; ; return 0; } EOF -if { (eval echo configure:14094: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14244: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "$ac_t""yes" 1>&6; { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_MULTICAST @@ -14121,10 +14271,10 @@ echo $ac_n "checking for msgget""... $ac_c" 1>&6 -echo "configure:14125: checking for msgget" >&5 +echo "configure:14275: checking for msgget" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14301: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_msgget=yes" else @@ -14162,15 +14312,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "sys/ipc.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/ipc.h""... $ac_c" 1>&6 -echo "configure:14166: checking for sys/ipc.h" >&5 +echo "configure:14316: checking for sys/ipc.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14174: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14324: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14187,15 +14337,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "sys/msg.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/msg.h""... $ac_c" 1>&6 -echo "configure:14191: checking for sys/msg.h" >&5 +echo "configure:14341: checking for sys/msg.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14199: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14349: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14233,15 +14383,15 @@ ac_safe=`echo "dirent.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for dirent.h""... $ac_c" 1>&6 -echo "configure:14237: checking for dirent.h" >&5 +echo "configure:14387: checking for dirent.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14245: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14395: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14268,15 +14418,15 @@ echo "$ac_t""no" 1>&6 ac_safe=`echo "sys/dir.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/dir.h""... $ac_c" 1>&6 -echo "configure:14272: checking for sys/dir.h" >&5 +echo "configure:14422: checking for sys/dir.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14280: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14430: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14309,15 +14459,15 @@ ac_safe=`echo "nlist.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for nlist.h""... $ac_c" 1>&6 -echo "configure:14313: checking for nlist.h" >&5 +echo "configure:14463: checking for nlist.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14321: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14471: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14347,22 +14497,22 @@ echo "checking "for sound support"" 1>&6 -echo "configure:14351: checking "for sound support"" >&5 +echo "configure:14501: checking "for sound support"" >&5 test -z "$with_native_sound" -a -n "$native_sound_lib" && with_native_sound=yes if test "$with_native_sound" != "no"; then if test -n "$native_sound_lib"; then ac_safe=`echo "multimedia/audio_device.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for multimedia/audio_device.h""... $ac_c" 1>&6 -echo "configure:14358: checking for multimedia/audio_device.h" >&5 +echo "configure:14508: checking for multimedia/audio_device.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14366: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14516: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14418,12 +14568,12 @@ if test -z "$native_sound_lib"; then echo $ac_n "checking for ALopenport in -laudio""... $ac_c" 1>&6 -echo "configure:14422: checking for ALopenport in -laudio" >&5 +echo "configure:14572: checking for ALopenport in -laudio" >&5 ac_lib_var=`echo audio'_'ALopenport | sed 'y%./+-%__p_%'` xe_check_libs=" -laudio " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -14465,12 +14615,12 @@ if test -z "$native_sound_lib"; then echo $ac_n "checking for AOpenAudio in -lAlib""... $ac_c" 1>&6 -echo "configure:14469: checking for AOpenAudio in -lAlib" >&5 +echo "configure:14619: checking for AOpenAudio in -lAlib" >&5 ac_lib_var=`echo Alib'_'AOpenAudio | sed 'y%./+-%__p_%'` xe_check_libs=" -lAlib " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14635: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -14529,15 +14679,15 @@ for dir in "machine" "sys" "linux"; do ac_safe=`echo "${dir}/soundcard.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ${dir}/soundcard.h""... $ac_c" 1>&6 -echo "configure:14533: checking for ${dir}/soundcard.h" >&5 +echo "configure:14683: checking for ${dir}/soundcard.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14541: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14691: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14573,7 +14723,50 @@ done fi - test "$sound_found" = "yes" && with_native_sound=yes + if test "$sound_found" = "yes"; then + with_native_sound=yes + + if test "$opsys" = "netbsd" ; then + +echo $ac_n "checking for _oss_ioctl in -lossaudio""... $ac_c" 1>&6 +echo "configure:14733: checking for _oss_ioctl in -lossaudio" >&5 +ac_lib_var=`echo ossaudio'_'_oss_ioctl | sed 'y%./+-%__p_%'` + +xe_check_libs=" -lossaudio " +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +xe_check_libs="" + +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes" ; then + echo "$ac_t""yes" 1>&6 + native_sound_lib="-lossaudio" +else + echo "$ac_t""no" 1>&6 +fi + + + fi + fi fi if test "$with_native_sound" = "yes"; then @@ -14591,15 +14784,15 @@ if test "$with_nas_sound" != "no"; then ac_safe=`echo "audio/audiolib.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for audio/audiolib.h""... $ac_c" 1>&6 -echo "configure:14595: checking for audio/audiolib.h" >&5 +echo "configure:14788: checking for audio/audiolib.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14603: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:14796: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14617,12 +14810,12 @@ echo $ac_n "checking for AuOpenServer in -laudio""... $ac_c" 1>&6 -echo "configure:14621: checking for AuOpenServer in -laudio" >&5 +echo "configure:14814: checking for AuOpenServer in -laudio" >&5 ac_lib_var=`echo audio'_'AuOpenServer | sed 'y%./+-%__p_%'` xe_check_libs=" -laudio " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14830: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -14672,7 +14865,7 @@ fi libs_x="-laudio $libs_x" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-laudio\" to \$libs_x"; fi cat > conftest.$ac_ext < EOF @@ -14703,7 +14896,7 @@ # Extract the first word of "esd-config", so it can be a program name with args. set dummy esd-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:14707: checking for $ac_word" >&5 +echo "configure:14900: checking for $ac_word" >&5 if test -n "$have_esd_config"; then ac_cv_prog_have_esd_config="$have_esd_config" # Let the user override the test. @@ -14732,10 +14925,10 @@ c_switch_site="$c_switch_site `esd-config --cflags`" && if test "$extra_verbose" = "yes"; then echo " Appending \"`esd-config --cflags`\" to \$c_switch_site"; fi LIBS="`esd-config --libs` $LIBS" && if test "$extra_verbose" = "yes"; then echo " Prepending \"`esd-config --libs`\" to \$LIBS"; fi echo $ac_n "checking for esd_play_stream""... $ac_c" 1>&6 -echo "configure:14736: checking for esd_play_stream" >&5 +echo "configure:14929: checking for esd_play_stream" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_esd_play_stream=yes" else @@ -14809,7 +15002,7 @@ if test "$with_tty" = "yes" ; then echo "checking for TTY-related features" 1>&6 -echo "configure:14813: checking for TTY-related features" >&5 +echo "configure:15006: checking for TTY-related features" >&5 { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_TTY EOF @@ -14822,12 +15015,12 @@ if test -z "$with_ncurses"; then echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6 -echo "configure:14826: checking for tgetent in -lncurses" >&5 +echo "configure:15019: checking for tgetent in -lncurses" >&5 ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'` xe_check_libs=" -lncurses " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15035: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -14871,15 +15064,15 @@ ac_safe=`echo "ncurses/curses.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ncurses/curses.h""... $ac_c" 1>&6 -echo "configure:14875: checking for ncurses/curses.h" >&5 +echo "configure:15068: checking for ncurses/curses.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14883: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:15076: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14901,15 +15094,15 @@ ac_safe=`echo "ncurses/term.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ncurses/term.h""... $ac_c" 1>&6 -echo "configure:14905: checking for ncurses/term.h" >&5 +echo "configure:15098: checking for ncurses/term.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14913: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:15106: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14939,15 +15132,15 @@ c_switch_site="$c_switch_site -I/usr/include/ncurses" ac_safe=`echo "ncurses/curses.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ncurses/curses.h""... $ac_c" 1>&6 -echo "configure:14943: checking for ncurses/curses.h" >&5 +echo "configure:15136: checking for ncurses/curses.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:14951: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:15144: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -14982,12 +15175,12 @@ for lib in curses termlib termcap; do echo $ac_n "checking for tgetent in -l$lib""... $ac_c" 1>&6 -echo "configure:14986: checking for tgetent in -l$lib" >&5 +echo "configure:15179: checking for tgetent in -l$lib" >&5 ac_lib_var=`echo $lib'_'tgetent | sed 'y%./+-%__p_%'` xe_check_libs=" -l$lib " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15195: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15029,12 +15222,12 @@ else echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6 -echo "configure:15033: checking for tgetent in -lcurses" >&5 +echo "configure:15226: checking for tgetent in -lcurses" >&5 ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'` xe_check_libs=" -lcurses " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15063,12 +15256,12 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6 -echo "configure:15067: checking for tgetent in -ltermcap" >&5 +echo "configure:15260: checking for tgetent in -ltermcap" >&5 ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'` xe_check_libs=" -ltermcap " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15128,15 +15321,15 @@ if test "$with_gpm" != "no"; then ac_safe=`echo "gpm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for gpm.h""... $ac_c" 1>&6 -echo "configure:15132: checking for gpm.h" >&5 +echo "configure:15325: checking for gpm.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:15140: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:15333: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -15154,12 +15347,12 @@ echo $ac_n "checking for Gpm_Open in -lgpm""... $ac_c" 1>&6 -echo "configure:15158: checking for Gpm_Open in -lgpm" >&5 +echo "configure:15351: checking for Gpm_Open in -lgpm" >&5 ac_lib_var=`echo gpm'_'Gpm_Open | sed 'y%./+-%__p_%'` xe_check_libs=" -lgpm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15367: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15222,20 +15415,20 @@ test "$with_database_gdbm $with_database_dbm $with_database_berkdb" \ != "no no no" && echo "checking for database support" 1>&6 -echo "configure:15226: checking for database support" >&5 +echo "configure:15419: checking for database support" >&5 if test "$with_database_gdbm $with_database_dbm" != "no no"; then ac_safe=`echo "ndbm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ndbm.h""... $ac_c" 1>&6 -echo "configure:15231: checking for ndbm.h" >&5 +echo "configure:15424: checking for ndbm.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:15239: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:15432: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -15265,12 +15458,12 @@ if test "$with_database_gdbm" != "no"; then echo $ac_n "checking for dbm_open in -lgdbm""... $ac_c" 1>&6 -echo "configure:15269: checking for dbm_open in -lgdbm" >&5 +echo "configure:15462: checking for dbm_open in -lgdbm" >&5 ac_lib_var=`echo gdbm'_'dbm_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lgdbm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15478: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15309,10 +15502,10 @@ if test "$with_database_dbm" != "no"; then echo $ac_n "checking for dbm_open""... $ac_c" 1>&6 -echo "configure:15313: checking for dbm_open" >&5 +echo "configure:15506: checking for dbm_open" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15532: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_dbm_open=yes" else @@ -15354,12 +15547,12 @@ echo $ac_n "checking for dbm_open in -ldbm""... $ac_c" 1>&6 -echo "configure:15358: checking for dbm_open in -ldbm" >&5 +echo "configure:15551: checking for dbm_open in -ldbm" >&5 ac_lib_var=`echo dbm'_'dbm_open | sed 'y%./+-%__p_%'` xe_check_libs=" -ldbm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15567: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15411,10 +15604,10 @@ if test "$with_database_berkdb" != "no"; then echo $ac_n "checking for Berkeley db.h""... $ac_c" 1>&6 -echo "configure:15415: checking for Berkeley db.h" >&5 +echo "configure:15608: checking for Berkeley db.h" >&5 for header in "db/db.h" "db.h"; do cat > conftest.$ac_ext < @@ -15436,7 +15629,7 @@ ; return 0; } EOF -if { (eval echo configure:15440: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:15633: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* db_h_file="$header"; break else @@ -15452,9 +15645,9 @@ if test "$with_database_berkdb" != "no"; then echo $ac_n "checking for Berkeley DB version""... $ac_c" 1>&6 -echo "configure:15456: checking for Berkeley DB version" >&5 +echo "configure:15649: checking for Berkeley DB version" >&5 cat > conftest.$ac_ext < #if DB_VERSION_MAJOR > 1 @@ -15466,7 +15659,7 @@ egrep "yes" >/dev/null 2>&1; then rm -rf conftest* cat > conftest.$ac_ext < #if DB_VERSION_MAJOR > 2 @@ -15478,7 +15671,7 @@ egrep "yes" >/dev/null 2>&1; then rm -rf conftest* cat > conftest.$ac_ext < #if DB_VERSION_MAJOR > 3 @@ -15512,10 +15705,10 @@ rm -f conftest* echo $ac_n "checking for $dbfunc""... $ac_c" 1>&6 -echo "configure:15516: checking for $dbfunc" >&5 +echo "configure:15709: checking for $dbfunc" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$dbfunc=yes" else @@ -15557,12 +15750,12 @@ echo $ac_n "checking for $dbfunc in -ldb""... $ac_c" 1>&6 -echo "configure:15561: checking for $dbfunc in -ldb" >&5 +echo "configure:15754: checking for $dbfunc in -ldb" >&5 ac_lib_var=`echo db'_'$dbfunc | sed 'y%./+-%__p_%'` xe_check_libs=" -ldb " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15770: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15607,12 +15800,12 @@ echo "configure: warning: "db_create is really $dbfunc"" 1>&2 echo $ac_n "checking for $dbfunc in -ldb""... $ac_c" 1>&6 -echo "configure:15611: checking for $dbfunc in -ldb" >&5 +echo "configure:15804: checking for $dbfunc in -ldb" >&5 ac_lib_var=`echo db'_'$dbfunc | sed 'y%./+-%__p_%'` xe_check_libs=" -ldb " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15820: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15682,12 +15875,12 @@ if test "$with_socks" = "yes"; then echo $ac_n "checking for SOCKSinit in -lsocks""... $ac_c" 1>&6 -echo "configure:15686: checking for SOCKSinit in -lsocks" >&5 +echo "configure:15879: checking for SOCKSinit in -lsocks" >&5 ac_lib_var=`echo socks'_'SOCKSinit | sed 'y%./+-%__p_%'` xe_check_libs=" -lsocks " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15754,15 +15947,15 @@ if test "$use_number_lib" = "gmp"; then ac_safe=`echo "gmp.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for gmp.h""... $ac_c" 1>&6 -echo "configure:15758: checking for gmp.h" >&5 +echo "configure:15951: checking for gmp.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:15766: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:15959: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -15780,12 +15973,12 @@ echo $ac_n "checking for __gmpz_init in -lgmp""... $ac_c" 1>&6 -echo "configure:15784: checking for __gmpz_init in -lgmp" >&5 +echo "configure:15977: checking for __gmpz_init in -lgmp" >&5 ac_lib_var=`echo gmp'_'__gmpz_init | sed 'y%./+-%__p_%'` xe_check_libs=" -lgmp " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15993: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15845,15 +16038,15 @@ for library in "" "-lcrypto"; do ac_safe=`echo "mp.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for mp.h""... $ac_c" 1>&6 -echo "configure:15849: checking for mp.h" >&5 +echo "configure:16042: checking for mp.h" >&5 cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:15857: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:16050: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -15873,12 +16066,12 @@ xe_msg_checking="for mp_mfree in -lmp" test -n "$library" && xe_msg_checking="$xe_msg_checking using extra libs $library" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:15877: checking "$xe_msg_checking"" >&5 +echo "configure:16070: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo mp'_'mp_mfree | sed 'y%./+-%__p_%'` xe_check_libs=" -lmp $library" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:16086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15910,12 +16103,12 @@ xe_msg_checking="for mfree in -lmp" test -n "$library" && xe_msg_checking="$xe_msg_checking using extra libs $library" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:15914: checking "$xe_msg_checking"" >&5 +echo "configure:16107: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo mp'_'mfree | sed 'y%./+-%__p_%'` xe_check_libs=" -lmp $library" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:16123: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15968,10 +16161,10 @@ LIBS="$LIBS $library" && if test "$extra_verbose" = "yes"; then echo " Appending \"$library\" to \$LIBS"; fi fi echo $ac_n "checking for mp_move""... $ac_c" 1>&6 -echo "configure:15972: checking for mp_move" >&5 +echo "configure:16165: checking for mp_move" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:16191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_mp_move=yes" else @@ -16025,10 +16218,10 @@ LIBS="$LIBS $library" && if test "$extra_verbose" = "yes"; then echo " Appending \"$library\" to \$LIBS"; fi fi echo $ac_n "checking for move""... $ac_c" 1>&6 -echo "configure:16029: checking for move" >&5 +echo "configure:16222: checking for move" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:16248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_move=yes" else @@ -16098,11 +16291,11 @@ fi cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 +if { (eval echo configure:16299: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit $?) 2>&5 then : else @@ -16345,6 +16538,14 @@ done +if test -z "$package_path" && test -n "$package_prefix" ; then + if test "$with_mule" = "yes" ; then + package_path="~/.xemacs::${package_prefix}/site-packages:${package_prefix}/xemacs-packages:${package_prefix}/mule-packages" + else + package_path="~/.xemacs::${package_prefix}/site-packages:${package_prefix}/xemacs-packages" + fi +fi + PACKAGE_PATH=$package_path @@ -16451,7 +16652,7 @@ -RECURSIVE_MAKE="\$(MAKE) \$(MFLAGS) CC='\$(CC)' CFLAGS='\$(CFLAGS)' LDFLAGS='\$(LDFLAGS)' CPPFLAGS='\$(CPPFLAGS)'" +RECURSIVE_MAKE_ARGS="\$(MFLAGS) CC='\$(CC)' CFLAGS='\$(CFLAGS)' LDFLAGS='\$(LDFLAGS)' CPPFLAGS='\$(CPPFLAGS)'" @@ -17145,7 +17346,7 @@ s%@ld_libs_general@%$ld_libs_general%g s%@ld_libs_window_system@%$ld_libs_window_system%g s%@ld_libs_all@%$ld_libs_all%g -s%@RECURSIVE_MAKE@%$RECURSIVE_MAKE%g +s%@RECURSIVE_MAKE_ARGS@%$RECURSIVE_MAKE_ARGS%g s%@native_sound_lib@%$native_sound_lib%g s%@sound_cflags@%$sound_cflags%g s%@dynodump_arch@%$dynodump_arch%g @@ -17370,6 +17571,12 @@ for dir in . $MAKE_SUBDIR; do ( cd $dir + + + + + + rm -f junk.c < Makefile.in \ sed -e '/^# Generated/d' \ @@ -17386,8 +17593,6 @@ s/$/"/ }' > junk.c; - - echo creating $dir/Makefile $CPP -I. -I${top_srcdir}/src junk.c \ | sed -e 's/^\#.*//' \ @@ -17417,7 +17622,8 @@ mv -f Makefile.new GNUmakefile if test -r "xemacs.def.in"; then - cp -f xemacs.def.in junk.c + rm -f junk.c + cp xemacs.def.in junk.c echo creating $dir/xemacs.def $CPP -I. -I${top_srcdir}/src junk.c \ | sed -e 's/^\#.*//' \ diff --text -u 'xemacs-21.5.18/configure.in' 'xemacs-21.5.19/configure.in' Index: ./configure.in --- ./configure.in Thu Sep 30 00:38:31 2004 +++ ./configure.in Fri Feb 4 02:33:53 2005 @@ -6,7 +6,7 @@ #### Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. #### Copyright (C) 1993-1995 Board of Trustees, University of Illinois. #### Copyright (C) 1996, 1997 Sun Microsystems, Inc. -#### Copyright (C) 1995, 1996, 2002, 2003 Ben Wing. +#### Copyright (C) 1995, 1996, 2002, 2003, 2004 Ben Wing. #### Copyright (C) 2000, 2001 Martin Buchholz. #### Copyright (C) 1998, 1999 J. Kean Johnston. @@ -531,6 +531,7 @@ with_dnet | \ with_infodock | \ with_netinstall | \ + with_optimization | \ with_ipv6_cname | \ external_widget | \ use_kkcc | \ @@ -560,6 +561,8 @@ xemacs_compiler | \ cflags | \ cflags_warning | \ + cflags_optimization | \ + cflags_debugging | \ cpp | \ cppflags | \ libs | \ @@ -698,8 +701,10 @@ flock ) val=flock ;; file | dot ) val=file ;; locking ) val=locking ;; + mmdf ) val=mmdf ;; + pop ) val=pop ;; * ) USAGE_ERROR(["The \`--$optname' option must have one of these values: - \`lockf', \`flock', \`file', \`locking', or \`mmdf'."]) ;; + \`lockf', \`flock', \`file', \`dot', \`locking', \`mmdf', or \`pop'."]) ;; esac eval "$opt=\"$val\"" ;; @@ -785,7 +790,7 @@ dnl Has the user specified one of the path options? prefix | exec_prefix | bindir | datadir | statedir | libdir | \ mandir | infodir | infopath | lispdir | etcdir | \ - archlibdir | docdir | package_path | moduledir ) + archlibdir | docdir | package_path | package_prefix | moduledir ) dnl If the value was omitted, get it from the next argument. if test "$valomitted" = "yes"; then if test "$#" = 0; then @@ -806,6 +811,7 @@ etcdir ) AC_DEFINE(ETCDIR_USER_DEFINED) ;; infodir ) AC_DEFINE(INFODIR_USER_DEFINED) ;; infopath ) AC_DEFINE(INFOPATH_USER_DEFINED) ;; + package_prefix ) AC_DEFINE(PACKAGE_PATH_USER_DEFINED) ;; package_path ) AC_DEFINE(PACKAGE_PATH_USER_DEFINED) ;; datadir ) AC_DEFINE(INFODIR_USER_DEFINED) @@ -1598,6 +1604,7 @@ case "$opsys" in linux* ) pdump=yes ;; dnl glibc 2.3.1 seems to hose unexec darwin ) pdump=yes ;; dnl No "native" working dumper available + cygwin* ) pdump=yes ;; dnl unexec is broken * ) pdump=no ;; esac fi @@ -1671,6 +1678,16 @@ else cflags_warning_specified=no; fi +if test "${cflags_optimization-unset}" != unset + then cflags_optimization_specified=yes; + else cflags_optimization_specified=no; +fi + +if test "${cflags_debugging-unset}" != unset + then cflags_debugging_specified=yes; + else cflags_debugging_specified=no; +fi + xe_save_CFLAGS="$CFLAGS" AC_PROG_CC dnl Autoconf has its own magic for compiler autodetection @@ -1951,7 +1968,7 @@ objects_machine objects_system c_switch_machine c_switch_system ld_switch_machine ld_switch_system unexec ld_switch_shared ld lib_gcc ld_text_start_addr start_files ordinary_link - have_terminfo mail_use_flock mail_use_lockf) && echo "" + have_terminfo mail_use_flock mail_use_lockf mail_using_locking) && echo "" dnl Pick up mingw include path dnl We only cope with headers in mingw, not mingw32: no previous version of @@ -2007,34 +2024,66 @@ fi fi -dnl #### This may need to be overhauled so that all of XEMACS_CC's flags -dnl are handled separately, not just the xe_cflags_warning stuff. - -AC_MSG_CHECKING([for preferred CFLAGS]) +dnl Calculate optimization flags. These will be off by default in beta +dnl versions and on in release versions. -dnl Use either command line flag, environment var, or autodetection -if test "$cflags_specified" = "no"; then - dnl Following values of CFLAGS are known to work well. - dnl Should we take debugging options into consideration? - if test "$GCC" = "yes"; then - CFLAGS="-g -O3" - elif test "$__SUNPRO_C" = "yes"; then - case "$opsys" in - sol2 ) CFLAGS="-xO4" ;; - sunos4* ) CFLAGS="-xO2" ;; - esac - elif test "$__DECC" = "yes"; then - CFLAGS="-O3" - elif test "$CC" = "xlc"; then - CFLAGS="-g -O3 -qstrict -qnoansialias -qlibansi -qro -qmaxmem=20000" - elif test "$__ICC" = "yes"; then - CFLAGS="-g -O3 -Ob2" - dnl ### Add optimal CFLAGS support for other compilers HERE! +if test -z "$with_optimization" ; then + if test -n "$emacs_is_beta" ; then + with_optimization=no else - CFLAGS="-O" ;dnl The only POSIX-approved flag + with_optimization=yes fi fi -AC_MSG_RESULT([${CFLAGS}]) + +dnl #### We should be checking C_OPTIMIZE_SWITCH in m/*, s/*. + +AC_MSG_CHECKING([for preferred optimization flags]) +if test "$with_optimization" = "yes" ; then + if test "$cflags_optimization_specified" = "no"; then + dnl Following values of cflags_optimization are known to work well. + dnl Should we take debugging options into consideration? + if test "$GCC" = "yes"; then + cflags_optimization="-O3" + elif test "$__SUNPRO_C" = "yes"; then + case "$opsys" in + sol2 ) cflags_optimization="-xO4" ;; + sunos4* ) cflags_optimization="-xO2" ;; + esac + elif test "$__DECC" = "yes"; then + cflags_optimization="-O3" + elif test "$CC" = "xlc"; then + dnl see http://www.nersc.gov/vendor_docs/ibm/vac/sc094959.pdf + cflags_optimization="-O3 -qstrict -qnoansialias -qlibansi -qmaxmem=20000" + elif test "$__ICC" = "yes"; then + cflags_optimization="-O3 -Ob2" + dnl ### Add optimal cflags_optimization support for other compilers HERE! + else + cflags_optimization="-O" ;dnl The only POSIX-approved flag + fi + fi +else + cflags_optimization= +fi + +AC_MSG_RESULT([${cflags_optimization}]) + +dnl #### We should be checking C_DEBUG_SWITCH in m/*, s/*. + +AC_MSG_CHECKING([for preferred debugging flags]) +if test "$cflags_debugging_specified" = "no"; then + dnl ### Add optimal debugging support for other compilers HERE! + cflags_debugging="-g" + + debugging_ok_with_optimization=no + if test "$GCC" = "yes" -o "$CC" = "xlc" -o "$__ICC" = "yes"; then + debugging_ok_with_optimization=yes + fi + + if test "$with_optimization" = "yes" -a "$debugging_ok_with_optimization" = "no"; then + cflags_debugging= + fi +fi +AC_MSG_RESULT([${cflags_debugging}]) dnl Calculate warning flags. We separate the flags for warnings from dnl the other flags because we want to force the warnings to be seen @@ -2054,11 +2103,16 @@ elif test "$CC" = "xlc"; then cflags_warning="-qinfo" elif test "$GCC" = "yes"; then - cflags_warning="-Wall -Wno-switch -Winline -Wmissing-prototypes" + cflags_warning="-Wall -Wno-switch -Wundef" + dnl This is not very useful, as it issues warnings that may appear + dnl or disappear rather randomly, cannot easily be fixed, and are + dnl not a big deal. If you want it, add it yourself. + dnl cflags_warning="$cflags_warning -Winline" dnl Yuck, bad compares have been worth at least 3 crashes! - cflags_warning="$cflags_warning -Wsign-compare" - cflags_warning="$cflags_warning -Wundef -Wstrict-prototypes" + dnl Warnings about char subscripts are pretty pointless, though, + dnl and we use them in various places. + cflags_warning="$cflags_warning -Wsign-compare -Wno-char-subscripts" test "$__GCC3" = "yes" && cflags_warning="$cflags_warning -Wpacked" dnl glibc is intentionally not `-Wpointer-arith'-clean. dnl Ulrich Drepper has rejected patches to fix the glibc header files. @@ -2079,6 +2133,7 @@ xe_cflags_warning="$cflags_warning -Wunused-parameter" fi cflags_warning="$cflags_warning -Wshadow -Wmissing-declarations" + cflags_warning="$cflags_warning -Wmissing-prototypes -Wstrict-prototypes" dnl **** If more gcc/g++ flags are added, from here on must handle dnl **** cflags_warning and xe_cflags_warning in parallel elif test "$__ICC" = "yes"; then @@ -2092,13 +2147,33 @@ AC_MSG_CHECKING([for preferred warning flags for CC]) AC_MSG_RESULT([${cflags_warning}]) -dnl Now combine all C flags. Put the warning flags first so that -dnl user-specified flags will override. -dnl Do XE_CFLAGS before adding warning flags to CFLAGS. +dnl Calculate remaining cflags. +dnl Use either command line flag, environment var, or autodetection + +AC_MSG_CHECKING([for remaining CFLAGS]) + +if test "$cflags_specified" = "no"; then + dnl Following values of CFLAGS are known to work well. + if test "$CC" = "xlc"; then + CFLAGS="-qro" + dnl ### Add optimal CFLAGS support for other compilers HERE! + fi +fi +AC_MSG_RESULT([${CFLAGS}]) + +dnl Now combine all C flags. Put the warning and optimization flags first +dnl so that user-specified flags will override. +dnl Do XE_CFLAGS before adding flags to CFLAGS. dnl Flags for XEMACS_CC: -XE_CFLAGS="$xe_cflags_warning $CFLAGS" + +XE_CFLAGS="$xe_cflags_warning $cflags_debugging $cflags_optimization $CFLAGS" dnl Flags for CC: -CFLAGS="$cflags_warning $CFLAGS" +CFLAGS="$cflags_warning $cflags_debugging $cflags_optimization $CFLAGS" + +AC_MSG_CHECKING([total value of XE_CFLAGS]) +AC_MSG_RESULT([${XE_CFLAGS}]) +AC_MSG_CHECKING([total value of CFLAGS]) +AC_MSG_RESULT([${CFLAGS}]) dnl Search for GCC specific build problems we know about if test "$GCC" = "yes"; then @@ -2802,7 +2877,8 @@ elif test "$mail_locking" = "pop"; then with_pop=yes mail_locking= -else mail_locking="dot-locking"; AC_DEFINE(MAIL_LOCK_DOT) +elif test "$mail_locking" = "mmdf"; then AC_DEFINE(MAIL_LOCK_MMDF) +else mail_locking="file"; AC_DEFINE(MAIL_LOCK_DOT) fi test "$mail_locking" = "lockf" -a "$ac_cv_func_lockf" != "yes" && \ XE_DIE("lockf mail locking requested but not available.") @@ -3459,7 +3535,7 @@ fi if test "$with_modules" != "yes"; then MOD_CC="$XEMACS_CC" - MODCFLAGS="\$(CFLAGS) -I../../src -I\$(srcdir)/../../src" + MODCFLAGS="\$(XE_CFLAGS) -I../../src -I\$(srcdir)/../../src" INSTALLPATH="" MOD_INSTALL_PROGRAM="true" OBJECT_TO_BUILD="\$(MODNAME).o" @@ -3581,27 +3657,31 @@ test -z "$with_ldap" && { AC_CHECK_HEADER(ldap.h, ,with_ldap=no) } test -z "$with_ldap" && { AC_CHECK_HEADER(lber.h, ,with_ldap=no) } if test "$with_ldap" != "no"; then - AC_CHECK_LIB(ldap, ldap_search, with_ldap_nolber=yes, with_ldap_nolber=no) - test "$with_ldap_nolber" = "no" && { AC_CHECK_LIB(ldap, ldap_open, with_ldap_lber=yes, with_ldap_lber=no, -llber) } - test "$with_ldap_nolber" = "no" -a "$with_ldap_lber" = "no" && { AC_CHECK_LIB(ldap, ldap_open, with_ldap_krb=yes, with_ldap_krb=no, -llber -lkrb) } - test "$with_ldap_nolber" = "no" -a "$with_ldap_lber" = "no" -a "$with_ldap_krb" = "no" && { AC_CHECK_LIB(ldap, ldap_open, with_ldap_krbdes=yes, with_ldap_krbdes=no, -llber -lkrb -ldes) } - test -z "$with_ldap" -a \( "$with_ldap_lber" = "yes" -o "$with_ldap_nolber" = "yes" -o "$with_ldap_krb" = "yes" -o "$with_ldap_krbdes" = "yes" \) && with_ldap=yes + AC_CHECK_LIB(ldap, ldap_search, with_ldap=yes) + dnl Check for other libraries we need to link with to get the main routines. + test "$with_ldap" != "yes" && { AC_CHECK_LIB(ldap, ldap_open, [with_ldap=yes with_ldap_lber=yes], , -llber) } + test "$with_ldap" != "yes" && { AC_CHECK_LIB(ldap, ldap_open, [with_ldap=yes with_ldap_lber=yes with_ldap_krb=yes], , -llber -lkrb) } + test "$with_ldap" != "yes" && { AC_CHECK_LIB(ldap, ldap_open, [with_ldap=yes with_ldap_lber=yes with_ldap_krb=yes with_ldap_des=yes], , -llber -lkrb -ldes) } + dnl Recently, we need -lber even though the main routines are elsewhere, + dnl because otherwise be get link errors w.r.t. ber_pvt_opt_on. So just + dnl check for that (it's a variable not a fun but that doesn't seem to + dnl matter in these checks) and stick in -lber if so. Can't hurt (even to + dnl stick it in always shouldn't hurt, I don't think) ... #### Someone who + dnl #### understands LDAP needs to fix this properly. + test "$with_ldap_lber" != "yes" && { AC_CHECK_LIB(lber, ber_pvt_opt_on, with_ldap_lber=yes) } fi if test "$with_ldap" = "yes"; then AC_DEFINE(HAVE_LDAP) - if test "$with_ldap_nolber" = "yes" ; then - XE_PREPEND(-lldap, ldap_libs) - else - if test "$with_ldap_krb" = "yes" ; then - XE_PREPEND(-lkrb, ldap_libs) - fi - if test "$with_ldap_krbdes" = "yes" ; then - XE_PREPEND(-ldes, ldap_libs) - XE_PREPEND(-lkrb, ldap_libs) - fi + if test "$with_ldap_des" = "yes" ; then + XE_PREPEND(-ldes, ldap_libs) + fi + if test "$with_ldap_krb" = "yes" ; then + XE_PREPEND(-lkrb, ldap_libs) + fi + if test "$with_ldap_lber" = "yes" ; then XE_PREPEND(-llber, ldap_libs) - XE_PREPEND(-lldap, ldap_libs) fi + XE_PREPEND(-lldap, ldap_libs) save_LIBS="$LIBS" LIBS="$LIBS $ldap_libs" AC_CHECK_FUNCS(ldap_set_option ldap_get_lderrno ldap_result2error ldap_parse_result) LIBS="$save_LIBS" @@ -4226,7 +4306,7 @@ dnl Check for POSIX functions. dnl ---------------------------------------------------------------- -AC_CHECK_FUNCS(cbrt closedir dup2 eaccess fmod fpathconf frexp ftime getaddrinfo gethostname getnameinfo getpagesize getrlimit gettimeofday getcwd getwd link logb lrand48 matherr mkdir mktime perror poll random readlink rename res_init rint rmdir select setitimer setpgid setlocale setsid sigblock sighold sigprocmask snprintf stpcpy strerror strlwr strupr symlink tzset ulimit usleep waitpid vsnprintf fsync ftruncate umask wcslen wcscmp vlimit) +AC_CHECK_FUNCS(cbrt closedir dup2 eaccess fmod fpathconf frexp fsync ftime ftruncate getaddrinfo gethostname getnameinfo getpagesize getrlimit gettimeofday getcwd link logb lrand48 matherr mkdir mktime perror poll random readlink rename res_init rint rmdir select setitimer setpgid setsid sigblock sighold sigprocmask snprintf strerror strlwr strupr symlink tzset ulimit umask usleep vlimit vsnprintf waitpid wcscmp wcslen) dnl getaddrinfo() is borked under hpux11 if test "$ac_cv_func_getaddrinfo" != "no" ; then @@ -4464,6 +4544,23 @@ test "$working_alloca_in_function_calls" != "yes" && \ AC_DEFINE(BROKEN_ALLOCA_IN_FUNCTION_CALLS) +AC_MSG_CHECKING(for working scanf) +AC_TRY_RUN([ +int +main (int argc, char **argv) +{ + int ret, cp1, cp2, endcount; + char *p = "0x7d 0x000E "; + ret = sscanf (p, "%i %i%n", &cp1, &cp2, &endcount); + /* endcount should be 13 but it's 11 in Cygwin newlib after 6/04; + this breaks unicode.c */ + return endcount != 13; +} +], working_scanf=yes, working_scanf=no) +AC_MSG_RESULT($working_scanf) +test "$working_scanf" != "yes" && \ + AC_DEFINE(CYGWIN_SCANF_BUG) + dnl Check whether strcoll exists and works correctly. (This does more dnl than just check for its existence.) If so, it defines HAVE_STRCOLL. AC_FUNC_STRCOLL @@ -4665,7 +4762,16 @@ done fi - test "$sound_found" = "yes" && with_native_sound=yes + if test "$sound_found" = "yes"; then + with_native_sound=yes + + dnl NetBSD can use Linux's sound API, but it needs an extra library at + dnl link time to do so. (OpenBSD apparently needs the same; not written + dnl or tested.) + if test "$opsys" = "netbsd" ; then + AC_CHECK_LIB(ossaudio, _oss_ioctl, native_sound_lib="-lossaudio") + fi + fi fi if test "$with_native_sound" = "yes"; then @@ -5177,6 +5283,14 @@ done AC_SUBST(INFOPATH) +if test -z "$package_path" && test -n "$package_prefix" ; then + if test "$with_mule" = "yes" ; then + package_path="~/.xemacs::${package_prefix}/site-packages:${package_prefix}/xemacs-packages:${package_prefix}/mule-packages" + else + package_path="~/.xemacs::${package_prefix}/site-packages:${package_prefix}/xemacs-packages" + fi +fi + AC_SUBST(package_path) AC_SUBST(PACKAGE_PATH_USER_DEFINED) PACKAGE_PATH=$package_path @@ -5288,8 +5402,8 @@ AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) -RECURSIVE_MAKE="\$(MAKE) \$(MFLAGS) CC='\$(CC)' CFLAGS='\$(CFLAGS)' LDFLAGS='\$(LDFLAGS)' CPPFLAGS='\$(CPPFLAGS)'" -AC_SUBST(RECURSIVE_MAKE) +RECURSIVE_MAKE_ARGS="\$(MFLAGS) CC='\$(CC)' CFLAGS='\$(CFLAGS)' LDFLAGS='\$(LDFLAGS)' CPPFLAGS='\$(CPPFLAGS)'" +AC_SUBST(RECURSIVE_MAKE_ARGS) AC_SUBST(native_sound_lib) AC_SUBST(sound_cflags) @@ -5638,8 +5752,26 @@ [for dir in . $MAKE_SUBDIR; do ( cd $dir + +dnl Normally []'s are used for quoting but this will cause problems +dnl since we use brackets in sed. When not inside of a macro definition, +dnl two brackets become one, but inside of a macro definition you need +dnl more, or something -- I don't understand, but Martin probably does. +dnl We put the brackets back later. +dnl [ben] +changequote(<<,>>)dnl + +dnl MAKE_JUNK_C(filename): +dnl Copy a .in file to junk.c in preparation for passing through the +dnl C preprocessor. Delete comment lines, pass lines that will be +dnl interpreted by cpp through directly, and put quotes around remaining +dnl lines, to avoid problems from overly helpful preprocessors that +dnl "helpfully" put extra quotes in various places for later use by the +dnl compiler. Later, the quotes will be removed. + +define(<>, rm -f junk.c - < Makefile.in \ + < <<$1>> \ sed -e '/^# Generated/d' \ -e 's%/\*\*/#.*%%' \ -e 's/^ *# */#/' \ @@ -5652,15 +5784,15 @@ }' \ dnl Quote other lines to protect from CPP substitution -e '/./ { -s/\([[\"]]\)/\\\1/g +s/\([\"]\)/\\\1/g s/^/"/ s/$/"/ }' > junk.c; +)dnl MAKE_JUNK_C -dnl Create a GNUmakefile and Makefile from Makefile.in. +dnl CPP_MAKEFILE(CPPFLAGS,filename): +dnl Pass junk.c through the preprocessor and put the result in FILENAME. -changequote(<<,>>)dnl -dnl CPP_MAKEFILE(CPPFLAGS,filename) define(<>, echo creating $dir/<<$2>> $CPP -I. -I${top_srcdir}/src <<$1>> junk.c \ @@ -5681,10 +5813,18 @@ mv -f Makefile.new <<$2>> )dnl CPP_MAKEFILE +dnl Create a GNUmakefile and Makefile from Makefile.in. +dnl Create xemacs.def from xemacs.def.in in the same fashion, +dnl if it exists (i.e. in the src/ directory). + MAKE_JUNK_C(Makefile.in) CPP_MAKEFILE(,Makefile) CPP_MAKEFILE(-DUSE_GNU_MAKE,GNUmakefile) if test -r "xemacs.def.in"; then - cp -f xemacs.def.in junk.c +dnl #### We should be using MAKE_JUNK_C instead of the next two lines. +dnl #### But the comments in xemacs.def.in need to be converted from C-style +dnl #### to lines beginning with ##. + rm -f junk.c + cp xemacs.def.in junk.c CPP_MAKEFILE(,xemacs.def) fi changequote([,])dnl diff --text -u 'xemacs-21.5.18/configure.usage' 'xemacs-21.5.19/configure.usage' Index: ./configure.usage --- ./configure.usage Tue Apr 6 21:13:55 2004 +++ ./configure.usage Wed Jan 26 19:02:13 2005 @@ -42,6 +42,22 @@ --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. +--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. +--cflags-optimization=FLAGS + Override compiler flags used to control optimization. + Only has an effect when optimization is enabled. + Normally, don't set this, as XEmacs will already set + the maximum safe optimization flags appropriate for + the compiler being invoked. +--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). --cpp=PROG C preprocessor to use (e.g. /usr/ccs/lib/cpp or cc -E) --cppflags=FLAGS C preprocessor flags (e.g. -I/foo or -Dfoo=bar) --libs=LIBS Additional libraries (e.g. -lfoo) @@ -98,6 +114,17 @@ searched before the installation packages. --with-site-modules=no Disable site-modules directory in the XEmacs hierarchy, which is searched before the installation modules. +--package-prefix=PATH Specify a directory under which packages will + be searched. The directories `xemacs-packages' and + (if MULE support exists) `mule-packages' (along with, + optionally, `site-packages') should exist under this + directory. This is preferred to specifying + `--package-path' directly and is equivalent to + --package-path="~/.xemacs::${package-prefix}/\ + site-packages:${package_prefix}/xemacs-packages:\ + ${package_prefix}/mule-packages" + (or the same without `.../mule-packages' if no + MULE support exists) --package-path=PATH Directories to search for packages to dump with xemacs. PATH splits into three parts separated by double colons (::), an early, a late, and a last part, @@ -259,8 +286,10 @@ ------------- --mail-locking=TYPE (*) Specify the locking to be used by movemail to prevent - concurrent updates of mail spool files. Valid types - are `lockf', `flock', `dot', `locking' or `mmdf'. + concurrent updates of mail spool files. Valid types + are `lockf', `flock', `file', `dot' (same as `file'), + `locking', `mmdf' and `pop' (equivalent to + `--with-pop=yes'). --with-pop Support POP for mail retrieval. --with-kerberos Support Kerberos-authenticated POP. --with-hesiod Support Hesiod to get the POP server host. diff --text -u 'xemacs-21.5.18/etc/ChangeLog' 'xemacs-21.5.19/etc/ChangeLog' Index: ./etc/ChangeLog --- ./etc/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./etc/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,68 @@ +2005-02-18 Stephen J. Turnbull + + * XEmacs 21.5.19 "chives" is released. + +2005-02-03 Jerry James + + * ETAGS.EBNF: Update to author version 17.11. + +2005-01-31 Ben Wing + + Delete stuff that is irrelevant, mislocated or woefully out-of-date. + + * GNU: Delete. + * SERVICE: Delete. + * ORDERS, ORDERS.EUROPE, ORDERS.JAPAN: Delete. + * CHARSETS, CODINGS: Delete. + * DEBUG, LPF, MORE.STUFF, MOTIVATION: Delete. + * aliases.ksh: Delete. (moved to xemacs-builds/steve) + * README.HYPERBOLE, README.OO-BROWSER: Delete. + * chr.png, chrm.png: Move to photos/. + * check_cygwin_setup.sh: Delete. + * gnu.xpm, gnu.xbm, sink.xbm: Delete. + * ms-kermit, ms-kermit-7bit: Delete. + * TERMS: Delete. + + * DISTRIB, FTP, MACHINES, MAILINGLISTS, PACKAGES: + Delete and move to FAQ. + + * BETA: + Delete and move to man/beta.texi. + + * README: Update. + +2004-11-13 Ben Wing + + * CODING-STANDARDS: Delete and incorporate into Internals manual. + +2004-11-16 Stephen J. Turnbull + + * gnuserv.1: Various fixes and improvements. + * gnuserv.README: Strengthen self-deprecation. + +2004-11-22 Adrian Aichner + + * TUTORIAL: Typo fixes, courtesy of Andreas Eder + . + +2004-11-07 Malcolm Purvis + + * photos/purvis.png, photos/purvism.png: New files. + +2004-10-26 Ben Wing + + * BETA: + * BETA (writing): Removed. + * BETA (--error-checking): New. + * BETA (--compiler): New. + * BETA (--xemacs-compiler): New. + * BETA (--package-path): New. + * BETA (--srcdir): New. + * BETA (--site-prefixes): New. + * BETA (Mail): + Rewrite section on configure to indicate what flags are important + and what not. + 2004-10-22 Stephen J. Turnbull * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/etc/ETAGS.EBNF' 'xemacs-21.5.19/etc/ETAGS.EBNF' Index: ./etc/ETAGS.EBNF --- ./etc/ETAGS.EBNF Thu Oct 7 23:51:11 2004 +++ ./etc/ETAGS.EBNF Fri Feb 4 03:09:30 2005 @@ -2,7 +2,7 @@ This file contains two sections: -1) An EBNF (Extended Backus Normal Form) description of the format of +1) An EBNF (Extended Backus-Naur Form) description of the format of the tags file created by etags.c and interpreted by etags.el; 2) A discussion of tag names and implicit tag names. diff --text -u 'xemacs-21.5.18/etc/README' 'xemacs-21.5.19/etc/README' Index: ./etc/README --- ./etc/README Thu Mar 27 21:57:44 2003 +++ ./etc/README Tue Feb 1 05:08:37 2005 @@ -3,40 +3,21 @@ of interest to XEmacs users, some programs used by or with XEmacs, and the file of on-line documentation for XEmacs. -BETA Information about Beta versions -CHARSETS Character set descriptions -CODING-STANDARDS XEmacs C & Lisp coding standards -CODINGS Character set codings -COOKIES Urban Legend, or True Story? :-) COPYING GNU Public License -COPYING.LIB Library GNU Public License -DEBUG Hints on how to debug XEmacs -DISTRIB How to obtain copies of XEmacs and Emacs +ChangeLog ChangeLog for etc/ +ETAGS.EBNF Description of TAGS file format Emacs.ad Sample Resource file -FTP XEmacs FTP Mirrors -GNU GNU Manifesto -GOATS Complete XEmacs internals documentation +HELLO Hello in many languages (Mule test file) InstallGuide Fast track to installation -LPF Information about the League for Programming Freedom -MACHINES List of known machines configurations (OLD) -MAILINGLISTS List of available Mailing lists -MORE.STUFF List of useful unbundled packages -NEWS XEmacs 21.4 release information -ORDERS -ORDERS.EUROPE -ORDERS.JAPAN Order forms for GNU software -PACKAGES List of packages available for 21.4 release +NEWS XEmacs 21.5 release information +ONEWS Older release information +OONEWS Even older release information README This file -README.HYPERBOLE -README.OO-BROWSER How to obtain Hyperbole and the OO-Browser -SERVICE How to obtain paid support for free software -TERMS Information about termcap entries TUTORIAL Tutorial for first time users (English version) TUTORIAL.* Tutorials in non-English languages +VEGETABLES XEmacs 21.5 code names XKeysymDB X Keysym Database with Motif bindings -aliases.sh Useful shell aliases cbx.png "Created by XEmacs" logo -check_cygwin_setup.sh Script to check for presence of Cygwin ctags.1 Ctags man page custom/ Images used in Custom mode editclient.sh Either start up XEmacs or connect to a running one @@ -44,18 +25,15 @@ emacsstrs.sco Special files for running on an SCO console eos/ Images for EOS support (GUD) etags.1 Etags man page -gnu.xbm -gnu.xpm Image of a Gnu. gnuattach.1 Gnuattach man page gnuclient.1 Gnuclient man page gnudoit.1 Gnudoit man page gnuserv.1 Gnuserv man page gnuserv.README Original README file from gnuserv -gnusref.tex Gnus reference card gray1.xbm Gray bitmap -ms-kermit -ms-kermit-7bit Files for running XEmacs through kermit -photos/*.Z Various pictures of XEmacs developers +idd/ ? +package-index.LATEST.gpg ? +photos/* Various pictures of XEmacs developers recycle.xpm recycle2.xpm Two versions of oversized Recycle cursor refcard.ps.gz Postscript version of XEmacs reference card @@ -63,19 +41,18 @@ sample.Xdefaults (legacy -- to be removed) sample.Xresources Example ~/.Xresources file sample.init.el Example ~/.xemacs/init.el file -sink.xbm A Gnu icon sparcworks/ Support files for Sparcworks tests/ Testcases for external widget -time/ Image files for display-time toolbar/ Image files for the toolbar trash.xpm Garbage can icon +unicode/ Unicode conversion tables xemacs-beta.xpm XEmacs Beta logo +xemacs-enhanced.png "XEmacs-enhanced" logo xemacs-fe.sh XEmacs frontend driver xemacs-icon.xpm xemacs-icon2.xbm xemacs-icon2.xpm xemacs-icon3.xpm Various versions of an XEmacs WM icon -xemacs-ja.1 Japanese XEmacs man page xemacs.1 XEmacs man page xemacs.xbm xemacs.xpm XEmacs logo used on the splash screen diff --text -u 'xemacs-21.5.18/etc/gnuserv.1' 'xemacs-21.5.19/etc/gnuserv.1' Index: ./etc/gnuserv.1 --- ./etc/gnuserv.1 Fri Apr 13 03:20:50 2001 +++ ./etc/gnuserv.1 Tue Dec 14 18:56:38 2004 @@ -17,29 +17,32 @@ .SH DESCRIPTION .PP +\fIgnuserv\fP is a server program run as a subprocess of XEmacs to handle +all incoming and outgoing requests from \fIgnuclient\fP. It is not usually +invoked directly, but is started from XEmacs by loading the \fIgnuserv\fP +package and evaluating the Lisp form (gnuserv-start). +.PP \fIgnuclient\fP allows the user to request a running XEmacs process to edit the named files or directories and/or evaluate lisp forms. -Depending on your environment, it can be an X frame or a TTY frame. +Depending on your environment, TTY, X, GTK, or MS Windows frames, as well as +batch (frameless) execution of Lisp may be available. One typical use for this is with a dialup connection to a machine on which an XEmacs process is currently running. .PP \fIgnudoit\fP is a shell script frontend to ``gnuclient -batch -eval form''. Its use is deprecated. Try to get used to calling gnuclient directly. .PP -\fIgnuserv\fP is the server program that is set running by XEmacs to -handle all incoming and outgoing requests. It is not usually invoked -directly, but is started from XEmacs by loading the \fIgnuserv\fP -package and evaluating the Lisp form (gnuserv-start). -.PP \fIgnuattach\fP no longer exists. Its functionality has been replaced by \fIgnuclient -nw\fP. .SH OPTIONS .PP -\fIgnuclient\fP supports as much of the command line options of Emacs as -makes sense in this context. In addition it adds a few of its own. +\fIgnuclient\fP supports as many of the command line options of Emacs as +make sense in this context. In addition it adds a few of its own. .br -Options with long names can also be specified using a double -hyphen instead of a single one. +For backward compatibility, ``long'' options (\fi.e.\fP, with doubled hyphen) +may be specified using a single hyphen instead of a doubled one. Similarly, +the ``-nw'' option is a historical artifact: a multiletter option with no +double-hyphen version. .TP 8 .BI \-nw This option makes \fIgnuclient\fP act as a frontend such that XEmacs @@ -49,7 +52,7 @@ the same machine as gnuclient. This is the default if the `DISPLAY' environment variable is not set. .TP 8 -.BI \-display " display, " \--display " display" +.BI \--display " display, " \-display " display" If this option is given or the `DISPLAY' environment variable is set then gnuclient will tell XEmacs to edit files in a frame on the specified X device. @@ -59,7 +62,8 @@ made with the XEmacs process. Normally \fIgnuclient\fP waits until all of the files on the command line have been finished with (their buffers killed) by the XEmacs process, and all the forms have been -evaluated. +evaluated. Note that this is \fIdifferent\fP from XEmacs itself, where +this option means to inhibit loading of the user init file. .TP 8 .BI \-v When this option is specified \fIgnuclient\fP will request for the @@ -81,26 +85,25 @@ .BI \-f " function," Make Emacs execute the lisp function. .TP 8 -.BI \-eval " form" -Make Emacs execute the lisp form. +.BI \--eval " form, " \-eval " form" +Make Emacs execute the Lisp form. .TP 8 .BI \-h " hostname" Used only with Internet-domain sockets, this option specifies the host machine which should be running \fIgnuserv\fP. If this option is not specified then the value of the environment variable GNU_HOST is used if set. If no hostname is specified, and the GNU_HOST variable is not -set, an internet connection will not be attempted. N\.B.: -\fIgnuserv\fP does NOT allow internet connections unless XAUTH +set, an Internet connection will not be attempted. N\.B.: +\fIgnuserv\fP does NOT allow Internet connections unless XAUTH authentication is used or the GNU_SECURE variable has been specified and points at a file listing all trusted hosts. (See SECURITY below.) .br -Note that an internet address may be specified instead of a hostname -which can speed up connections to the server by quite a bit, -especially if the client machine is running YP. +An Internet address (``dotted-quad'') may be specified instead of a +hostname. IPv6 support is not robust. .br -Note also that a hostname of \fBunix\fP can be used to specify that +A hostname of \fBunix\fP can be used to specify that the connection to the server should use a Unix-domain socket (if supported) rather than an Internet-domain socket. .TP 8 @@ -133,16 +136,15 @@ The cursor is put at line number 'n' if specified. .SH SETUP -\fIgnuserv\fP is packaged standardly with recent versions of XEmacs. -Therefore, you should be able to start the server simply by evaluating -the XEmacs Lisp form (gnuserv-start), or equivalently by typing -`M-x gnuserv-start'. +\fIgnuserv\fP is included with recent versions of XEmacs; no installation +is required. The server must be started before clients may attempt to +connect. Start the server by evaluating the Lisp form (gnuserv-start), or +interactively by typing `M-x gnuserv-start'. .SH CONFIGURATION -The behavior of this suite of program is mostly controlled on the lisp -side in Emacs and its behavior can be customized to a large extent. -Type `M-x customize-group RET gnuserv RET' for easy access. More -documentation can be found in the file `gnuserv.el' +The behavior of this suite of programs can be customized to a large extent. +Type `M-x customize-group RET gnuserv RET'. More documentation can be found +in the file `gnuserv.el' .SH EXAMPLE .RS 4 @@ -156,62 +158,63 @@ .br More examples and sample wrapper scripts are provided in the -etc/gnuserv directory of the Emacs installation. +etc/gnuserv directory of the XEmacs installation. .SH SYSV IPC -SysV IPC is used to communicate between \fIgnuclient\fP and -\fIgnuserv\fP if the symbol SYSV_IPC is defined at the top of -gnuserv.h. This is incompatible with both Unix-domain and +SysV IPC is a build-time option, enabled by defining the symbol SYSV_IPC +at the top of gnuserv.h. It is used to communicate between \fIgnuclient\fP +and \fIgnuserv\fP. It is incompatible with both Unix-domain and Internet-domain socket communication as described below. A file called /tmp/gsrv??? is created as a key for the message queue, and if removed will cause the communication between server and client to fail until the server is restarted. .SH UNIX-DOMAIN SOCKETS -A Unix-domain socket is used to communicate between \fIgnuclient\fP -and \fIgnuserv\fP if the symbol UNIX_DOMAIN_SOCKETS is defined at the -top of gnuserv.h. A file called /tmp/gsrvdir????/gsrv is created for +Unix-domain sockets are a build-time option, enabled by defining the symbol +UNIX_DOMAIN_SOCKETS at the top of gnuserv.h. A Unix-domain socket is used +to communicate between \fIgnuclient\fP +and \fIgnuserv\fP. A file called /tmp/gsrvdir????/gsrv is created for communication. If the symbol USE_TMPDIR is set at the top of gnuserv.h, $TMPDIR, when set, is used instead of /tmp. If that file is deleted, or TMPDIR has different values for the server and the client, communication between server and client will fail. Only the user running gnuserv will be able to connect to the socket. .SH INTERNET-DOMAIN SOCKETS -Internet-domain sockets are used to communicate between -\fIgnuclient\fP and \fIgnuserv\fP if the symbol -INTERNET_DOMAIN_SOCKETS is defined at the top of gnuserv.h. Both -Internet-domain and Unix-domain sockets can be used at the same -time. If a hostname is specified via -h or via the GNU_HOST +Internet-domain sockets are a build-time option, enabled by defining the +symbol INTERNET_DOMAIN_SOCKETS at the top of gnuserv.h. Internet-domain +sockets are used to communicate between \fIgnuclient\fP and \fIgnuserv\fP. +Both Internet-domain and Unix-domain sockets can be used at the same +time. If a hostname is specified via -h or via the GNU_HOST environment variable, \fIgnuclient\fP establish connections using an -internet domain socket. If not, a local connection is attempted via -either a unix-domain socket or SYSV IPC. +Internet domain socket. If not, a local connection is attempted via +either a Unix-domain socket or SYSV IPC. .SH SECURITY Using Internet-domain sockets, a more robust form of security is needed that wasn't necessary with either Unix-domain sockets or SysV IPC. Currently, two authentication protocols are supported to provide this: MIT-MAGIC-COOKIE-1 (based on the X11 xauth(1) program) and a simple host-based access control mechanism, hereafter called -GNUSERV-1. The GNUSERV-1 protocol is always available, whereas support -for MIT-MAGIC-COOKIE-1 may or may not have been enabled (via a #define -at the top of gnuserv.h) at compile-time. +GNUSERV-1. The GNUSERV-1 protocol is always available. Support +for MIT-MAGIC-COOKIE-1 is enabled (by defining AUTH_MAGIC_COOKIE +at the top of gnuserv.h. .PP \fIgnuserv\fP, using GNUSERV-1, performs a limited form of access -control at the machine level. By default no internet-domain socket is +control at the machine level. By default no Internet-domain socket is opened. If the variable GNU_SECURE can be found in \fIgnuserv\fP's environment, and it names a readable filename, then this file is opened and assumed to be a list of hosts, one per line, from which the server will allow requests. Connections from any other host will be rejected. Even the machine on which \fIgnuserv\fP is running is not -permitted to make connections via the internet socket unless its +permitted to make connections via the Internet socket unless its hostname is explicitly specified in this file. Note that a host may be either a numeric IP address or a hostname, and that .I any user on an approved host may connect to your gnuserv and execute arbitrary -elisp (e.g., delete all your files). +Lisp (e.g., delete all your files). If this file contains a lot of -hostnames then the server may take quite a time to start up. +hostnames then the server may take quite a long time to start up. .PP -When the MIT-MAGIC-COOKIE-1 protocol is enabled, an internet socket +When the MIT-MAGIC-COOKIE-1 protocol is enabled, an Internet socket \fIis\fP opened by default. \fIgnuserv\fP will accept a connection from any host, and will wait for a "magic cookie" (essentially, a password) to be presented by the client. If the client doesn't present the @@ -267,7 +270,7 @@ .PP .TP 8 .B DISPLAY -Default X device to put edit frame. +Default X (or GTK) device for display of edit frame. .SH FILES .PP @@ -278,7 +281,7 @@ .B /tmp/gsrvdir???/gsrv (unix domain sockets only) .TP 8 -.B ~/.emacs +.B ~/.xemacs/init.el XEmacs customization file, see xemacs(1). .SH SEE ALSO .PP diff --text -u 'xemacs-21.5.18/etc/gnuserv.README' 'xemacs-21.5.19/etc/gnuserv.README' Index: ./etc/gnuserv.README --- ./etc/gnuserv.README Tue Jun 30 15:35:13 1998 +++ ./etc/gnuserv.README Tue Dec 14 18:56:38 2004 @@ -1,5 +1,6 @@ -This file is not meant to be proper documentation. See the file gnuserv.1 for -more information. +**** WARNING **** +This file was never meant to be proper documentation, and now is bitrotted. +See the file gnuserv.1 and/or the sources for more information. **** NOTE: This version of gnuserv has some enhancements over the original version diff --text -u 'xemacs-21.5.18/lib-src/ChangeLog' 'xemacs-21.5.19/lib-src/ChangeLog' Index: ./lib-src/ChangeLog --- ./lib-src/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./lib-src/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,70 @@ +2005-02-18 Stephen J. Turnbull + + * XEmacs 21.5.19 "chives" is released. + +2005-01-29 Vin Shelton + + * movemail.c (popmail): Pass error string as format parameter + instead of as part of format string. Security fixes for + CAN-2005-0100. + +2005-02-03 Jerry James + + * etags.c: Update to author version 17.11. + +2005-01-26 Ben Wing + + * fakemail.c (main): Add args to fix warning. + +2005-01-25 Ben Wing + + * insert-data-in-exec.c (main): + Need to open everything as binary. + +2004-12-06 Ben Wing + + * i.c (pump): + Undo change of 2003-03-06. It causes truncation of output at the end. + +2004-12-06 Ben Wing + + * gnuclient.c: + * gnuclient.c (get_current_working_directory): + * gnuclient.c (filename_expand): + * gnuclient.c (main): + Use QXE_PATH_MAX. + +2004-12-05 Ben Wing + + * make-docfile.c (main): + * make-docfile.c (scan_c_file): + Use QXE_PATH_MAX. + +2004-11-08 Stephen J. Turnbull + + * ellcc.h.in: Use XE_CFLAGS, not CFLAGS. + +2004-10-14 Ben Wing + + * digest-doc.c (main): + * make-dump-id.c (main): + * profile.c: + * profile.c (main): + * sorted-doc.c (main): + Add proper decls for main(). + + * make-msgfile.c: + Document that this is old junk. + Move proposal to text.c. + + * make-msgfile.lex: + Move proposal to text.c. + + * make-mswin-unicode.pl: + Convert error-generating code so that the entire message will + be seen as a single unrecognized token. + + 2004-10-22 Stephen J. Turnbull * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/lib-src/digest-doc.c' 'xemacs-21.5.19/lib-src/digest-doc.c' Index: ./lib-src/digest-doc.c --- ./lib-src/digest-doc.c Tue Sep 21 04:19:10 2004 +++ ./lib-src/digest-doc.c Fri Nov 5 08:05:47 2004 @@ -11,7 +11,7 @@ #include int -main () +main (int argc, char **argv) { register int ch; register int notfirst = 0; diff --text -u 'xemacs-21.5.18/lib-src/ellcc.h.in' 'xemacs-21.5.19/lib-src/ellcc.h.in' Index: ./lib-src/ellcc.h.in --- ./lib-src/ellcc.h.in Mon Nov 18 15:52:24 2002 +++ ./lib-src/ellcc.h.in Tue Nov 9 00:14:45 2004 @@ -9,7 +9,7 @@ #define ELLCC_HDR #define ELLCC_CC "@XEMACS_CC@" -#define ELLCC_CFLAGS "@CFLAGS@" +#define ELLCC_CFLAGS "@XE_CFLAGS@" #define ELLCC_CPPFLAGS "@CPPFLAGS@" #define ELLCC_LDFLAGS "@LDFLAGS@" #define ELLCC_CF_GENERAL "@c_switch_general@" diff --text -u 'xemacs-21.5.18/lib-src/etags.c' 'xemacs-21.5.19/lib-src/etags.c' Index: ./lib-src/etags.c --- ./lib-src/etags.c Thu Oct 7 23:51:19 2004 +++ ./lib-src/etags.c Fri Feb 4 03:09:26 2005 @@ -1,5 +1,5 @@ /* Tags file maker to go with GNU Emacs -*- coding: latin-1 -*- - Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2001, 2002 + Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2004 Free Software Foundation, Inc. and Ken Arnold This file is not considered part of GNU Emacs. @@ -40,7 +40,7 @@ * configuration file containing regexp definitions for etags. */ -char pot_etags_version[] = "@(#) pot revision number is 17.6"; +char pot_etags_version[] = "@(#) pot revision number is 17.11"; #define TRUE 1 #define FALSE 0 @@ -342,6 +342,7 @@ static void Cplusplus_entries __P((FILE *)); static void Cstar_entries __P((FILE *)); static void Erlang_functions __P((FILE *)); +static void Forth_words __P((FILE *)); static void Fortran_functions __P((FILE *)); static void HTML_labels __P((FILE *)); static void Lisp_functions __P((FILE *)); @@ -630,6 +631,12 @@ "In Erlang code, the tags are the functions, records and macros\n\ defined in the file."; +char *Forth_suffixes [] = + { "fth", "tok", NULL }; +static char Forth_help [] = +"In Forth code, tags are words defined by `:',\n\ +constant, code, create, defer, value, variable, buffer:, field."; + static char *Fortran_suffixes [] = { "F", "f", "f90", "for", NULL }; static char Fortran_help [] = @@ -777,6 +784,7 @@ { "c*", no_lang_help, Cstar_entries, Cstar_suffixes }, { "cobol", Cobol_help, Cobol_paragraphs, Cobol_suffixes }, { "erlang", Erlang_help, Erlang_functions, Erlang_suffixes }, + { "forth", Forth_help, Forth_words, Forth_suffixes }, { "fortran", Fortran_help, Fortran_functions, Fortran_suffixes }, { "html", HTML_help, HTML_labels, HTML_suffixes }, { "java", Cjava_help, Cjava_entries, Cjava_suffixes }, @@ -1179,12 +1187,14 @@ globals = TRUE; } + /* When the optstring begins with a '-' getopt_long does not rearrange the + non-options arguments to be at the end, but leaves them alone. */ optstring = "-"; #ifdef ETAGS_REGEXPS optstring = "-r:Rc:"; #endif /* ETAGS_REGEXPS */ - if (LONG_OPTIONS) - optstring += 1; + if (!LONG_OPTIONS) + optstring += 1; /* remove the initial '-' */ optstring = concat (optstring, "Cf:Il:o:SVhH", (CTAGS) ? "BxdtTuvw" : "aDi:"); @@ -1284,6 +1294,7 @@ /* NOTREACHED */ } + /* No more options. Store the rest of arguments. */ for (; optind < argc; optind++) { argbuffer[current_arg].arg_type = at_filename; @@ -4074,10 +4085,18 @@ char_pointer = line_buffer.buffer, \ TRUE); \ ) -#define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \ - (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \ - && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \ - && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */ + +#define LOOKING_AT(cp, kw) /* kw is the keyword, a literal string */ \ + ((assert("" kw), TRUE) /* syntax error if not a literal string */ \ + && strneq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \ + && notinname ((cp)[sizeof(kw)-1]) /* end of kw */ \ + && ((cp) = skip_spaces((cp)+sizeof(kw)-1))) /* skip spaces */ + +/* Similar to LOOKING_AT but does not use notinname, does not skip */ +#define LOOKING_AT_NOCASE(cp, kw) /* the keyword is a literal string */ \ + ((assert("" kw), TRUE) /* syntax error if not a literal string */ \ + && strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \ + && ((cp) += sizeof(kw)-1)) /* skip spaces */ /* * Read a file, but do no processing. This is used to do regexp @@ -4955,7 +4974,7 @@ /* - * Postscript tag functions + * Postscript tags * Just look for lines where the first character is '/' * Also look at "defineps" for PSWrap * Ideas by: @@ -4986,6 +5005,43 @@ /* + * Forth tags + * Ignore anything after \ followed by space or in ( ) + * Look for words defined by : + * Look for constant, code, create, defer, value, and variable + * OBP extensions: Look for buffer:, field, + * Ideas by Eduardo Horvath (2004) + */ +static void +Forth_words (inf) + FILE *inf; +{ + register char *bp; + + LOOP_ON_INPUT_LINES (inf, lb, bp) + while ((bp = skip_spaces (bp))[0] != '\0') + if (bp[0] == '\\' && iswhite(bp[1])) + break; /* read next line */ + else if (bp[0] == '(' && iswhite(bp[1])) + do /* skip to ) or eol */ + bp++; + while (*bp != ')' && *bp != '\0'); + else if ((bp[0] == ':' && iswhite(bp[1]) && bp++) + || LOOKING_AT_NOCASE (bp, "constant") + || LOOKING_AT_NOCASE (bp, "code") + || LOOKING_AT_NOCASE (bp, "create") + || LOOKING_AT_NOCASE (bp, "defer") + || LOOKING_AT_NOCASE (bp, "value") + || LOOKING_AT_NOCASE (bp, "variable") + || LOOKING_AT_NOCASE (bp, "buffer:") + || LOOKING_AT_NOCASE (bp, "field")) + get_tag (skip_spaces (bp), NULL); /* Yay! A definition! */ + else + bp = skip_non_spaces (bp); +} + + +/* * Scheme tag functions * look for (def... xyzzy * (def... (xyzzy @@ -4993,7 +5049,6 @@ * (set! xyzzy * Original code by Ken Haase (1985?) */ - static void Scheme_functions (inf) FILE *inf; @@ -5212,11 +5267,6 @@ } -/* Similar to LOOKING_AT but does not use notinname, does not skip */ -#define LOOKING_AT_NOCASE(cp, kw) /* kw is a constant string */ \ - (strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \ - && ((cp) += sizeof(kw)-1)) /* skip spaces */ - /* * HTML support. * Contents of , <h1>, <h2>, <h3> are tags. @@ -6501,7 +6551,7 @@ : *s1 - *s2); } -/* Skip spaces, return new pointer. */ +/* Skip spaces (end of string is not space), return new pointer. */ static char * skip_spaces (cp) char *cp; @@ -6511,7 +6561,7 @@ return cp; } -/* Skip non spaces, return new pointer. */ +/* Skip non spaces, except end of string, return new pointer. */ static char * skip_non_spaces (cp) char *cp; diff --text -u 'xemacs-21.5.18/lib-src/fakemail.c' 'xemacs-21.5.19/lib-src/fakemail.c' Index: ./lib-src/fakemail.c --- ./lib-src/fakemail.c Tue Sep 21 04:19:10 2004 +++ ./lib-src/fakemail.c Wed Jan 26 18:53:28 2005 @@ -34,7 +34,7 @@ #include <stdio.h> #include <stdlib.h> int -main () +main (int argc, char *argv[]) { /* Linux /bin/mail, if it exists, is NOT the Unix v7 mail that fakemail depends on! This causes garbled mail. Better to diff --text -u 'xemacs-21.5.18/lib-src/gnuclient.c' 'xemacs-21.5.19/lib-src/gnuclient.c' Index: ./lib-src/gnuclient.c --- ./lib-src/gnuclient.c Tue Sep 21 04:19:10 2004 +++ ./lib-src/gnuclient.c Tue Dec 7 08:23:41 2004 @@ -74,10 +74,10 @@ } /* main */ #else /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */ -static char cwd[PATH_MAX+2]; /* current working directory when calculated */ +static char cwd[QXE_PATH_MAX+2];/* current working directory when calculated */ static char *cp = NULL; /* ptr into valid bit of cwd above */ -static pid_t emacs_pid; /* Process id for emacs process */ +static pid_t emacs_pid; /* Process id for emacs process */ void initialize_signals (void); @@ -149,7 +149,7 @@ if (cp == NULL) { /* haven't calculated it yet */ #ifdef HAVE_GETCWD - if (getcwd (cwd,PATH_MAX) == NULL) + if (getcwd (cwd,QXE_PATH_MAX) == NULL) #else if (getwd (cwd) == 0) #endif /* HAVE_GETCWD */ @@ -182,7 +182,7 @@ /* filename - filename to expand */ { #ifdef CYGWIN - char cygwinFilename[PATH_MAX+1]; + char cygwinFilename[QXE_PATH_MAX+1]; extern void cygwin_conv_to_posix_path(const char *, char *); #endif @@ -297,8 +297,8 @@ main (int argc, char *argv[]) { int starting_line = 1; /* line to start editing at */ - char command[PATH_MAX+50]; /* emacs command buffer */ - char fullpath[PATH_MAX+1]; /* full pathname to file */ + char command[QXE_PATH_MAX+50];/* emacs command buffer */ + char fullpath[QXE_PATH_MAX+1];/* full pathname to file */ char *eval_form = NULL; /* form to evaluate with `-eval' */ char *eval_function = NULL; /* function to evaluate with `-f' */ char *load_library = NULL; /* library to load */ @@ -317,7 +317,7 @@ char *hostarg = NULL; /* remote hostname */ char *remotearg; char thishost[HOSTNAMSZ]; /* this hostname */ - char remotepath[PATH_MAX+1]; /* remote pathname */ + char remotepath[QXE_PATH_MAX+1]; /* remote pathname */ char *path; int rflg = 0; /* pathname given on cmdline */ char *portarg; diff --text -u 'xemacs-21.5.18/lib-src/i.c' 'xemacs-21.5.19/lib-src/i.c' Index: ./lib-src/i.c --- ./lib-src/i.c Sun Mar 9 11:27:28 2003 +++ ./lib-src/i.c Tue Dec 7 09:20:51 2004 @@ -67,18 +67,30 @@ BYTE buffer [256]; DWORD really_read, unused; - /* The docs for ReadFile claim: + /* I said: + + [[ The docs for ReadFile claim: The ReadFile function returns when one of the following is true: a write operation completes on the write end of the pipe, the number of bytes requested has been read, or an error occurs. But this is just not true. ReadFile never seems to block, and unless we - Sleep(), we will chew up all the CPU time. --ben - */ + Sleep(), we will chew up all the CPU time. --ben ]] + + But in fact + + [a] this does not appear to be the case any more [maybe a temporary + bug in some versions of Win2000?] + [b] it causes data lossage. [#### Why should this be? Seems extremely + fishy. I tried commenting out the calls to close the standard + handles at the bottom of the program, but it made no difference. + Would we need some kind of additional handshaking? If we get + data loss with the sleep, then we are a race condition waiting + to happen. */ while (ReadFile (pi->source, buffer, sizeof (buffer), &really_read, NULL) && WriteFile (pi->drain, buffer, really_read, &unused, NULL)) - Sleep (100); + /* Sleep (100) */ ; return 0; } diff --text -u 'xemacs-21.5.18/lib-src/insert-data-in-exec.c' 'xemacs-21.5.19/lib-src/insert-data-in-exec.c' Index: ./lib-src/insert-data-in-exec.c --- ./lib-src/insert-data-in-exec.c Sat Apr 17 22:29:20 2004 +++ ./lib-src/insert-data-in-exec.c Wed Jan 26 12:40:10 2005 @@ -121,7 +121,7 @@ fprintf(stderr, "dumped_data found at offset 0x%lx, patching.\n", i); sprintf(msg, "Opening %s failed", argv[2]); - dump = fopen(argv[2], "r"); + dump = fopen(argv[2], "rb"); if(!dump) { perror(msg); exit(1); diff --text -u 'xemacs-21.5.18/lib-src/make-docfile.c' 'xemacs-21.5.19/lib-src/make-docfile.c' Index: ./lib-src/make-docfile.c --- ./lib-src/make-docfile.c Tue Sep 21 04:19:10 2004 +++ ./lib-src/make-docfile.c Mon Dec 6 12:50:53 2004 @@ -220,11 +220,11 @@ /* Allow a file containing files to process, for use w/MS Windows (where command-line length limits are more problematic) */ FILE *argfile = fopen (argv[i] + 1, READ_TEXT); - char arg[PATH_MAX]; + char arg[QXE_PATH_MAX]; if (!argfile) fatal ("Unable to open argument file %s", argv[i] + 1); - while (fgets (arg, PATH_MAX, argfile)) + while (fgets (arg, QXE_PATH_MAX, argfile)) { if (arg[strlen (arg) - 1] == '\n') arg[strlen (arg) - 1] = '\0'; /* chop \n */ @@ -640,10 +640,10 @@ register int defvarflag; int minargs, maxargs; int l = strlen (filename); - char f[PATH_MAX]; + char f[QXE_PATH_MAX]; /* XEmacs change: different method for checking filename extension */ - if (l > PATH_MAX - 1) + if (l > QXE_PATH_MAX - 1) { #ifdef ENAMETOOLONG errno = ENAMETOOLONG; diff --text -u 'xemacs-21.5.18/lib-src/make-dump-id.c' 'xemacs-21.5.19/lib-src/make-dump-id.c' Index: ./lib-src/make-dump-id.c --- ./lib-src/make-dump-id.c Tue Sep 21 04:19:10 2004 +++ ./lib-src/make-dump-id.c Fri Nov 5 08:05:47 2004 @@ -54,7 +54,7 @@ } int -main () +main (int argc, char **argv) { FILE *f; diff --text -u 'xemacs-21.5.18/lib-src/make-msgfile.c' 'xemacs-21.5.19/lib-src/make-msgfile.c' Index: ./lib-src/make-msgfile.c --- ./lib-src/make-msgfile.c Sun Jun 10 19:42:17 2001 +++ ./lib-src/make-msgfile.c Fri Nov 5 08:05:48 2004 @@ -1,196 +1,4 @@ -/* - - - PROPOSAL FOR HOW THIS ALL OUGHT TO WORK - this isn't implemented yet, but this is the plan-in-progress - - - In general, it's accepted that the best way to internationalize is for all - messages to be referred to by a symbolic name (or number) and come out of a - table or tables, which are easy to change. - - However, with Emacs, we've got the task of internationalizing a huge body - of existing code, which already contains messages internally. - - For the C code we've got two options: - - - Use a Sun-like gettext() form, which takes an "english" string which - appears literally in the source, and uses that as a hash key to find - a translated string; - - Rip all of the strings out and put them in a table. - - In this case, it's desirable to make as few changes as possible to the C - code, to make it easier to merge the code with the FSF version of emacs - which won't ever have these changes made to it. So we should go with the - former option. - - The way it has been done (between 19.8 and 19.9) was to use gettext(), but - *also* to make massive changes to the source code. The goal now is to use - gettext() at run-time and yet not require a textual change to every line - in the C code which contains a string constant. A possible way to do this - is described below. - - (gettext() can be implemented in terms of catgets() for non-Sun systems, so - that in itself isn't a problem.) - - For the Lisp code, we've got basically the same options: put everything in - a table, or translate things implicitly. - - Another kink that lisp code introduces is that there are thousands of third- - party packages, so changing the source for all of those is simply not an - option. - - Is it a goal that if some third party package displays a message which is - one we know how to translate, then we translate it? I think this is a - worthy goal. It remains to be seen how well it will work in practice. - - So, we should endeavor to minimize the impact on the lisp code. Certain - primitive lisp routines (the stuff in lisp/prim/, and especially in - cmdloop.el and minibuf.el) may need to be changed to know about translation, - but that's an ideologically clean thing to do because those are considered - a part of the emacs substrate. - - However, if we find ourselves wanting to make changes to, say, RMAIL, then - something has gone wrong. (Except to do things like remove assumptions - about the order of words within a sentence, or how pluralization works.) - - There are two parts to the task of displaying translated strings to the - user: the first is to extract the strings which need to be translated from - the sources; and the second is to make some call which will translate those - strings before they are presented to the user. - - The old way was to use the same form to do both, that is, GETTEXT() was both - the tag that we searched for to build a catalog, and was the form which did - the translation. The new plan is to separate these two things more: the - tags that we search for to build the catalog will be stuff that was in there - already, and the translation will get done in some more centralized, lower - level place. - - This program (make-msgfile.c) addresses the first part, extracting the - strings. - - For the emacs C code, we need to recognize the following patterns: - - message ("string" ... ) - error ("string") - report_file_error ("string" ... ) - signal_simple_error ("string" ... ) - signal_simple_error_2 ("string" ... ) - - build_translated_string ("string") - #### add this and use it instead of build_string() in some places. - - yes_or_no_p ("string" ... ) - #### add this instead of funcalling Qyes_or_no_p directly. - - barf_or_query_if_file_exists #### restructure this - check all callers of Fsignal #### restructure these - signal_error (Qerror ... ) #### change all of these to error() - - And we also parse out the `interactive' prompts from DEFUN() forms. - - #### When we've got a string which is a candidate for translation, we - should ignore it if it contains only format directives, that is, if - there are no alphabetic characters in it that are not a part of a `%' - directive. (Careful not to translate either "%s%s" or "%s: ".) - - For the emacs Lisp code, we need to recognize the following patterns: - - (message "string" ... ) - (error "string" ... ) - (format "string" ... ) - (read-from-minibuffer "string" ... ) - (read-shell-command "string" ... ) - (y-or-n-p "string" ... ) - (yes-or-no-p "string" ... ) - (read-file-name "string" ... ) - (temp-minibuffer-message "string") - (query-replace-read-args "string" ... ) - - I expect there will be a lot like the above; basically, any function which - is a commonly used wrapper around an eventual call to `message' or - `read-from-minibuffer' needs to be recognized by this program. - - - (dgettext "domain-name" "string") #### do we still need this? - - things that should probably be restructured: - `princ' in cmdloop.el - `insert' in debug.el - face-interactive - help.el, syntax.el all messed up - - - Menu descriptors: one way to extract the strings in menu labels would be - to teach this program about "^(defvar .*menu\n" forms; that's probably - kind of hard, though, so perhaps a better approach would be to make this - program recognize lines of the form - - "string" ... ;###translate - - where the magic token ";###translate" on a line means that the string - constant on this line should go into the message catalog. This is analogous - to the magic ";###autoload" comments, and to the magic comments used in the - EPSF structuring conventions. - - ----- - So this program manages to build up a catalog of strings to be translated. - To address the second part of the problem, of actually looking up the - translations, there are hooks in a small number of low level places in - emacs. - - Assume the existence of a C function gettext(str) which returns the - translation of `str' if there is one, otherwise returns `str'. - - - message() takes a char* as its argument, and always filters it through - gettext() before displaying it. - - - errors are printed by running the lisp function `display-error' which - doesn't call `message' directly (it princ's to streams), so it must be - carefully coded to translate its arguments. This is only a few lines - of code. - - - Fread_minibuffer_internal() is the lowest level interface to all minibuf - interactions, so it is responsible for translating the value that will go - into Vminibuf_prompt. - - - Fpopup_menu filters the menu titles through gettext(). - - The above take care of 99% of all messages the user ever sees. - - - The lisp function temp-minibuffer-message translates its arg. - - - query-replace-read-args is funny; it does - (setq from (read-from-minibuffer (format "%s: " string) ... )) - (setq to (read-from-minibuffer (format "%s %s with: " string from) ... )) - - What should we do about this? We could hack query-replace-read-args to - translate its args, but might this be a more general problem? I don't - think we ought to translate all calls to format. We could just change - the calling sequence, since this is odd in that the first %s wants to be - translated but the second doesn't. - - - Solving the "translating too much" problem: - The concern has been raised that in this situation: - - "Help" is a string for which we know a translation; - - someone visits a file called Help, and someone does something - contrived like (error buffer-file-name) - then we would display the translation of Help, which would not be correct. - We can solve this by adding a bit to Lisp_String objects which identifies - them as having been read as literal constants from a .el or .elc file (as - opposed to having been constructed at run time as it would in the above - case.) To solve this: - - - Fmessage() takes a lisp string as its first argument. - If that string is a constant, that is, was read from a source file - as a literal, then it calls message() with it, which translates. - Otherwise, it calls message_no_translate(), which does not translate. - - - Ferror() (actually, Fsignal() when condition is Qerror) works similarly. -*/ - - +/* #### Old code! Replaced with make-msgfile.lex. */ /* Scan specified C and Lisp files, extracting the following messages: diff --text -u 'xemacs-21.5.18/lib-src/make-msgfile.lex' 'xemacs-21.5.19/lib-src/make-msgfile.lex' Index: ./lib-src/make-msgfile.lex --- ./lib-src/make-msgfile.lex Fri Apr 13 03:21:03 2001 +++ ./lib-src/make-msgfile.lex Fri Nov 5 08:05:48 2004 @@ -25,6 +25,8 @@ /* Written by Ben Wing, November 1994. Some code based on earlier make-msgfile.c. */ +/* See text.c for a proposal about how this whole system should work. */ + /* Note: there is still much work to be done on this. 1) Definition of Arg below won't handle a generalized argument @@ -60,230 +62,6 @@ */ -/* Long comment from jwz: - - (much of this comment is outdated, and a lot of it is actually - implemented) - - - PROPOSAL FOR HOW THIS ALL OUGHT TO WORK - this isn't implemented yet, but this is the plan-in-progress - - - In general, it's accepted that the best way to internationalize is for all - messages to be referred to by a symbolic name (or number) and come out of a - table or tables, which are easy to change. - - However, with Emacs, we've got the task of internationalizing a huge body - of existing code, which already contains messages internally. - - For the C code we've got two options: - - - Use a Sun-like gettext() form, which takes an "english" string which - appears literally in the source, and uses that as a hash key to find - a translated string; - - Rip all of the strings out and put them in a table. - - In this case, it's desirable to make as few changes as possible to the C - code, to make it easier to merge the code with the FSF version of emacs - which won't ever have these changes made to it. So we should go with the - former option. - - The way it has been done (between 19.8 and 19.9) was to use gettext(), but - *also* to make massive changes to the source code. The goal now is to use - gettext() at run-time and yet not require a textual change to every line - in the C code which contains a string constant. A possible way to do this - is described below. - - (gettext() can be implemented in terms of catgets() for non-Sun systems, so - that in itself isn't a problem.) - - For the Lisp code, we've got basically the same options: put everything in - a table, or translate things implicitly. - - Another kink that lisp code introduces is that there are thousands of third- - party packages, so changing the source for all of those is simply not an - option. - - Is it a goal that if some third party package displays a message which is - one we know how to translate, then we translate it? I think this is a - worthy goal. It remains to be seen how well it will work in practice. - - So, we should endeavor to minimize the impact on the lisp code. Certain - primitive lisp routines (the stuff in lisp/prim/, and especially in - cmdloop.el and minibuf.el) may need to be changed to know about translation, - but that's an ideologically clean thing to do because those are considered - a part of the emacs substrate. - - However, if we find ourselves wanting to make changes to, say, RMAIL, then - something has gone wrong. (Except to do things like remove assumptions - about the order of words within a sentence, or how pluralization works.) - - There are two parts to the task of displaying translated strings to the - user: the first is to extract the strings which need to be translated from - the sources; and the second is to make some call which will translate those - strings before they are presented to the user. - - The old way was to use the same form to do both, that is, GETTEXT() was both - the tag that we searched for to build a catalog, and was the form which did - the translation. The new plan is to separate these two things more: the - tags that we search for to build the catalog will be stuff that was in there - already, and the translation will get done in some more centralized, lower - level place. - - This program (make-msgfile.c) addresses the first part, extracting the - strings. - - For the emacs C code, we need to recognize the following patterns: - - message ("string" ... ) - error ("string") - report_file_error ("string" ... ) - signal_simple_error ("string" ... ) - signal_simple_error_2 ("string" ... ) - - build_translated_string ("string") - #### add this and use it instead of build_string() in some places. - - yes_or_no_p ("string" ... ) - #### add this instead of funcalling Qyes_or_no_p directly. - - barf_or_query_if_file_exists #### restructure this - check all callers of Fsignal #### restructure these - signal_error (Qerror ... ) #### change all of these to error() - - And we also parse out the `interactive' prompts from DEFUN() forms. - - #### When we've got a string which is a candidate for translation, we - should ignore it if it contains only format directives, that is, if - there are no alphabetic characters in it that are not a part of a `%' - directive. (Careful not to translate either "%s%s" or "%s: ".) - - For the emacs Lisp code, we need to recognize the following patterns: - - (message "string" ... ) - (error "string" ... ) - (format "string" ... ) - (read-from-minibuffer "string" ... ) - (read-shell-command "string" ... ) - (y-or-n-p "string" ... ) - (yes-or-no-p "string" ... ) - (read-file-name "string" ... ) - (temp-minibuffer-message "string") - (query-replace-read-args "string" ... ) - - I expect there will be a lot like the above; basically, any function which - is a commonly used wrapper around an eventual call to `message' or - `read-from-minibuffer' needs to be recognized by this program. - - - (dgettext "domain-name" "string") #### do we still need this? - - things that should probably be restructured: - `princ' in cmdloop.el - `insert' in debug.el - face-interactive - help.el, syntax.el all messed up - - BPW: (format) is a tricky case. If I use format to create a string - that I then send to a file, I probably don't want the string translated. - On the other hand, If the string gets used as an argument to (y-or-n-p) - or some such function, I do want it translated, and it needs to be - translated before the %s and such are replaced. The proper solution - here is for (format) and other functions that call gettext but don't - immediately output the string to the user to add the translated (and - formatted) string as a string property of the object, and have - functions that output potentially translated strings look for a - "translated string" property. Of course, this will fail if someone - does something like - - (y-or-n-p (concat (if you-p "Do you " "Does he ") - (format "want to delete %s? " filename)))) - - But you shouldn't be doing things like this anyway. - - BPW: Also, to avoid excessive translating, strings should be marked - as translated once they get translated, and further calls to gettext - don't do any more translating. Otherwise, a call like - - (y-or-n-p (format "Delete %s? " filename)) - - would cause translation on both the pre-formatted and post-formatted - strings, which could lead to weird results in some cases (y-or-n-p - has to translate its argument because someone could pass a string to - it directly). Note that the "translating too much" solution outlined - below could be implemented by just marking all strings that don't - come from a .el or .elc file as already translated. - - Menu descriptors: one way to extract the strings in menu labels would be - to teach this program about "^(defvar .*menu\n" forms; that's probably - kind of hard, though, so perhaps a better approach would be to make this - program recognize lines of the form - - "string" ... ;###translate - - where the magic token ";###translate" on a line means that the string - constant on this line should go into the message catalog. This is analogous - to the magic ";###autoload" comments, and to the magic comments used in the - EPSF structuring conventions. - - ----- - So this program manages to build up a catalog of strings to be translated. - To address the second part of the problem, of actually looking up the - translations, there are hooks in a small number of low level places in - emacs. - - Assume the existence of a C function gettext(str) which returns the - translation of `str' if there is one, otherwise returns `str'. - - - message() takes a char* as its argument, and always filters it through - gettext() before displaying it. - - - errors are printed by running the lisp function `display-error' which - doesn't call `message' directly (it princ's to streams), so it must be - carefully coded to translate its arguments. This is only a few lines - of code. - - - Fread_minibuffer_internal() is the lowest level interface to all minibuf - interactions, so it is responsible for translating the value that will go - into Vminibuf_prompt. - - - Fpopup_menu filters the menu titles through gettext(). - - The above take care of 99% of all messages the user ever sees. - - - The lisp function temp-minibuffer-message translates its arg. - - - query-replace-read-args is funny; it does - (setq from (read-from-minibuffer (format "%s: " string) ... )) - (setq to (read-from-minibuffer (format "%s %s with: " string from) ... )) - - What should we do about this? We could hack query-replace-read-args to - translate its args, but might this be a more general problem? I don't - think we ought to translate all calls to format. We could just change - the calling sequence, since this is odd in that the first %s wants to be - translated but the second doesn't. - - - Solving the "translating too much" problem: - The concern has been raised that in this situation: - - "Help" is a string for which we know a translation; - - someone visits a file called Help, and someone does something - contrived like (error buffer-file-name) - then we would display the translation of Help, which would not be correct. - We can solve this by adding a bit to Lisp_String objects which identifies - them as having been read as literal constants from a .el or .elc file (as - opposed to having been constructed at run time as it would in the above - case.) To solve this: - - - Fmessage() takes a lisp string as its first argument. - If that string is a constant, that is, was read from a source file - as a literal, then it calls message() with it, which translates. - Otherwise, it calls message_no_translate(), which does not translate. - - - Ferror() (actually, Fsignal() when condition is Qerror) works similarly. -*/ - /* Some notes: -- {Arg} below could get confused by commas inside of quotes. diff --text -u 'xemacs-21.5.18/lib-src/make-mswin-unicode.pl' 'xemacs-21.5.19/lib-src/make-mswin-unicode.pl' Index: ./lib-src/make-mswin-unicode.pl --- ./lib-src/make-mswin-unicode.pl Sun Mar 31 17:27:15 2002 +++ ./lib-src/make-mswin-unicode.pl Fri Nov 5 08:05:48 2004 @@ -2,7 +2,7 @@ ### make-mswin-unicode --- generate Unicode-encapsulation code for MS Windows -## Copyright (C) 2001, 2002 Ben Wing. +## Copyright (C) 2001, 2002, 2004 Ben Wing. ## Author: Ben Wing <ben@xemacs.org> ## Maintainer: Ben Wing <ben@xemacs.org> @@ -269,7 +269,8 @@ } print HOUT "#undef $fun\n"; - print HOUT "#define $fun error $reason\n"; + (my $munged_reason = $reason) =~ s/[^A-Za-z0-9]/_/g; + print HOUT "#define $fun error_$munged_reason\n"; print COUT "/* Error if $fun used: $reason */\n\n"; } elsif ($command eq "skip") @@ -333,7 +334,7 @@ } print HOUT "#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED\n"; print HOUT "#undef $fun\n"; - print HOUT "#define $fun error use qxe$fun or ${fun}A/${fun}W\n"; + print HOUT "#define $fun error_use_qxe${fun}_or_${fun}A_and_${fun}W\n"; print HOUT "#endif\n"; if (defined ($reason)) { diff --text -u 'xemacs-21.5.18/lib-src/movemail.c' 'xemacs-21.5.19/lib-src/movemail.c' Index: ./lib-src/movemail.c --- ./lib-src/movemail.c Wed Mar 13 17:51:59 2002 +++ ./lib-src/movemail.c Mon Feb 14 12:40:45 2005 @@ -746,14 +746,14 @@ server = pop_open (0, user, password, POP_NO_GETPASS); if (! server) { - error (pop_error, NULL, NULL); + error ("%s", pop_error, NULL); return (1); } VERBOSE(("stat'ing messages\n")); if (pop_stat (server, &nmsgs, &nbytes)) { - error (pop_error, NULL, NULL); + error ("%s", pop_error, NULL); return (1); } @@ -801,7 +801,7 @@ mbx_delimit_begin (mbf); if (pop_retr (server, i, mbx_write, mbf) != POP_RETRIEVED) { - error (Errmsg, NULL, NULL); + error ("%s", Errmsg, NULL); close (mbfi); return (1); } @@ -849,7 +849,7 @@ VERBOSE(("deleting message %d \n", i)); if (pop_delete (server, i)) { - error (pop_error, NULL, NULL); + error ("%s", pop_error, NULL); pop_close (server); return (1); } @@ -860,7 +860,7 @@ VERBOSE(("closing server \n")); if (pop_quit (server)) { - error (pop_error, NULL, NULL); + error ("%s", pop_error, NULL); return (1); } diff --text -u 'xemacs-21.5.18/lib-src/profile.c' 'xemacs-21.5.19/lib-src/profile.c' Index: ./lib-src/profile.c --- ./lib-src/profile.c Tue Sep 21 04:19:11 2004 +++ ./lib-src/profile.c Fri Nov 5 08:05:48 2004 @@ -1,5 +1,6 @@ /* profile.c --- generate periodic events for profiling of Emacs Lisp code. Copyright (C) 1992, 1994 Free Software Foundation, Inc. + Copyright (C) 2004 Ben Wing. Author: Boaz Ben-Zvi <boaz@lcs.mit.edu> @@ -91,7 +92,7 @@ } int -main () +main (int argc, char **argv) { int c; while ((c = getchar ()) != EOF) diff --text -u 'xemacs-21.5.18/lib-src/sorted-doc.c' 'xemacs-21.5.19/lib-src/sorted-doc.c' Index: ./lib-src/sorted-doc.c --- ./lib-src/sorted-doc.c Tue Sep 21 04:19:11 2004 +++ ./lib-src/sorted-doc.c Fri Nov 5 08:05:48 2004 @@ -99,7 +99,7 @@ }; int -main () +main (int argc, char **argv) { register DOCSTR *dp = NULL; /* allocated DOCSTR */ register LINE *lp = NULL; /* allocated line */ diff --text -u 'xemacs-21.5.18/lisp/ChangeLog' 'xemacs-21.5.19/lisp/ChangeLog' Index: ./lisp/ChangeLog --- ./lisp/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./lisp/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,731 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + +2005-02-16 Aidan Kehoe <kehoea@parhasard.net> + + * buffer.el (pop-to-buffer): + * window-xemacs.el (display-buffer): + Document use of `same-window-buffer-names,' `same-window-regexps' + by pop-to-buffer and display-buffer. + +2005-02-09 Ben Wing <ben@xemacs.org> + + * dumped-lisp.el (preloaded-file-list): + Move paragraphs later so that decode-coding-string is defined. + +2005-02-09 Ben Wing <ben@xemacs.org> + + * paragraphs.el (sentence-end): + Don't have literal chars in the string and don't put the extended + chars in the string unless (featurep 'mule). + +2005-02-09 Aidan Kehoe <kehoea@parhasard.net> + + * mule/european.el: Fix a comment typo pointed out by Jerry James + in psu0olr8z7.fsf@diannao.ittc.ku.edu. + +2005-02-09 Aidan Kehoe <kehoea@parhasard.net> + + * mule/european.el: Create the 8859-16 character set and coding system. + * mule/european.el (latin-iso8859-16): Make the character set available. + +2005-02-09 Aidan Kehoe <kehoea@parhasard.net> + + * unicode.el (load-unicode-tables): + Initialise mapping tables for ISO + 8859-16--cf. s3tk6pieyuk.fsf@magellan.suse.de , DOUBLE LOW-9 + QUOTATION MARK is very much used for German and in Central Europe. + +2005-02-09 Aidan Kehoe <kehoea@parhasard.net> + + * unicode.el: + Add coding system aliases for utf-16-be and utf-16-le, for + improved compatibility with Mule-UCS and the FSF. + +2005-02-07 Ben Wing <ben@xemacs.org> + + * menubar.el (find-menu-item-1): + Forgot to rename this when find-menu-item-1 was extracted. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * autoload.el (batch-update-autoloads): + Use correct parameters when invoking older interface. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * shadow.el (find-emacs-lisp-shadows): + Ignore custom-defines. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * about.el: + * about.el (xemacs-hackers): + * about.el (about-personal-info): + * about.el (about-hacker-contribution): + * about.el (about-hackers): + Add Aidan, alexm. Update my info. Sort list of ancillary + contributors, delete a couple of duplicates. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * dumped-lisp.el (preloaded-file-list): + Document that paragraphs needs easy-mmode. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * packages.el (package-suppress): New. + Add actual command to suppress packages. + +2005-02-03 Jerry James <james@xemacs.org> + + * dumped-lisp.el (preloaded-file-list): Add easy-mmode. + * paragraphs.el (paragraphs): Undo the require as it is now + unnecessary. + +2005-02-03 Jerry James <james@xemacs.org> + + * paragraphs.el: Require easy-mmode, due to its move in core. + * paragraphs.el (sentence-end): Fix a typo. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * regexp-opt.el: + * regexp-opt.el (regexp-opt): + * regexp-opt.el (regexp-opt-not-groupie*-re): New. + * regexp-opt.el (regexp-opt-group): + Update to latest version in package tree. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * paragraphs.el: + * paragraphs.el (paragraphs): New. + * paragraphs.el (use-hard-newlines): Removed. + * paragraphs.el (paragraph-start): + * paragraphs.el (paragraph-separate): + * paragraphs.el (sentence-end-double-space): New. + * paragraphs.el (sentence-end-without-period): New. + * paragraphs.el (sentence-end): + * paragraphs.el (forward-paragraph): + * paragraphs.el (backward-paragraph): + * paragraphs.el (mark-paragraph): + * paragraphs.el (forward-sentence): + * paragraphs.el (mark-end-of-sentence): + * paragraphs.el (transpose-sentences): + Sync to 21.3. Depends on easy-mmode in core. + +2005-02-02 Ben Wing <ben@xemacs.org> + + * easy-mmode.el, regexp-opt.el: + Move these files into core. + Uncomment stuff depending on new custom.el. + + * autoload.el: + * autoload.el (generate-autoload-function): New. + * autoload.el (autoload-feature-suffix): New. + * autoload.el (generate-autoload-section-continuation): New. + * autoload.el (make-autoload): + * autoload.el (generate-file-autoloads): + * autoload.el (generate-autoload-type-section): + * autoload.el (process-one-lisp-autoload): New. + * autoload.el (generate-lisp-file-autoloads-1): + * autoload.el (generate-c-file-autoloads-1): + * autoload.el (generate-custom-defines): New. + * autoload.el (print-autoload): Removed. + * autoload.el (autoload-print-form): New. + * autoload.el (defcustom): + * autoload.el (autoload-read-section-header): New. + * autoload.el (update-file-autoloads): + * autoload.el (update-autoloads-here): Removed. + * autoload.el (batch-update-directory-custom-defines): New. + * autoload.el (update-autoload-files): + * autoload.el (autoload-update-directory-autoloads): Removed. + * autoload.el (batch-update-directory-autoloads): New. + * autoload.el (autoload-featurep-protect-autoloads): + * autoload.el (update-autoloads-from-directory): Removed. + * autoload.el (update-custom-define-files): New. + * autoload.el (autoload-make-feature-name): + * autoload.el (batch-update-autoloads): + * autoload.el (batch-update-directory): Removed. + * autoload.el (batch-update-one-directory): Removed. + * autoload.el (batch-force-update-one-directory): Removed. + Major update. Sync with FSF 21.2. + Create the ability to make custom-defines files. + + * update-elc-2.el (batch-update-elc-2): + * update-elc.el (do-autoload-commands): + Rewrite to use new autoload API. + + * update-elc.el (lisp-files-needing-early-byte-compilation): + Add easy-mmode. + +2005-02-02 Ben Wing <ben@xemacs.org> + + * behavior.el: + * behavior.el (behavior-group-hash-table): New. + * behavior.el (behavior-override-hash-table): New. + * behavior.el (define-behavior): Removed. + * behavior.el (behavior-group-p): New. + * behavior.el (check-behavior-group): New. + * behavior.el (override-behavior): + * behavior.el (define-behavior-group): + * behavior.el (read-behavior): + * behavior.el (compute-behavior-group-children): New. + * behavior.el (behavior-menu-filter-1): New. + * behavior.el (behavior-menu-filter): New. + Major update. Add documentation of how it works. + + * behavior-defs.el: + * behavior-defs.el (tty): + * behavior-defs.el ('scroll-in-place): Removed. + * behavior-defs.el ('mouse-avoidance): Removed. + * behavior-defs.el ('jka-compr): Removed. + * behavior-defs.el ('efs): Removed. + * behavior-defs.el ('resize-minibuffer): Removed. + * behavior-defs.el ('func-menu): Removed. + * behavior-defs.el ('mwheel): Removed. + * behavior-defs.el ('recent-files): Removed. + * behavior-defs.el ('filladapt): Removed. + * behavior-defs.el ('tty)): New. + * behavior-defs.el ('toolbars)): New. + * behavior-defs.el ('menus)): New. + * behavior-defs.el ('mouse)): New. + * behavior-defs.el ('editing)): New. + * behavior-defs.el ('keyboard)): New. + * behavior-defs.el ('files)): New. + * behavior-defs.el ('games)): New. + * behavior-defs.el ('processes)): New. + * behavior-defs.el ('display)): New. + * behavior-defs.el ('programming)): New. + * behavior-defs.el ('international)): New. + * behavior-defs.el ('buffers-and-windows)): New. + * behavior-defs.el ('internet)): New. + * behavior-defs.el ('compose-mail): New. + Only define the basic behavior groups here. + Move the definitions for particular packages to the + appropriate package files. + + * mwheel.el: + * mwheel.el ('mwheel): New. + Add define-behavior for mwheel. + +2005-02-02 Ben Wing <ben@xemacs.org> + + * easymenu.el (easy-menu-add): + * easymenu.el (easy-menu-remove): + * map-ynp.el (map-y-or-n-p): + Use normalize-menu-text not normalize-menu-item-name. + + * menubar-items.el (submenu-generate-accelerator-spec): Removed. + * menubar.el (submenu-generate-accelerator-spec): New. + Move to menubar.el and rewrite for cleanliness. + + * menubar-items.el (coding-system-menu-filter): + Use menu-split-long-menu-and-sort. + + * menubar-items.el (menu-item-strip-accelerator-spec): Removed. + * menubar-items.el (menu-item-generate-accelerator-spec): Removed. + * menubar-items.el (menu-max-items): Removed. + * menubar-items.el (menu-submenu-max-items): Removed. + * menubar-items.el (menu-submenu-name-format): Removed. + * menubar-items.el (menu-split-long-menu): Removed. + * menubar-items.el (menu-sort-menu): Removed. + * menubar.el (menu-item-strip-accelerator-spec): New. + * menubar.el (menu-item-generate-accelerator-spec): New. + * menubar.el (menu-max-items): New. + * menubar.el (menu-submenu-max-items): New. + * menubar.el (menu-submenu-name-format): New. + * menubar.el (menu-split-long-menu): New. + * menubar.el (menu-sort-menu): New. + Move to menubar.el. + + * menubar.el (menu-item-text): New. + * menubar.el (menu-split-long-menu-and-sort): New. + New funs. + + * menubar.el (find-menu-item): + * menubar.el (find-menu-item-1): New. + Split up find-menu-item w/find-menu-item-1, since PARENT is not + an external item. + Rewrite to use compare-menu-text. + + * menubar.el (add-menu-item-1): + Don't normalize items as find-menu-item does not need it. + + * menubar-items.el (default-menubar): + Delete old Behavior menu defn, replaced by behavior-menu-filter. + Planning to [[Delete many menus from Tools menu -- they have been + integrated as part of the behavior system.]] Currently the new + Tools menu (very short, just a call to the behavior-menu-filter) + is commented out, and the old Toold menu defn remains. Once the + new packages are in place (c. 1 or 2 weeks), I'll make the + switchover. + + Use menu-split-long-menu-and-sort. + +2005-02-02 Ben Wing <ben@xemacs.org> + + * cus-dep.el (Custom-make-dependencies-1): + If a directory has no custom dependencies, write a blank + custom-load file rather than deleting the file, so that + time-based rebuild checking will work. + + * cus-edit.el: + * cus-edit.el (custom-load-symbol): + * cus-edit.el (custom-load-symbol-1): New. + * cus-edit.el (custom-already-loaded-custom-defines): New. + * cus-edit.el (custom-define-current-source-file): New. + * cus-edit.el (custom-warn-when-reloading-necessary): New. + * cus-edit.el (custom-load-custom-defines): New. + * cus-edit.el (custom-load-custom-defines-1): New. + Split out code in custom-load-symbol. Support loading of + the new custom-defines file. + + * cus-edit.el (custom-menu-create): + Split long menus. + + * custom.el: + * custom.el (load): + * custom.el (custom-dont-initialize): New. + * custom.el (custom-current-group-alist): New. + * custom.el (custom-declare-variable): + * custom.el (defcustom): + * custom.el (custom-current-group): New. + * custom.el (custom-declare-group): + * custom.el (defgroup): + * custom.el (custom-add-to-group): + * custom.el (custom-group-of-mode): New. + * custom.el (custom-handle-all-keywords): + * custom.el (custom-autoload): New. + * custom.el (custom-variable-p): New. + * custom.el (custom-load-recursion): New. + * custom.el (custom-load-symbol): New. + * custom.el (custom-known-themes): + * custom.el (custom-declare-theme): New. + * custom.el (deftheme): + * custom.el (custom-make-theme-feature): + * custom.el (custom-check-theme): + * custom.el (custom-push-theme): + * custom.el (custom-set-variables): + * custom.el (custom-theme-set-variables): + * custom.el (custom-set-default): New. + * custom.el (custom-quote): New. + * custom.el (customize-mark-to-save): New. + * custom.el (provide-theme): + * custom.el (require-theme): + * custom.el (customize-mark-as-set): New. + * custom.el (custom-remove-theme): New. + * custom.el (custom-do-theme-reset): + * custom.el (custom-theme-load-themes): + * custom.el (custom-load-themes): + * custom.el (custom-theme-value): + * custom.el (custom-theme-variable-value): + * custom.el (custom-theme-reset-internal): + * custom.el (copy-upto-last): Removed. + * custom.el (custom-theme-reset-variables): + * custom.el (custom-reset-variables): + * custom.el: + * custom.el (load): + * custom.el (custom-dont-initialize): New. + * custom.el (custom-current-group-alist): New. + * custom.el (custom-declare-variable): + * custom.el (defcustom): + * custom.el (custom-current-group): New. + * custom.el (custom-declare-group): + * custom.el (defgroup): + * custom.el (custom-add-to-group): + * custom.el (custom-group-of-mode): New. + * custom.el (custom-handle-all-keywords): + * custom.el (custom-autoload): New. + * custom.el (custom-variable-p): New. + * custom.el (custom-load-recursion): New. + * custom.el (custom-load-symbol): New. + * custom.el (custom-known-themes): + * custom.el (custom-declare-theme): New. + * custom.el (deftheme): + * custom.el (custom-make-theme-feature): + * custom.el (custom-check-theme): + * custom.el (custom-push-theme): + * custom.el (custom-set-variables): + * custom.el (custom-theme-set-variables): + * custom.el (custom-set-default): New. + * custom.el (custom-quote): New. + * custom.el (customize-mark-to-save): New. + * custom.el (provide-theme): + * custom.el (require-theme): + * custom.el (customize-mark-as-set): New. + * custom.el (custom-remove-theme): New. + * custom.el (custom-do-theme-reset): + * custom.el (custom-theme-load-themes): + * custom.el (custom-load-themes): + * custom.el (custom-theme-value): + * custom.el (custom-theme-variable-value): + * custom.el (custom-theme-reset-internal): + * custom.el (copy-upto-last): Removed. + * custom.el (custom-theme-reset-variables): + * custom.el (custom-reset-variables): + Sync with FSF 21.3. + +2005-01-31 Ben Wing <ben@xemacs.org> + + * help.el: + * help.el (describe-distribution): Go to appropriate FAQ entry. + * help.el (describe-beta): Go to info file. + * help.el (describe-project): Removed. + +2005-01-27 Ben Wing <ben@xemacs.org> + + * font-menu.el: + * font.el: + * font.el (internal-facep): + * font.el (x-font-build-cache): + * font.el (font-lookup-rgb-components): + * frame.el (set-frame-font): + * gtk-font-menu.el (gtk-reset-device-font-menus): + * minibuf.el (read-color-completion-table): + * minibuf.el (x-library-search-path): Removed. + * minibuf.el (x-read-color-completion-table)): Removed. + * msw-faces.el (mswindows-available-font-sizes): + * msw-font-menu.el (mswindows-reset-device-font-menus): + * obsolete.el: + * x-faces.el: + * x-faces.el (x-available-font-sizes): + * x-faces.el (x-library-search-path): New. + * x-faces.el (x-color-list-internal-cache)): New. + * x-faces.el (x-color-list-internal): New. + * x-font-menu.el (x-reset-device-font-menus): + list-fonts->font-list. Create color-list. Abstract out + x/msw-specific versions and obsolete the x/msw-specific Lisp + functions. + +2005-01-27 Ben Wing <ben@xemacs.org> + + * subr.el: + * subr.el (macro-declaration-function): New. + Some synching with FSF 21.2. + +2005-01-27 Ben Wing <ben@xemacs.org> + + * gtk-marshal.el (find-file): + Propagate hash changes to gtk-marshal.el. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * newcomment.el: + * newcomment.el (comment): + * newcomment.el (comment-fill-column): New. + * newcomment.el (comment-style): + * newcomment.el (comment-padding): + * newcomment.el (comment-multi-line): + * newcomment.el (comment-normalize-vars): + * newcomment.el (comment-indent): + * newcomment.el (uncomment-region): + * newcomment.el (comment-make-extra-lines): + * newcomment.el (comment-with-narrowing): + * newcomment.el (comment-region-internal): + * newcomment.el (comment-region): + * newcomment.el (comment-box): + * newcomment.el (comment-or-uncomment-region): New. + * newcomment.el (comment-dwim): + * newcomment.el (comment-auto-fill-only-comments): + * newcomment.el (comment-valid-prefix): New. + * newcomment.el (comment-indent-new-line): + Sync to FSF 21.3. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * fill.el: + * fill.el (canonically-space-region): + * fill.el (fill-region-as-paragraph): + * fill.el (justify-current-line): + * fill.el (fill-individual-paragraphs): + Sync for real to FSF 19.34. + + * page.el: + * page.el (narrow-to-page): + * register.el: + * register.el (set-register): + * register.el (point-to-register): + * register.el (register-swap-out): + * register.el (number-to-register): + * register.el (view-register): + * register.el (list-registers): New. + * register.el (describe-register-1): New. + * register.el (insert-register): + Sync to FSF 21.3. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * frame.el (display-mouse-p): + Fix warning. + + * cl.el (cl-random-time): + Conditionalize on coerce-number as Jerry says it's OK. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * code-init.el (set-eol-detection): + * code-init.el (coding-system-default-variable-list): + * code-init.el (get-coding-system-variable): + * code-init.el (set-coding-system-variable): + Undo Stephen's change of 2004-05-11. + Implement no-conversion-coding-system-mapping as a coding + system variable. + +2005-01-25 Ben Wing <ben@xemacs.org> + + * startup.el: + * startup.el (splash-frame-timeout): Removed. + * startup.el (command-line-1): + * startup.el (startup-presentation-hack-keymap): Removed. + * startup.el (startup-presentation-hack-help): + * startup.el (startup-presentation-hack): Removed. + * startup.el (splash-frame-present): Removed. + * startup.el (splash-screen-present): New. + * startup.el (splash-frame-present-hack): Removed. + * startup.el (startup-presentation-activate): New. + * startup.el (splash-screen-present-hack): New. + * startup.el (startup-center-spaces): + * startup.el (splash-frame-body): Removed. + * startup.el (splash-screen-window-body): New. + * startup.el (splash-screen-tty-body): New. + * startup.el (splash-frame-static-body): Removed. + * startup.el (circulate-splash-frame-elements): Removed. + * startup.el (display-splash-frame): Removed. + * startup.el (splash-screen-static-body): New. + * startup.el ('splash-frame-static-body): New. + * startup.el (display-splash-screen): New. + * startup.el (xemacs-splash-buffer): New. + Rename "splash-frame" -> "splash-screen" (its change + long ago from screen to frame happened during the general + screen->frame sub and was a mistake). Compress all info + onto one screen rather than cycling through 3 of them. + Update copyright years and some other random stuff. + + * menubar-items.el: + * menubar-items.el (default-menubar): + * menubar-items.el (xemacs-splash-buffer): Removed. + frame->screen and rewrite to fix bugginess. + Add menu items for beta and distribution info. + +2005-01-25 Ben Wing <ben@xemacs.org> + + * mouse.el: + * mouse.el (mouse-track-activate-strokes): + * mouse.el (mouse-track-conservative-activate-strokes): New. + * mouse.el (Mouse-track-gensym): + * mouse.el (mouse-track-do-activate): Removed. + * mouse.el (default-mouse-track-check-for-activation): New. + * mouse.el (default-mouse-track-click-hook): New. + * mouse.el (mouse-track-down-hook): + Redo mouse-track activation to separate out a "conservative" + activation that is only triggered by button2 or button1 double-click + and a regular activation also triggered by button1. + +2005-01-25 Ben Wing <ben@xemacs.org> + + * font-lock.el (c-font-lock-keywords-2): Removed. + * font-lock.el (xemacs-c-font-lock-keywords-2): New. + * font-lock.el (c-font-lock-keywords-3): Removed. + * font-lock.el (xemacs-c-font-lock-keywords-3): New. + Proper defvars. + +2005-01-17 Adrian Aichner <adrian@xemacs.org> + + * simple.el (shifted-motion-keys-select-region): Fix statement + about unshifted-motion-keys-deselect-region. + +2005-01-08 Mike Sperber <mike@xemacs.org> + + * packages.el (packages-find-installation-package-directories): Add. + + * find-paths.el (paths-for-each-emacs-directory): Abstract FUNC + parameter out of `paths-find-emacs-directory'. + (paths-find-emacs-directories): Add. + (paths-find-emacs-directory): Redefine in terms of + `paths-for-each-emacs-directory'. + (paths-for-each-site-directory): Add. + (paths-find-site-directory): Redefine in terms of + `paths-for-each-site-directory'. + (paths-find-site-directories): Add. + (paths-for-each-version-directory): Add. + (paths-find-version-directory): Redefine in terms of + `paths-for-each-version-directory'. + (paths-find-version-directories): Add. + +2005-01-09 Adrian Aichner <adrian@xemacs.org> + + * dumped-lisp.el (preloaded-file-list): Fix typo in + "mule-win32-init" path in preloaded-file-list, as suggected by + Alejandro L~pez-Valencia. + +2005-01-09 Adrian Aichner <adrian@xemacs.org> + + * process.el (start-process-shell-command): Correct docstring. + +2005-01-03 Mike Sperber <mike@xemacs.org> + + * dumped-lisp.el (preloaded-file-list): Prefix Mule files with + mule/, unbreaking the build. + +2004-12-18 Mike Sperber <mike@xemacs.org> + + * package-admin.el: + * startup.el: Reflect the changes made in packages.el. + + * packages.el: + * loadup.el: + * make-docfile.el: + * package-admin.el: + * startup.el: + * update-elc.el (early-package-hierarchies) + (late-package-hierarchies) + (last-package-hierarchies): Renamed these from `early-packages', + `late-packages' and `last-packages'. + + * packages.el: Rewrote package-finding logic to separate the + concepts of "package directories" and "package hierarchies". + Added explanation of these concepts. + + * setup-paths.el: + * find-paths.el: Added parameter descriptions to some of the + docstrings. + + * packages.el, setup-paths.el: Make terminology more explicit + about "package hierarchies" + + * startup.el (emacs-roots, emacs-data-roots) + (user-init-directory-base, user-init-directory) + (user-init-file-base, user-init-file-base-list) + (user-home-init-file-base-list) + (load-home-init-file, load-user-init-file-p) + (startup-find-load-path, startup-setup-paths) + (startup-find-load-path-for-packages): Moved these back from + setup-paths.el where they belong---setup-paths.el now again, as + documented, contains no code that sets global variables. (They + were moved from startup.el to setup-paths.el on 2003-02-28.) + Clarify that in the comment at the top. + + * setup-paths.el (paths-find-emacs-roots): Restored + `invocation-directory' 'invocation-name' parameters removed on + 2003-02-28; they're useful for debugging. + +2004-12-15 Ville Skyttä <scop@xemacs.org> + + * bytecomp-runtime.el (make-obsolete): Add 3rd argument (no-op for + now) for GNU Emacs compatibility. + (make-obsolete-variable): Ditto. + +2004-11-16 Stephen J. Turnbull <stephen@xemacs.org> + + * gnuserv.el (gnuserv-edit-files): Improve docstring. + +2004-12-13 Stephen J. Turnbull <stephen@xemacs.org> + + * simple.el (next-line): + (previous-line): + Document effect of `signal-error-on-buffer-boundary'. + +2004-12-11 Ben Wing <ben@xemacs.org> + + * files.el (find-coding-system-magic-cookie-in-file): + File positions are 0 based not 1 based. + +2004-12-05 Ben Wing <ben@xemacs.org> + + * info.el (Info-additional-search-directory-list): + Correct doc string giving example package path. + + * menubar-items.el (default-menubar): + Move Prefix Rectangle command up one level. + +2004-11-14 Adrian Aichner <adrian@xemacs.org> + + * mule/devan-util.el (devanagari-composite-glyph-unit): doctring + typo fix. + +2004-09-22 Stephen J. Turnbull <stephen@xemacs.org> + + * menubar-items.el (save-options-file): + (save-options-init-file): + (options-save-faces): + Remove obsolete and unused variables. + +2004-09-22 Stephen J. Turnbull <stephen@xemacs.org> + + * menubar-items.el (init-menubar-at-startup): + XEmacs loads "init files", not ".emacs". + +2004-11-07 Malcolm Purvis <malcolmp@xemacs.org> + + * about.el (about-personal-info): Added my personal details. + Added missing entry for Norbert Koch. + * about.el (about-hacker-contribution): Added missing entry for + Norbert Koch. + +2004-11-04 Ben Wing <ben@xemacs.org> + + * mule/mule-ccl.el (define-ccl-program): + * mule/mule-ccl.el (TRANSLATE): New. + * mule/mule-ccl.el (MAP): New. + * mule/mule-ccl.el (MAP-IDs): New. + * mule/mule-ccl.el (MAP-SET): New. + * mule/mule-ccl.el (MAP-ID): New. + * mule/mule-ccl.el (INT-OR-CHAR): New. + Update docs. + +2004-10-26 Ben Wing <ben@xemacs.org> + + * cl-extra.el (coerce): + * cl.el (cl-random-time): + * wid-edit.el (widget-url-link-action): + * widgets-gtk.el (gtk-widget-instantiate-notebook-internal): + * dialog-gtk.el: + * frame.el (frame-notice-user-settings): + * frame.el (display-mouse-p): + * frame.el (display-visual-class): + * package-ui.el (pui-display-maintainer): + Fix compile warnings. + +2004-10-14 Ben Wing <ben@xemacs.org> + + * dumped-lisp.el: + Put in comment about extended chars in dumped files. + + * font-lock.el: + * font-lock.el (lisp-font-lock-keywords-2): + * font-lock.el (c-font-lock-keywords-2): New. + * font-lock.el (c-font-lock-keywords-3): New. + Add versions of C keywords for editing XEmacs source code, + recognizing many basic XEmacs types. + + * loadup.el (really-early-error-handler): + * unicode.el: + * unicode.el (load-unicode-tables-at-dump-time): New. + * unicode.el (init-unicode-at-startup): Removed. + * mule/mule-cmds.el (init-mule-at-startup): + Define and implement load-unicode-tables-at-dump-time. Set this + to true on Windows systems. This will increase the size of the + dumped XEmacs but allow XEmacs to be run when in a non-ASCII + directory or with non-ASCII command-line arguments. + + * update-elc.el: + * update-elc.el (unbytecompiled-lisp-files): + * update-elc.el (additional-dump-dependencies): New. + * update-elc.el ((preloaded-file-list site-load-packages files-to-process)): + Add loadup.el, loadup-el.el and update-elc.el as additional + dependencies, forcing a redump if they are changed. + + * win32-native.el: + Add stuff snipped from Microsoft docs concerning how quoting + conventions are supposed to work. + +2004-10-28 Stephen J. Turnbull <stephen@xemacs.org> + + * code-process.el (call-process-region): Fix region deletion bug. + Report by Katsumi Yamaoka <b9yvfcyuscf.fsf@jpl.org>. + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/lisp/about.el' 'xemacs-21.5.19/lisp/about.el' Index: ./lisp/about.el --- ./lisp/about.el Thu Sep 23 14:35:07 2004 +++ ./lisp/about.el Fri Feb 4 11:56:43 2005 @@ -1,7 +1,7 @@ ;;; about.el --- the About The Authors page (shameless self promotion). ;; Copyright (c) 1997 Free Software Foundation, Inc. -;; Copyright (C) 2001 Ben Wing. +;; Copyright (C) 2001, 2005 Ben Wing. ;; Keywords: extensions ;; Version: 2.5 @@ -95,9 +95,11 @@ ;; to sort the stuff below, use M-x sort-regexp-fields RET ;; ^.*$ RET (\([a-z]*\) RET (adrian "Adrian Aichner" "adrian@xemacs.org") + (aidan "Aidan Kehoe" "aidan@xemacs.org") (aj "Andreas Jaeger" "aj@xemacs.org") (ajc "Andrew Cosgriff" "ajc@xemacs.org") (alastair "Alastair Houghton" "alastair@xemacs.org") + (alexm "Alexey Mahotkin" "alexm@xemacs.org") (baw "Barry Warsaw" "bwarsaw@xemacs.org") (ben "Ben Wing" "ben@xemacs.org") (bw "Bob Weiner" "weiner@xemacs.org") @@ -873,15 +875,15 @@ Since September 1992, I've worked on XEmacs as a contractor for various companies and more recently as an unpaid volunteer. -Alas, life has not been good to me recently. This former San -Francisco \"Mission Critter\" developed insidious hand and neck -problems after a brief stint working on a Java-based VRML toolkit for -the now defunct Dimension X, and I was forced to quit working. I was -exiled first to \"Stroller Valley\" and later all the way to Tucson, -Arizona, and for two years was almost completely disabled due to pain. -More recently I have fought my way back with loads and loads of -narcotic painkillers, and currently I'm an art student at the -University of Arizona.\n\n") +Alas, life has not been good to me recently. This former San Francisco +\"Mission Critter\" developed insidious hand and neck problems after a +brief stint working on a Java-based VRML toolkit for the now defunct +Dimension X, and I was forced to quit working. I was exiled first to +\"Stroller Valley\" and later all the way to Tucson, Arizona, and for two +years was almost completely disabled due to pain. More recently I have +fought my way back with loads and loads of narcotic painkillers, and after +a stint as an art student at the University of Arizona I'm currently a +Ph.D. student in linguistics at the University of Texas, Austin.\n\n") (widget-insert "Architecting XEmacs: ") (about-url-link 'ben-xemacs nil "Find the miracles in store for XEmacs") (widget-insert "\nBen's home page: ") @@ -1324,7 +1326,14 @@ (purvis (widget-insert "\ -Sorry, no personal information available about me yet.\n")) +Graduate of the University of New South Wales and resident of Sydney, +Australia. My day job involves developing and maintaining software +development tools for a telco manufacturer. I've yet to get XEmacs hacking +added to my job description. + +When not hacking, I relax by chasing after my young son, reading SciFi, +listening to Hip Hop and serving on various boards and committees of the +Anglican Church in Sydney.\n")) (rickc (widget-insert "\ The hacker formerly known as Rick Busdiecker is a developer and @@ -1428,6 +1437,10 @@ Association. See ") (about-url-link 'vin nil "Visit the UPA homepage") (widget-insert ".\n")) + (viteno + (widget-insert + "\ +Sorry, no personal information available about me yet.\n")) (vladimir (widget-insert "\ Former technical lead for XEmacs at Sun. He is now writing a book on @@ -1522,7 +1535,7 @@ Author of an earlier version of the MS Windows setup program for XEmacs.\n")) (chr (widget-insert "\ -Maintainer of the XEmacs FAQ and proud author of `zap-up-to-char'.\n")) +Former maintainer of the XEmacs FAQ and proud author of `zap-up-to-char'.\n")) (craig (widget-insert "\ @@ -1845,6 +1858,10 @@ using emacs for a long, long time.) Vin also contributed the detached minibuffer code as well as a few minor enhancements to the menubar options.\n")) + (viteno + (widget-insert + "\ +Norbert is XEmacs' package release manager.\n")) (vladimir (widget-insert "\ Former technical lead for XEmacs at Sun.\n")) @@ -1952,243 +1969,241 @@ great deal of effort providing feedback, testing beta versions of XEmacs, providing patches to the source code, or doing all of the above. We couldn't have done it without them.\n\n") - (print-short "Nagi M. Aboulenein" "aboulene@ponder.csci.unt.edu") - (print-short "Per Abrahamsen" "abraham@dina.kvl.dk") - (print-short "Gary Adams" "gra@zeppo.East.Sun.COM") - (print-short "Gennady Agranov" "agranov@csa.CS.Technion.Ac.IL") - (print-short "Mark Allender" "allender@vnet.IBM.COM") - (print-short "Stephen R. Anderson" "sra@bloch.ling.yale.edu") - (print-short "Butch Anton" "butch@zaphod.uchicago.edu") - (print-short "Fred Appelman" "Fred.Appelman@cv.ruu.nl") - (print-short "Erik \"The Pope\" Arneson" "lazarus@mind.net") - (print-short "Tor Arntsen" "tor@spacetec.no") - (print-short "Marc Aurel" "4-tea-2@bong.saar.de") - (print-short "Larry Auton" "lda@control.att.com") - (print-short "Larry Ayers" "layers@marktwain.net") - (print-short "Oswald P. Backus IV" "backus@altagroup.com") - (print-short "Mike Battaglia" "mbattagl@dsccc.com") - (print-short "Neal Becker" "neal@ctd.comsat.com") - (print-short "Paul Bibilo" "peb@delcam.com") - (print-short "Leonard Blanks" "ltb@haruspex.demon.co.uk") - (print-short "Jan Borchers" "job@tk.uni-linz.ac.at") - (print-short "Mark Borges" "mdb@cdc.noaa.gov") - (print-short "David P. Boswell" "daveb@tau.space.thiokol.com") - (print-short "Tim Bradshaw" "tfb@edinburgh.ac.uk") - (print-short "Rick Braumoeller" "rickb@mti.sgi.com") - (print-short "Matthew J. Brown" "mjb@doc.ic.ac.uk") + (print-short "Achim Oppelt" "aoppelt@theorie3.physik.uni-erlangen.de") + (print-short "Adam Hammer" "hammer@cs.purdue.edu") + (print-short "Aki Vehtari" "Aki.Vehtari@hut.fi") (print-short "Alastair Burt" "burt@dfki.uni-kl.de") - (print-short "David Bush" "david.bush@adn.alcatel.com") - (print-short "Richard Caley" "rjc@cstr.edinburgh.ac.uk") - (print-short "Stephen Carney" "carney@gvc.dec.com") - (print-short "Lorenzo M. Catucci" "lorenzo@argon.roma2.infn.it") - (print-short "Philippe Charton" "charton@lmd.ens.fr") - (print-short "Peter Cheng" "peter.cheng@sun.com") - (print-short "Jin S. Choi" "jin@atype.com") - (print-short "Tomasz J. Cholewo" "tjchol01@mecca.spd.louisville.edu") - (print-short "Serenella Ciongoli" "czs00@ladybug.oes.amdahl.com") - (print-short "Glynn Clements" "glynn@sensei.co.uk") - (print-short "Richard Cognot" "cognot@ensg.u-nancy.fr") + (print-short "Alexandre Oliva" "oliva@dcc.unicamp.br") + (print-short "Amir Katz" "amir@ndsoft.com") + (print-short "Anders Stenman" "stenman@isy.liu.se") + (print-short "Andreas Kaempf" "andreas@sccon.com") + (print-short "Andrew Innes" "andrewi@harlequin.co.uk") (print-short "Andy Cohen" "cohen@andy.bu.edu") - (print-short "Richard Coleman" "coleman@math.gatech.edu") - (print-short "Mauro Condarelli" "MC5686@mclink.it") - (print-short "Nick J. Crabtree" "nickc@scopic.com") - (print-short "Christopher Davis" "ckd@kei.com") - (print-short "Soren Dayton" "csdayton@cs.uchicago.edu") - (print-short "Chris Dean" "ctdean@cogit.com") - (print-short "Michael Diers" "mdiers@elego.de") - (print-short "William G. Dubuque" "wgd@martigny.ai.mit.edu") - (print-short "Steve Dunham" "dunham@dunham.tcimet.net") - (print-short "Samuel J. Eaton" "samuele@cogs.susx.ac.uk") + (print-short "Andy Norman" "ange@hplb.hpl.hp.com") + (print-short "Art Rijos" "art.rijos@SNET.com") + (print-short "Arup Mukherjee" "arup+@cs.cmu.edu") + (print-short "August Hill" "awhill@inlink.com") + (print-short "Axel Seibert" "seiberta@informatik.tu-muenchen.de") + (print-short "Barry Friedman" "friedman@nortel.ca") + (print-short "Ben Gross" "bgross@uiuc.edu") + (print-short "Benedikt Heinen" "beh@icemark.thenet.ch") + (print-short "Benjamin Fried" "bf@morgan.com") + (print-short "Blair Zajac" "blair@olympia.gps.caltech.edu") + (print-short "Brad Miller" "bmiller@cs.umn.edu") + (print-short "Butch Anton" "butch@zaphod.uchicago.edu") (print-short "Carl Edman" "cedman@Princeton.EDU") + (print-short "Carsten Leonhardt" "leo@arioch.oche.de") + (print-short "Casey Nielson" "knielson@joule.elee.calpoly.edu") + (print-short "ChangGil Han" "cghan@phys401.phys.pusan.ac.kr") + (print-short "Charles Hines" "chuck_hines@VNET.IBM.COM") + (print-short "Chris Dean" "ctdean@cogit.com") + (print-short "Chris Holt" "xris@migraine.stanford.edu") + (print-short "Christian F. Goetze" "cg@bigbook.com") + (print-short "Christian Limpach" "Christian.Limpach@nice.ch") + (print-short "Christoph Wedler" "wedler@fmi.uni-passau.de") + (print-short "Christopher Davis" "ckd@kei.com") + (print-short "Colas Nahaboo" "Colas.Nahaboo@sophia.inria.fr") + (print-short "Colin Rafferty" "colin@xemacs.org") + (print-short "Cotton Seed" "cottons@cybercom.net") + (print-short "Damon Lipparelli" "lipp@aa.net") + (print-short "Daniel Rich" "drich@cisco.com") + (print-short "Daniel Schepler" "daniel@shep13.wustl.edu") + (print-short "Daniel Zivkovic" "daniel@canada.sun.com") + (print-short "Darrel Schneider" "darrel@slc.com") (print-short "Dave Edmondson" "davided@sco.com") - (print-short "Jonathan Edwards" "edwards@intranet.com") - (print-short "Eric Eide" "eeide@asylum.cs.utah.edu") - (print-short "EKR" "ekr@terisa.com") + (print-short "Dave Gillespie" "daveg@synaptics.com") + (print-short "Dave Mason" "dmason@plg.uwaterloo.ca") + (print-short "David Bush" "david.bush@adn.alcatel.com") + (print-short "David C Worenklein" "dcw@gcm.com") (print-short "David Fletcher" "frodo@tsunami.com") - (print-short "Paul Flinders" "ptf@delcam.co.uk") - (print-short "Jered J Floyd" "jered@mit.edu") + (print-short "David Hughes" "djh@harston.cv.com") + (print-short "David M. Meyer" "meyer@ns.uoregon.edu") + (print-short "David Ofelt" "ofelt@getalife.Stanford.EDU") + (print-short "David P. Boswell" "daveb@tau.space.thiokol.com") + (print-short "David Walte" "djw18@cornell.edu") + (print-short "Derek Harding" "dharding@lssec.bt.co.uk") + (print-short "Derrell Lipman" "derrell@vis-av.com") + (print-short "Dinesh Somasekhar" "somasekh@ecn.purdue.edu") + (print-short "Dipankar Gupta" "dg@hplb.hpl.hp.com") + (print-short "Dirk Grunwald" "grunwald@foobar.cs.Colorado.EDU") + (print-short "Doug Keller" "dkeller@vnet.ibm.com") + (print-short "E. Rehmi Post" "rehmi@asylum.sf.ca.us") + (print-short "EKR" "ekr@terisa.com") + (print-short "Eric Eide" "eeide@asylum.cs.utah.edu") + (print-short "Erik \"The Pope\" Arneson" "lazarus@mind.net") + (print-short "Francois Staes" "frans@kiwi.uia.ac.be") + (print-short "Fred Appelman" "Fred.Appelman@cv.ruu.nl") + (print-short "Frederic Poncin" "fp@info.ucl.ac.be") + (print-short "Gary Adams" "gra@zeppo.East.Sun.COM") (print-short "Gary D. Foster" "Gary.Foster@Corp.Sun.COM") - (print-short "Jerry Frain" "jerry@sneffels.tivoli.com") + (print-short "Gary Thomas" "g.thomas@opengroup.org") + (print-short "Gennady Agranov" "agranov@csa.CS.Technion.Ac.IL") + (print-short "Georg Nikodym" "Georg.Nikodym@canada.sun.com") + (print-short "Glynn Clements" "glynn@sensei.co.uk") + (print-short "Greg Klanderman" "greg.klanderman@alum.mit.edu") + (print-short "Greg Onufer" "Greg.Onufer@eng.sun.com") + (print-short "Gregor Kennedy" "gregork@dadd.ti.com") + (print-short "Gregory Neil Shapiro" "gshapiro@sendmail.org") + (print-short "Hajime Saitou" "hajime@jsk.t.u-tokyo.ac.jp") + (print-short "Hamish Macdonald" "hamish@bnr.ca") + (print-short "Hayden Schultz" "haydens@ll.mit.edu") + (print-short "Heiko Muenkel" "muenkel@tnt.uni-hannover.de") (print-short "Holger Franz" "hfranz@physik.rwth-aachen.de") - (print-short "Benjamin Fried" "bf@morgan.com") - (print-short "Barry Friedman" "friedman@nortel.ca") - (print-short "Noah Friedman" "friedman@splode.com") - (print-short "Kazuyoshi Furutaka" "furutaka@Flux.tokai.jaeri.go.jp") - (print-short "Lew Gaiter III" "lew@StarFire.com") + (print-short "Holger Schauer" "schauer@coling.uni-freiburg.de") + (print-short "Hunter Kelly" "retnuh@corona") + (print-short "Ian MacKinnon" "imackinnon@telia.co.uk") (print-short "Itay Gat" "itay@cs.huji.ac.il") - (print-short "Tim Geisler" "Tim.Geisler@informatik.uni-muenchen.de") - (print-short "Dave Gillespie" "daveg@synaptics.com") - (print-short "Christian F. Goetze" "cg@bigbook.com") - (print-short "Yusuf Goolamabbas" "yusufg@iss.nus.sg") - (print-short "Wolfgang Grieskamp" "wg@cs.tu-berlin.de") - (print-short "John Griffith" "griffith@sfs.nphil.uni-tuebingen.de") + (print-short "J. Kean Johnston" "jkj@paradigm-sa.com") + (print-short "Jack Repenning" "jackr@sgi.com") (print-short "James Grinter" "jrg@demon.net") - (print-short "Ben Gross" "bgross@uiuc.edu") - (print-short "Dirk Grunwald" "grunwald@foobar.cs.Colorado.EDU") - (print-short "Michael Guenther" "michaelg@igor.stuttgart.netsurf.de") - (print-short "Dipankar Gupta" "dg@hplb.hpl.hp.com") - (print-short "Markus Gutschke" "gutschk@GOEDEL.UNI-MUENSTER.DE") - (print-short "Kai Haberzettl" "khaberz@synnet.de") - (print-short "Adam Hammer" "hammer@cs.purdue.edu") - (print-short "Magnus Hammerin" "magnush@epact.se") - (print-short "ChangGil Han" "cghan@phys401.phys.pusan.ac.kr") - (print-short "Derek Harding" "dharding@lssec.bt.co.uk") - (print-short "Michael Harnois" "mharnois@sbt.net") + (print-short "James LewisMoss" "moss@cs.sc.edu") + (print-short "James Thompson" "thompson@wg2.waii.com") + (print-short "Jan Borchers" "job@tk.uni-linz.ac.at") + (print-short "Jan Sandquist" "etxquist@iqa.ericsson.se") + (print-short "Jason McLaren" "mclaren@math.mcgill.ca") + (print-short "Jason Stewart" "jasons@cs.unm.edu") + (print-short "Jason Yanowitz" "yanowitz@eternity.cs.umass.edu") + (print-short "Jaye Mathisen" "mrcpu@cdsnet.net") + (print-short "Jeffrey Sparkes" "jsparkes@bnr.ca") + (print-short "Jens Krinke" "krinke@ips.cs.tu-bs.de") + (print-short "Jered J Floyd" "jered@mit.edu") + (print-short "Jerry Frain" "jerry@sneffels.tivoli.com") + (print-short "Jin S. Choi" "jin@atype.com") + (print-short "Joe Nuspl" "nuspl@sequent.com") + (print-short "Joel Peterson" "tarzan@aosi.com") + (print-short "John Griffith" "griffith@sfs.nphil.uni-tuebingen.de") (print-short "John Haxby" "J.Haxby@isode.com") + (print-short "John Mignault" "jbm@panix.com") + (print-short "John Morey" "jmorey@crl.com") + (print-short "John Shen" "zfs60@cas.org") + (print-short "John Turner" "turner@xdiv.lanl.gov") + (print-short "John W. Jones" "jj@asu.edu") + (print-short "Jonathan Edwards" "edwards@intranet.com") + (print-short "Juan E. Villacis" "jvillaci@cs.indiana.edu") + (print-short "Justin Sheehy" "justin@linus.mitre.org") + (print-short "Kai Haberzettl" "khaberz@synnet.de") + (print-short "Karel Zuiderveld" "Karel.Zuiderveld@cv.ruu.nl") (print-short "Karl M. Hegbloom" "karlheg@inetarena.com") - (print-short "Benedikt Heinen" "beh@icemark.thenet.ch") - (print-short "Stephan Herrmann" "sh@first.gmd.de") - (print-short "August Hill" "awhill@inlink.com") - (print-short "Mike Hill" "mikehill@hgeng.com") - (print-short "Charles Hines" "chuck_hines@VNET.IBM.COM") - (print-short "Shane Holder" "holder@rsn.hp.com") - (print-short "Chris Holt" "xris@migraine.stanford.edu") - (print-short "Tetsuya HOYANO" "hoyano@ari.bekkoame.or.jp") - (print-short "David Hughes" "djh@harston.cv.com") - (print-short "Tudor Hulubei" "tudor@cs.unh.edu") - (print-short "Tatsuya Ichikawa" "ichikawa@hv.epson.co.jp") - (print-short "Andrew Innes" "andrewi@harlequin.co.uk") + (print-short "Katsumi Yamaoka" "yamaoka@ga.sony.co.jp") + (print-short "Kazuyoshi Furutaka" "furutaka@Flux.tokai.jaeri.go.jp") + (print-short "Kenji Sato" "ken@ny.kdd.com") + (print-short "Ketil Z Malde" "ketil@ii.uib.no") + (print-short "Kevin Oberman" "oberman@es.net") + (print-short "Kim Nyberg" "kny@tekla.fi") + (print-short "La Monte Yarroll" "piggy@hilbert.maths.utas.edu.au") + (print-short "Larry Auton" "lda@control.att.com") + (print-short "Larry Ayers" "layers@marktwain.net") + (print-short "Leonard Blanks" "ltb@haruspex.demon.co.uk") + (print-short "Lew Gaiter III" "lew@StarFire.com") + (print-short "Lorenzo M. Catucci" "lorenzo@argon.roma2.infn.it") + (print-short "Lynn D. Newton" "lynn@ives.phx.mcd.mot.com") + (print-short "Magnus Hammerin" "magnush@epact.se") + (print-short "Manoj Srivastava" "srivasta@pilgrim.umass.edu") + (print-short "Marc Aurel" "4-tea-2@bong.saar.de") + (print-short "Mark Allender" "allender@vnet.IBM.COM") + (print-short "Mark Borges" "mdb@cdc.noaa.gov") (print-short "Markku Jarvinen" "Markku.Jarvinen@simpukka.funet.fi") - (print-short "Robin Jeffries" "robin.jeffries@sun.com") - (print-short "Philip Johnson" "johnson@uhics.ics.Hawaii.Edu") - (print-short "J. Kean Johnston" "jkj@paradigm-sa.com") - (print-short "John W. Jones" "jj@asu.edu") - (print-short "Andreas Kaempf" "andreas@sccon.com") - (print-short "Yoshiaki Kasahara" "kasahara@nc.kyushu-u.ac.jp") - (print-short "Amir Katz" "amir@ndsoft.com") - (print-short "Doug Keller" "dkeller@vnet.ibm.com") - (print-short "Hunter Kelly" "retnuh@corona") - (print-short "Gregor Kennedy" "gregork@dadd.ti.com") - (print-short "Michael Kifer" "kifer@cs.sunysb.edu") - (print-short "Yasuhiko Kiuchi" "kiuchi@dsp.ksp.fujixerox.co.jp") - (print-short "Greg Klanderman" "greg.klanderman@alum.mit.edu") - (print-short "Valdis Kletnieks" "Valdis.Kletnieks@vt.edu") - (print-short "Norbert Koch" "n.koch@delta-ii.de") - (print-short "Rob Kooper" "kooper@cc.gatech.edu") - (print-short "Peter Skov Knudsen" "knu@dde.dk") - (print-short "Jens Krinke" "krinke@ips.cs.tu-bs.de") - (print-short "Maximilien Lincourt" "max@toonboom.com") + (print-short "Markus Gutschke" "gutschk@GOEDEL.UNI-MUENSTER.DE") + (print-short "Markus Linnala" "maage@b14b.tupsu.ton.tut.fi") + (print-short "Martin Pottendorfer" "Martin.Pottendorfer@aut.alcatel.at") + (print-short "Marty Sasaki" "sasaki@spdcc.com") (print-short "Mats Larsson" "Mats.Larsson@uab.ericsson.se") - (print-short "Simon Leinen" "simon@instrumatic.ch") - (print-short "Carsten Leonhardt" "leo@arioch.oche.de") - (print-short "James LewisMoss" "moss@cs.sc.edu") (print-short "Mats Lidell" "mats.lidell@contactor.se") (print-short "Matt Liggett" "mliggett@seven.ucs.indiana.edu") - (print-short "Christian Limpach" "Christian.Limpach@nice.ch") + (print-short "Matt Simmons" "simmonmt@acm.org") + (print-short "Matthew J. Brown" "mjb@doc.ic.ac.uk") + (print-short "Mauro Condarelli" "MC5686@mclink.it") (print-short "Maximilien Lincourt" "max@toonboom.com") - (print-short "Markus Linnala" "maage@b14b.tupsu.ton.tut.fi") - (print-short "Robert Lipe" "robertl@arnet.com") - (print-short "Derrell Lipman" "derrell@vis-av.com") - (print-short "Damon Lipparelli" "lipp@aa.net") - (print-short "Hamish Macdonald" "hamish@bnr.ca") - (print-short "Ian MacKinnon" "imackinnon@telia.co.uk") - (print-short "Patrick MacRoberts" "macro@hpcobr30.cup.hp.com") - (print-short "Tonny Madsen" "Tonny.Madsen@netman.dk") - (print-short "Ketil Z Malde" "ketil@ii.uib.no") - (print-short "Steve March" "smarch@quaver.urbana.mcd.mot.com") - (print-short "Ricardo Marek" "ricky@ornet.co.il") - (print-short "Pekka Marjola" "pema@iki.fi") - (print-short "Simon Marshall" "simon@gnu.ai.mit.edu") - (print-short "Dave Mason" "dmason@plg.uwaterloo.ca") - (print-short "Jaye Mathisen" "mrcpu@cdsnet.net") - (print-short "Jason McLaren" "mclaren@math.mcgill.ca") + (print-short "Michael Diers" "mdiers@elego.de") + (print-short "Michael Guenther" "michaelg@igor.stuttgart.netsurf.de") + (print-short "Michael Harnois" "mharnois@sbt.net") + (print-short "Michael Kifer" "kifer@cs.sunysb.edu") (print-short "Michael McNamara" "mac@silicon-sorcery.com") (print-short "Michael Meissner" "meissner@osf.org") - (print-short "David M. Meyer" "meyer@ns.uoregon.edu") - (print-short "John Mignault" "jbm@panix.com") - (print-short "Brad Miller" "bmiller@cs.umn.edu") - (print-short "John Morey" "jmorey@crl.com") - (print-short "Rob Mori" "rob.mori@sun.com") - (print-short "Heiko Muenkel" "muenkel@tnt.uni-hannover.de") - (print-short "Arup Mukherjee" "arup+@cs.cmu.edu") - (print-short "Colas Nahaboo" "Colas.Nahaboo@sophia.inria.fr") - (print-short "Lynn D. Newton" "lynn@ives.phx.mcd.mot.com") - (print-short "Casey Nielson" "knielson@joule.elee.calpoly.edu") - (print-short "Georg Nikodym" "Georg.Nikodym@canada.sun.com") - (print-short "Andy Norman" "ange@hplb.hpl.hp.com") - (print-short "Joe Nuspl" "nuspl@sequent.com") - (print-short "Kim Nyberg" "kny@tekla.fi") - (print-short "Kevin Oberman" "oberman@es.net") - (print-short "David Ofelt" "ofelt@getalife.Stanford.EDU") - (print-short "Alexandre Oliva" "oliva@dcc.unicamp.br") - (print-short "Tore Olsen" "toreo@colargol.idb.hist.no") - (print-short "Greg Onufer" "Greg.Onufer@eng.sun.com") - (print-short "Achim Oppelt" "aoppelt@theorie3.physik.uni-erlangen.de") - (print-short "Rebecca Ore" "rebecca.ore@op.net") - (print-short "Sudeep Kumar Palat" "palat@idt.unit.no") - (print-short "Joel Peterson" "tarzan@aosi.com") - (print-short "Thomas A. Peterson" "tap@src.honeywell.com") - (print-short "Tibor Polgar" "tibor@alteon.com") - (print-short "Frederic Poncin" "fp@info.ucl.ac.be") - (print-short "E. Rehmi Post" "rehmi@asylum.sf.ca.us") - (print-short "Martin Pottendorfer" "Martin.Pottendorfer@aut.alcatel.at") - (print-short "Colin Rafferty" "colin@xemacs.org") - (print-short "Rick Rankin" "Rick_Rankin-P15254@email.mot.com") - (print-short "Paul M Reilly" "pmr@pajato.com") - (print-short "Jack Repenning" "jackr@sgi.com") - (print-short "Daniel Rich" "drich@cisco.com") - (print-short "Roland Rieke" "rol@darmstadt.gmd.de") - (print-short "Art Rijos" "art.rijos@SNET.com") - (print-short "Russell Ritchie" "ritchier@britannia-life.co.uk") - (print-short "Roland" "rol@darmstadt.gmd.de") + (print-short "Mike Battaglia" "mbattagl@dsccc.com") + (print-short "Mike Hill" "mikehill@hgeng.com") (print-short "Mike Russell" "mjruss@rchland.vnet.ibm.com") - (print-short "Hajime Saitou" "hajime@jsk.t.u-tokyo.ac.jp") - (print-short "Jan Sandquist" "etxquist@iqa.ericsson.se") - (print-short "Marty Sasaki" "sasaki@spdcc.com") - (print-short "SATO Daisuke" "densuke@ga2.so-net.or.jp") - (print-short "Kenji Sato" "ken@ny.kdd.com") (print-short "Mike Scheidler" "c23mts@eng.delcoelect.com") - (print-short "Daniel Schepler" "daniel@shep13.wustl.edu") - (print-short "Holger Schauer" "schauer@coling.uni-freiburg.de") - (print-short "Darrel Schneider" "darrel@slc.com") - (print-short "Hayden Schultz" "haydens@ll.mit.edu") - (print-short "Cotton Seed" "cottons@cybercom.net") - (print-short "Axel Seibert" "seiberta@informatik.tu-muenchen.de") - (print-short "Odd-Magne Sekkingstad" "oddms@ii.uib.no") - (print-short "Gregory Neil Shapiro" "gshapiro@sendmail.org") - (print-short "Justin Sheehy" "justin@linus.mitre.org") - (print-short "John Shen" "zfs60@cas.org") (print-short "Murata Shuuichirou" "mrt@mickey.ai.kyutech.ac.jp") - (print-short "Matt Simmons" "simmonmt@acm.org") - (print-short "Dinesh Somasekhar" "somasekh@ecn.purdue.edu") - (print-short "Jeffrey Sparkes" "jsparkes@bnr.ca") - (print-short "Manoj Srivastava" "srivasta@pilgrim.umass.edu") - (print-short "Francois Staes" "frans@kiwi.uia.ac.be") - (print-short "Anders Stenman" "stenman@isy.liu.se") - (print-short "Jason Stewart" "jasons@cs.unm.edu") - (print-short "Rick Tait" "rickt@gnu.ai.mit.edu") - (print-short "TANAKA Hayashi" "tanakah@mxa.mesh.ne.jp") - (print-short "Samuel Tardieu" "sam@inf.enst.fr") - (print-short "James Thompson" "thompson@wg2.waii.com") + (print-short "Nagi M. Aboulenein" "aboulene@ponder.csci.unt.edu") + (print-short "Neal Becker" "neal@ctd.comsat.com") + (print-short "Nick J. Crabtree" "nickc@scopic.com") + (print-short "Noah Friedman" "friedman@splode.com") (print-short "Nobu Toge" "toge@accad1.kek.jp") + (print-short "Norbert Koch" "n.koch@delta-ii.de") + (print-short "Odd-Magne Sekkingstad" "oddms@ii.uib.no") + (print-short "Oswald P. Backus IV" "backus@altagroup.com") + (print-short "Patrick MacRoberts" "macro@hpcobr30.cup.hp.com") + (print-short "Paul Bibilo" "peb@delcam.com") + (print-short "Paul Flinders" "ptf@delcam.co.uk") + (print-short "Paul M Reilly" "pmr@pajato.com") + (print-short "Pekka Marjola" "pema@iki.fi") + (print-short "Per Abrahamsen" "abraham@dina.kvl.dk") + (print-short "Peter B. West" "p.west@uq.net.au") + (print-short "Peter Cheng" "peter.cheng@sun.com") + (print-short "Peter Skov Knudsen" "knu@dde.dk") + (print-short "Peter Ware" "ware@cis.ohio-state.edu") + (print-short "Peter Windle" "peterw@SDL.UG.EDS.COM") + (print-short "Philip Johnson" "johnson@uhics.ics.Hawaii.Edu") + (print-short "Philippe Charton" "charton@lmd.ens.fr") (print-short "Raymond L. Toy" "toy@rtp.ericsson.se") + (print-short "Raymond Wiker" "raymond@orion.no") + (print-short "Rebecca Ore" "rebecca.ore@op.net") (print-short "Remek Trzaska" "remek@npac.syr.edu") - (print-short "TSUTOMU Nakamura" "tsutomu@rs.kyoto.omronsoft.co.jp") + (print-short "Ricardo Marek" "ricky@ornet.co.il") + (print-short "Rich Williams" "rdw@hplb.hpl.hp.com") + (print-short "Richard Caley" "rjc@cstr.edinburgh.ac.uk") + (print-short "Richard Cognot" "cognot@ensg.u-nancy.fr") + (print-short "Richard Coleman" "coleman@math.gatech.edu") + (print-short "Rick Braumoeller" "rickb@mti.sgi.com") + (print-short "Rick Rankin" "Rick_Rankin-P15254@email.mot.com") + (print-short "Rick Tait" "rickt@gnu.ai.mit.edu") + (print-short "Rob Kooper" "kooper@cc.gatech.edu") + (print-short "Rob Mori" "rob.mori@sun.com") + (print-short "Robert Lipe" "robertl@arnet.com") + (print-short "Robin Jeffries" "robin.jeffries@sun.com") + (print-short "Rod Whitby" "rwhitby@asc.corp.mot.com") + (print-short "Roland Rieke" "rol@darmstadt.gmd.de") + (print-short "Russell Ritchie" "ritchier@britannia-life.co.uk") + (print-short "SATO Daisuke" "densuke@ga2.so-net.or.jp") + (print-short "Samuel J. Eaton" "samuele@cogs.susx.ac.uk") + (print-short "Samuel Tardieu" "sam@inf.enst.fr") + (print-short "Serenella Ciongoli" "czs00@ladybug.oes.amdahl.com") + (print-short "Shane Holder" "holder@rsn.hp.com") + (print-short "Simon Leinen" "simon@instrumatic.ch") + (print-short "Simon Marshall" "simon@gnu.ai.mit.edu") + (print-short "Soren Dayton" "csdayton@cs.uchicago.edu") (print-short "Stefanie Teufel" "s.teufel@ndh.net") - (print-short "Gary Thomas" "g.thomas@opengroup.org") - (print-short "John Turner" "turner@xdiv.lanl.gov") + (print-short "Stephan Herrmann" "sh@first.gmd.de") + (print-short "Stephen Carney" "carney@gvc.dec.com") + (print-short "Stephen R. Anderson" "sra@bloch.ling.yale.edu") + (print-short "Steve Dunham" "dunham@dunham.tcimet.net") + (print-short "Steve March" "smarch@quaver.urbana.mcd.mot.com") + (print-short "Sudeep Kumar Palat" "palat@idt.unit.no") + (print-short "TANAKA Hayashi" "tanakah@mxa.mesh.ne.jp") + (print-short "TSUTOMU Nakamura" "tsutomu@rs.kyoto.omronsoft.co.jp") + (print-short "Takeshi Yamada" "yamada@sylvie.kecl.ntt.jp") + (print-short "Tatsuya Ichikawa" "ichikawa@hv.epson.co.jp") + (print-short "Tetsuya HOYANO" "hoyano@ari.bekkoame.or.jp") + (print-short "Thomas A. Peterson" "tap@src.honeywell.com") + (print-short "Tibor Polgar" "tibor@alteon.com") + (print-short "Tim Bradshaw" "tfb@edinburgh.ac.uk") + (print-short "Tim Geisler" "Tim.Geisler@informatik.uni-muenchen.de") + (print-short "Tomasz J. Cholewo" "tjchol01@mecca.spd.louisville.edu") + (print-short "Tonny Madsen" "Tonny.Madsen@netman.dk") + (print-short "Tor Arntsen" "tor@spacetec.no") + (print-short "Tore Olsen" "toreo@colargol.idb.hist.no") + (print-short "Tudor Hulubei" "tudor@cs.unh.edu") (print-short "UENO Fumihiro" "7m2vej@ritp.ye.IHI.CO.JP") - (print-short "Aki Vehtari" "Aki.Vehtari@hut.fi") - (print-short "Juan E. Villacis" "jvillaci@cs.indiana.edu") + (print-short "Valdis Kletnieks" "Valdis.Kletnieks@vt.edu") (print-short "Vladimir Vukicevic" "vladimir@intrepid.com") - (print-short "David Walte" "djw18@cornell.edu") - (print-short "Peter Ware" "ware@cis.ohio-state.edu") - (print-short "Christoph Wedler" "wedler@fmi.uni-passau.de") - (print-short "Yoav Weiss" "yoav@zeus.datasrv.co.il") - (print-short "Peter B. West" "p.west@uq.net.au") - (print-short "Rod Whitby" "rwhitby@asc.corp.mot.com") - (print-short "Rich Williams" "rdw@hplb.hpl.hp.com") - (print-short "Raymond Wiker" "raymond@orion.no") - (print-short "Peter Windle" "peterw@SDL.UG.EDS.COM") - (print-short "David C Worenklein" "dcw@gcm.com") - (print-short "Takeshi Yamada" "yamada@sylvie.kecl.ntt.jp") - (print-short "Katsumi Yamaoka" "yamaoka@ga.sony.co.jp") - (print-short "Jason Yanowitz" "yanowitz@eternity.cs.umass.edu") - (print-short "La Monte Yarroll" "piggy@hilbert.maths.utas.edu.au") - (print-short "Blair Zajac" "blair@olympia.gps.caltech.edu") (print-short "Volker Zell" "vzell@de.oracle.com") - (print-short "Daniel Zivkovic" "daniel@canada.sun.com") - (print-short "Karel Zuiderveld" "Karel.Zuiderveld@cv.ruu.nl") + (print-short "William G. Dubuque" "wgd@martigny.ai.mit.edu") + (print-short "Wolfgang Grieskamp" "wg@cs.tu-berlin.de") + (print-short "Yasuhiko Kiuchi" "kiuchi@dsp.ksp.fujixerox.co.jp") + (print-short "Yoav Weiss" "yoav@zeus.datasrv.co.il") + (print-short "Yoshiaki Kasahara" "kasahara@nc.kyushu-u.ac.jp") + (print-short "Yusuf Goolamabbas" "yusufg@iss.nus.sg") (widget-insert "\n")) (about-finish-buffer))) diff --text -u 'xemacs-21.5.18/lisp/autoload.el' 'xemacs-21.5.19/lisp/autoload.el' Index: ./lisp/autoload.el --- ./lisp/autoload.el Wed Oct 15 18:19:10 2003 +++ ./lisp/autoload.el Fri Feb 4 12:57:34 2005 @@ -2,9 +2,10 @@ ;; Copyright (C) 1991-1994, 1997, 2003 Free Software Foundation, Inc. ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. -;; Copyright (C) 1996, 2000, 2002, 2003 Ben Wing. +;; Copyright (C) 1996, 2000, 2002, 2003, 2004 Ben Wing. -;; Author: Roland McGrath <roland@gnu.ai.mit.edu> +;; Original Author: Roland McGrath <roland@gnu.ai.mit.edu> +;; Heavily Modified: XEmacs Maintainers ;; Keywords: maint ;; This file is part of XEmacs. @@ -24,13 +25,17 @@ ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ;; 02111-1307, USA. -;;; Synched up with: Not synched with FSF. +;;; Synched up with: FSF 21.2 by Ben Wing. +;;; Note that update-file-autoloads is seriously modified and not really +;;; syncable. ;;; Commentary: ;; This code keeps auto-autoloads.el files up to date. It interprets ;; magic cookies (of the form ";;;###autoload" in Lisp source files ;; and "/* ###autoload */" in C source files) in various useful ways. +;; It is also used to maintain custom-defines.el files, since most of +;; the logic for computing them is the same as for auto-autoloads.el. ;; Usage ;; ===== @@ -39,8 +44,7 @@ ;; build process, is ;; xemacs -no-packages -batch \ -;; -eval "(setq generated-autoload-file \"PATH\")" \ -;; -l autoload -f autoload-update-directory-autoloads PREFIX DIRECTORY +;; -l autoload -f batch-update-directory-autoloads PREFIX DIRECTORY ;; which causes XEmacs to update the file named by PATH from the .el ;; files in DIRECTORY (but not recursing into subdirectories) and (if @@ -61,24 +65,13 @@ ;; of XEmacs). ;; The probable next step is to fix up the packages to use the -;; `autoload-update-directory-autoloads' API. However, for backward +;; `batch-update-directory-autoloads' API. However, for backward ;; compatibility with XEmacs 21.4 and 21.1, this can't be done quickly. -;; For now the API used in update-elc-2.el: - -;; (let* ((dir "DIRECTORY") -;; (generated-autoload-file (expand-file-name "auto-autoloads.el" dir)) -;; (autoload-package-name "PREFIX")) -;; (update-autoload-files (list muledir)) -;; (byte-recompile-file generated-autoload-file 0)) - -;; is available, but this ugly kludge is deprecated. It will be removed -;; in favor of using proper arguments instead of special variables. - ;; For backward compatibility the API used in the packages/XEmacs.rules: ;; xemacs -vanilla -batch -eval "$(AUTOLOAD_PACKAGE_NAME)" \ -;; -l autoload -f batch-update-directory $(AUTOLOAD_PATH) +;; -l autoload -f batch-update-autoloads $(AUTOLOAD_PATH) ;; is supported, and the implementation is unchanged. However, ;; revision of the API (in a backward compatible way) and the @@ -130,6 +123,10 @@ ;;; Code: +;; Need to load easy-mmode because we expand macro calls to easy-mmode +;; macros in make-autoloads below. +(require 'easy-mmode) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Standard file and directory names @@ -144,6 +141,10 @@ ;; Dynamic variables for communication among functions +;; FSF 21.2: +;; The autoload file is assumed to contain a trailer starting with a FormFeed +;; character. + (defvar generated-autoload-file (expand-file-name autoload-file-name lisp-directory) "*File `update-file-autoloads' puts autoloads into. @@ -154,6 +155,11 @@ generally the file named by `autoload-file-name' in the directory being updated. XEmacs.rules setq's this variable for package autoloads.") +(defvar generate-autoload-function + #'generate-file-autoloads + "Function to generate the autoloads for a file and insert at point. +Called with one argument, the file.") + (define-obsolete-variable-alias 'autoload-package-name 'autoload-feature-prefix) (defvar autoload-feature-prefix nil @@ -164,6 +170,9 @@ auto-autoloads file). Highest priority candidate except for an explicit argument to `autoload-make-feature-name' (q.v.).") +(defvar autoload-feature-suffix "-autoloads" + "String added to `autoload-feature-prefix' to create the autoload feature name.") + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Magic strings in source files @@ -210,40 +219,69 @@ (defconst generate-autoload-section-trailer "\n;;;***\n" "String which indicates the end of the section of autoloads for a file.") +(defconst generate-autoload-section-continuation ";;;;;; " + "String to add on each continuation of the section header form.") + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Parsing the source file text. -;; Autoloads in C source differ from those in Lisp source. For historical -;; reasons, functions handling only Lisp don't have "lisp" in their names; -;; maybe this should be changed. +;; Autoloads in C source differ from those in Lisp source. (defun make-autoload (form file) - "Turn a definition generator FORM into an autoload for source file FILE. -Returns nil if FORM is not a defun, defun*, defmacro, defmacro*, -define-skeleton, or define-derived-mode." - (let ((car (car-safe form))) - (if (memq car '(defun defun* define-skeleton defmacro defmacro* - define-derived-mode)) - (let ((macrop (memq car '(defmacro defmacro*))) - name doc) - (setq form (cdr form) - name (car form) - ;; Ignore the arguments. - form (cdr (cond ((eq car 'define-skeleton) - form) - ((eq car 'define-derived-mode) - (cddr form)) - (t - (cdr form)))) - doc (car form)) - (if (stringp doc) - (setq form (cdr form)) - (setq doc nil)) - (list 'autoload (list 'quote name) file doc - (or (eq car 'define-skeleton) - (eq car 'define-derived-mode) - (eq (car-safe (car form)) 'interactive)) - (if macrop (list 'quote 'macro) nil))) - nil))) + "Turn FORM into an autoload or defvar for source file FILE. +Returns nil if FORM is not a special autoload form (i.e. a function definition +or macro definition or a defcustom)." + (let ((car (car-safe form)) expand) + (cond + ;; For complex cases, try again on the macro-expansion. + ((and (memq car '(easy-mmode-define-global-mode + easy-mmode-define-minor-mode define-minor-mode)) + (setq expand (let ((load-file-name file)) (macroexpand form))) + (eq (car expand) 'progn) + (memq :autoload-end expand)) + (let ((end (memq :autoload-end expand))) + ;; Cut-off anything after the :autoload-end marker. + (setcdr end nil) + (cons 'progn + (mapcar (lambda (form) (make-autoload form file)) + (cdr expand))))) + + ;; For special function-like operators, use the `autoload' function. + ((memq car '(defun define-skeleton defmacro define-derived-mode + define-generic-mode easy-mmode-define-minor-mode + easy-mmode-define-global-mode + define-minor-mode defun* defmacro*)) + (let* ((macrop (memq car '(defmacro defmacro*))) + (name (nth 1 form)) + (body (nthcdr (get car 'doc-string-elt) form)) + (doc (if (stringp (car body)) (pop body)))) + ;; `define-generic-mode' quotes the name, so take care of that + (list 'autoload (if (listp name) name (list 'quote name)) file doc + (or (and (memq car '(define-skeleton define-derived-mode + define-generic-mode + easy-mmode-define-global-mode + easy-mmode-define-minor-mode + define-minor-mode)) t) + (eq (car-safe (car body)) 'interactive)) + (if macrop (list 'quote 'macro) nil)))) + + ;; Convert defcustom to a simpler (and less space-consuming) defvar, + ;; but add some extra stuff if it uses :require. + ((eq car 'defcustom) + (let ((varname (car-safe (cdr-safe form))) + (init (car-safe (cdr-safe (cdr-safe form)))) + (doc (car-safe (cdr-safe (cdr-safe (cdr-safe form))))) + (rest (cdr-safe (cdr-safe (cdr-safe (cdr-safe form)))))) + (if (not (plist-get rest :require)) + `(defvar ,varname ,init ,doc) + `(progn + (defvar ,varname ,init ,doc) + (custom-add-to-group ,(plist-get rest :group) + ',varname 'custom-variable) + (custom-add-load ',varname + ,(plist-get rest :require)))))) + + ;; nil here indicates that this is not a special autoload form. + (t nil)))) (defun make-c-autoload (module) "Make an autoload list for the DEFUN at point in MODULE. @@ -283,7 +321,7 @@ ;; Generating autoloads for a single file ;;;###autoload -(defun generate-file-autoloads (file &optional funlist) +(defun generate-file-autoloads (file) "Insert at point an autoload section for FILE. autoloads are generated for defuns and defmacros in FILE marked by `generate-autoload-cookie' (which see). @@ -291,26 +329,26 @@ are used." (interactive "fGenerate autoloads for file: ") (cond ((string-match "\\.el$" file) - (generate-autoload-ish-1 + (generate-autoload-type-section file (replace-in-string (file-name-nondirectory file) "\\.elc?$" "") - nil #'generate-file-autoloads-1 - funlist)) + nil #'generate-lisp-file-autoloads-1)) ;; #### jj, are C++ modules possible? ((string-match "\\.c$" file) - (generate-autoload-ish-1 + (generate-autoload-type-section file (replace-in-string (file-name-nondirectory file) "\\.c$" "") - t #'generate-c-file-autoloads-1 - funlist)) + t #'generate-c-file-autoloads-1)) (t (error 'wrong-type-argument file "not a C or Elisp source file")))) -(defun* generate-autoload-ish-1 (file load-name literal fun-to-call &rest args) +(defun* generate-autoload-type-section (file load-name literal fun-to-call) "Insert at point an autoload-type section for FILE. -If LITERAL, open the file literally, without decoding. -Calls FUN-TO-CALL to compute the autoloads, passing it OUTBUF, LOAD-NAME, - TRIM-NAME, and ARGS." +LOAD-NAME is the non-directory portion of the name, with the final .el, .elc +or .c section removed. If LITERAL, open the file literally, without decoding. +Calls FUN-TO-CALL to compute the autoloads, with the loaded file in the +current buffer, passing it OUTBUF (where to write the autoloads), LOAD-NAME, +and TRIM-NAME (result of calling `autoload-trim-file-name' on FILE)." (let ((outbuf (current-buffer)) (trim-name (autoload-trim-file-name file)) (autoloads-done '()) @@ -318,6 +356,7 @@ (print-readably t) ; XEmacs (float-output-format nil) (visited (get-file-buffer file)) + suppress-form ;; (done-any nil) output-end) @@ -329,21 +368,74 @@ ;; subdirectory of the current buffer's directory, we'll make it ;; relative to the current buffer's directory. (setq file (expand-file-name file)) + ;; #### FSF 21.2. Do we want this? +; (let* ((source-truename (file-truename file)) +; (dir-truename (file-name-as-directory +; (file-truename default-directory))) +; (len (length dir-truename))) +; (if (and (< len (length source-truename)) +; (string= dir-truename (substring source-truename 0 len))) +; (setq file (substring source-truename len)))) + + ;; Check for suppression form (XEmacs) + (let* ((dir (file-name-directory file)) + (_pkg (expand-file-name "_pkg.el" dir)) + (pkg-vis (get-file-buffer _pkg)) + pkg-buf) + (save-excursion + (when (file-readable-p _pkg) + (unwind-protect + (progn + (let ((find-file-hooks nil) + (enable-local-variables nil)) + (set-buffer (or pkg-vis (find-file-noselect _pkg))) + (set-syntax-table emacs-lisp-mode-syntax-table)) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (block nil + (while (search-forward "(package-suppress" nil t) + ;; skip over package-name + (forward-sexp 1) + (let ((supfile (read (current-buffer)))) + (when (equal supfile load-name) + (setq suppress-form (eval (read (current-buffer)))) + (return)))))))) + (unless pkg-vis + ;; We created this buffer, so we should kill it. + (if pkg-buf (kill-buffer pkg-buf))))))) (save-excursion (unwind-protect (progn - (let ((find-file-hooks nil) - (enable-local-variables nil)) + (let (;(find-file-hooks nil) + ;(enable-local-variables nil) + ) (set-buffer (or visited (find-file-noselect file literal literal ))) ;; This doesn't look right for C files, but it is. The only ;; place we need the syntax table is when snarfing the Lisp ;; function name. (set-syntax-table emacs-lisp-mode-syntax-table)) +; (if visited +; (set-buffer visited) +; ;; It is faster to avoid visiting the file. +; (set-buffer (get-buffer-create " *generate-autoload-file*")) +; (kill-all-local-variables) +; (erase-buffer) +; (setq buffer-undo-list t +; buffer-read-only nil) +; ;; This doesn't look right for C files, but it is. The only +; ;; place we need the syntax table is when snarfing the Lisp +; ;; function name. +; (emacs-lisp-mode) +; (if literal +; (insert-file-contents-literally file nil) +; (insert-file-contents file nil))) (unless (setq autoloads-done - (apply fun-to-call outbuf load-name trim-name args)) - (return-from generate-autoload-ish-1)) + (funcall fun-to-call outbuf load-name trim-name)) + (return-from generate-autoload-type-section)) ) (unless visited ;; We created this buffer, so we should kill it. @@ -354,108 +446,124 @@ ;; XEmacs -- always do this so that we cache the information ;; that we've processed the file already. (progn + ;; Insert the section-header line + ;; which lists the file name and which functions are in it, etc. (insert generate-autoload-section-header) - (prin1 (list 'autoloads autoloads-done load-name trim-name) + (prin1 (list 'autoloads autoloads-done load-name trim-name + ;; In FSF 21.2. Also in FSF 19.30. Presumably + ;; deleted from XEmacs. + ;; (nth 5 (file-attributes file)) + ) outbuf) (terpri outbuf) - ;;;; (insert ";;; Generated autoloads from " - ;;;; (autoload-trim-file-name file) "\n") - ;; Warn if we put a line in auto-autoloads.el - ;; that is long enough to cause trouble. - (when (< output-end (point)) - (setq output-end (point-marker))) - (while (< (point) output-end) - ;; (let ((beg (point))) - (end-of-line) - ;; Emacs -- I still haven't figured this one out. - ;; (if (> (- (point) beg) 900) - ;; (progn - ;; (message "A line is too long--over 900 characters") - ;; (sleep-for 2) - ;; (goto-char output-end))) - ;; ) - (forward-line 1)) + ;; #### Alas, we will have to think about this. Adding this means + ;; that, once we have created or maintained an auto-autoloads file, + ;; we alone and our successors can update the file. The file itself + ;; will work fine in older XEmacsen, but they won't be able to + ;; update autoloads -- hence, to build. +; ;; Break that line at spaces, to avoid very long lines. +; ;; Make each sub-line into a comment. +; (with-current-buffer outbuf +; (save-excursion +; (forward-line -1) +; (while (not (eolp)) +; (move-to-column 64) +; (skip-chars-forward "^ \n") +; (or (eolp) +; (insert "\n" generate-autoload-section-continuation))))) + ;; XEmacs: This was commented out before. #### Correct? +; (insert ";;; Generated autoloads from " +; (autoload-trim-file-name file) "\n") + ;; XEmacs -- handle suppression + (when suppress-form + (insert "\n;;; Suppress form from _pkg.el\n") + (insert "(unless " (prin1-to-string suppress-form) "\n\n")) (goto-char output-end) + ;; XEmacs -- handle suppression + (when suppress-form + (insert "\n) ;; unless (suppressed)\n")) (insert generate-autoload-section-trailer))) - (or noninteractive ; XEmacs: only need one line in -batch mode. - (message "Generating autoloads for %s...done" file)))) + )) -(defun* generate-file-autoloads-1 (outbuf load-name trim-name funlist) - "Insert at point an autoload section for FILE. -autoloads are generated for defuns and defmacros in FILE -marked by `generate-autoload-cookie' (which see). -If FILE is being visited in a buffer, the contents of the buffer -are used." + +(defun process-one-lisp-autoload (autoloads-done outbuf load-name) + "Process a single autoload at point and write to OUTBUF. +Point should be just after a magic cookie string (e.g. ;;;###autoload). +Updates AUTOLOADS-DONE and returns the new value." + (skip-chars-forward " \t") + ;; (setq done-any t) + (if (eolp) + ;; Read the next form and make an autoload. + (let* ((form (prog1 (read (current-buffer)) + (or (bolp) (forward-line 1)))) + (autoload (make-autoload form load-name))) + (if autoload + (setq autoloads-done (cons (nth 1 form) + autoloads-done)) + (setq autoload form)) + (autoload-print-form autoload outbuf "")) + ;; Copy the rest of the line to the output. + (cond ((looking-at "immediate\\s *$") ; XEmacs + ;; This is here so that you can automatically + ;; have small hook functions copied to + ;; auto-autoloads.el so that it's not necessary + ;; to load a whole file just to get a two-line + ;; do-nothing find-file-hook... --Stig + (forward-line 1) + (let ((begin (point))) + (forward-sexp) + (forward-line 1) + (princ (buffer-substring begin (point)) outbuf))) + (t + (princ (buffer-substring + (progn + ;; Back up over whitespace, to preserve it. + (skip-chars-backward " \f\t") + (if (= (char-after (1+ (point))) ? ) + ;; Eat one space. + (forward-char 1)) + (point)) + (progn (forward-line 1) (point))) + outbuf)))) + autoloads-done) + +(defun* generate-lisp-file-autoloads-1 (outbuf load-name trim-name) + "Insert at point in OUTBUF an autoload section for an Elisp file. +The file is assumed to be already loaded and in the current buffer. +autoloads are generated for defuns and defmacros marked by +`generate-autoload-cookie' (which see)." (let ((autoloads-done '()) - (dofiles (not (null funlist))) ) - (save-excursion (save-restriction (widen) (goto-char (point-min)) (unless (search-forward generate-autoload-cookie nil t) (message "No autoloads found in %s" trim-name) - (return-from generate-file-autoloads-1 nil)) + (return-from generate-lisp-file-autoloads-1 nil)) (message "Generating autoloads for %s..." trim-name) (goto-char (point-min)) - (while (if dofiles funlist (not (eobp))) - (if (not dofiles) - (skip-chars-forward " \t\n\f") - (goto-char (point-min)) - (re-search-forward - (concat "(def\\(un\\|var\\|const\\|macro\\) " - (regexp-quote (symbol-name (car funlist))) - "\\s ")) - (goto-char (match-beginning 0))) + (while (not (eobp)) + (skip-chars-forward " \t\n\f") (cond - ((or dofiles - (looking-at (regexp-quote generate-autoload-cookie))) - (if dofiles - nil - (search-forward generate-autoload-cookie) - (skip-chars-forward " \t")) - ;; (setq done-any t) - (if (or dofiles (eolp)) - ;; Read the next form and make an autoload. - (let* ((form (prog1 (read (current-buffer)) - (or (bolp) (forward-line 1)))) - (autoload (make-autoload form load-name)) - (doc-string-elt (get (car-safe form) - 'doc-string-elt))) - (if autoload - (setq autoloads-done (cons (nth 1 form) - autoloads-done)) - (setq autoload form)) - (print-autoload autoload doc-string-elt outbuf "")) - ;; Copy the rest of the line to the output. - (let ((begin (point))) - ;; (terpri outbuf) - (cond ((looking-at "immediate\\s *$") ; XEmacs - ;; This is here so that you can automatically - ;; have small hook functions copied to - ;; auto-autoloads.el so that it's not necessary - ;; to load a whole file just to get a two-line - ;; do-nothing find-file-hook... --Stig - (forward-line 1) - (setq begin (point)) - (forward-sexp) - (forward-line 1)) - (t - (forward-line 1))) - (princ (buffer-substring begin (point)) outbuf)))) + ((looking-at (regexp-quote generate-autoload-cookie)) + (search-forward generate-autoload-cookie) + (setq autoloads-done + (process-one-lisp-autoload autoloads-done outbuf load-name))) ((looking-at ";") ;; Don't read the comment. (forward-line 1)) (t (forward-sexp 1) (forward-line 1))) - (if dofiles - (setq funlist (cdr funlist)))))) + ))) + (or noninteractive ; XEmacs: only need one line in -batch mode. + (message "Generating autoloads for %s...done" trim-name)) autoloads-done)) -(defun* generate-c-file-autoloads-1 (outbuf load-name trim-name funlist) +(defun* generate-c-file-autoloads-1 (outbuf load-name trim-name + &optional funlist) "Insert at point an autoload section for the C file FILE. autoloads are generated for defuns and defmacros in FILE marked by `generate-c-autoload-cookie' (which see). @@ -488,7 +596,7 @@ (let ((autoload (make-c-autoload load-name))) (when autoload (push (nth 1 (nth 1 autoload)) autoloads-done) - (print-autoload autoload 3 outbuf " ")))) + (autoload-print-form autoload outbuf " ")))) ;; close the princ'd `when' form (princ ")" outbuf)) (goto-char (point-min)) @@ -505,91 +613,175 @@ (let ((autoload (make-c-autoload load-name))) (when autoload (push (nth 1 (nth 1 autoload)) autoloads-done) - (print-autoload autoload 3 outbuf " "))) + (autoload-print-form autoload outbuf " "))) (setq match (search-forward generate-c-autoload-cookie nil t))) ;; close the princ'd `when' form (princ ")" outbuf))))) + (or noninteractive ; XEmacs: only need one line in -batch mode. + (message "Generating autoloads for %s...done" trim-name)) autoloads-done)) -;; Assorted utilities for generating autoloads and pieces thereof +;;;###autoload +(defun generate-custom-defines (file) + "Insert at point a custom-define section for FILE. +If FILE is being visited in a buffer, the contents of the buffer +are used." + (interactive "fGenerate custom defines for file: ") + (cond ((string-match "\\.el$" file) + (generate-autoload-type-section + file + (replace-in-string (file-name-nondirectory file) "\\.elc?$" "") + nil #'generate-custom-defines-1)) + ((string-match "\\.c$" file) + ;; no way to generate custom-defines for C files (currently?), + ;; but cannot signal an error. + nil) + (t + (error 'wrong-type-argument file "not a C or Elisp source file")))) + +(defun* generate-custom-defines-1 (outbuf load-name trim-name) + "Insert at point in OUTBUF a custom-define section for an Elisp file. +This contains all defcustoms and defgroups in the file. +The file is assumed to be already loaded and in the current buffer." + (let* ((search-regexp-1 "^(\\(defcustom\\|defgroup\\) ") + (search-string-2 ";;;###custom-define") + (search-regexp-2 (regexp-quote search-string-2)) + (autoloads-done '())) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (unless (or (re-search-forward search-regexp-1 nil t) + (re-search-forward search-regexp-2 nil t)) + (message "No custom defines found in %s" trim-name) + (return-from generate-custom-defines-1 nil)) + (message "Generating custom defines for %s..." trim-name) + (princ "(defconst custom-define-current-source-file " outbuf) + (prin1 (file-relative-name (buffer-file-name) + (symbol-value-in-buffer 'default-directory + outbuf)) outbuf) + (princ ")\n" outbuf) + + (goto-char (point-min)) + (while (not (eobp)) + (skip-chars-forward " \t\n\f") + (cond + ((looking-at search-regexp-1) + ;; Read the next form and copy it to make an autoload. + (let* ((form (prog1 (read (current-buffer)) + (or (bolp) (forward-line 1)))) + (autoload form ;(make-autoload form load-name) + )) + (if autoload + (setq autoloads-done (cons (nth 1 form) + autoloads-done)) + (setq autoload form)) + (autoload-print-form autoload outbuf "")) + ) + ((looking-at search-regexp-2) + (search-forward search-string-2) + (beep) + (setq autoloads-done + (process-one-lisp-autoload autoloads-done outbuf load-name))) + ((looking-at ";") + ;; Don't read the comment. + (forward-line 1)) + (t + (forward-sexp 1) + (forward-line 1))) + ))) + (or noninteractive ; XEmacs: only need one line in -batch mode. + (message "Generating custom defines for %s...done" trim-name)) + autoloads-done)) -(defun print-autoload (autoload doc-string-elt outbuf margin) +;; Assorted utilities for generating autoloads and pieces thereof + +(defun autoload-print-form (form outbuf margin) "Print an autoload form, handling special characters. In particular, print docstrings with escapes inserted before left parentheses at the beginning of lines and ^L characters." - (if (and doc-string-elt (stringp (nth doc-string-elt autoload))) - ;; We need to hack the printing because the doc-string must be - ;; printed specially for make-docfile (sigh). - (let* ((p (nthcdr (1- doc-string-elt) autoload)) - (elt (cdr p)) - (start-string (format "\n%s(" margin))) - (setcdr p nil) - (princ start-string outbuf) - ;; XEmacs change: don't let ^^L's get into - ;; the file or sorting is hard. - (let ((print-escape-newlines t) - (p (save-excursion - (set-buffer outbuf) - (point))) + (cond + ;; If the form is a sequence, recurse. + ((eq (car form) 'progn) + (mapcar #'(lambda (x) (autoload-print-form x outbuf margin)) + (cdr form))) + ;; Symbols at the toplevel are meaningless. + ((symbolp form) nil) + (t + (let ((doc-string-elt (get (car-safe form) 'doc-string-elt))) + (if (and doc-string-elt (stringp (nth doc-string-elt form))) + ;; We need to hack the printing because the doc-string must be + ;; printed specially for make-docfile (sigh). + (let* ((p (nthcdr (1- doc-string-elt) form)) + (elt (cdr p)) + (start-string (format "\n%s(" margin))) + (setcdr p nil) + (princ start-string outbuf) + ;; XEmacs change: don't let ^^L's get into + ;; the file or sorting is hard. + (let ((print-escape-newlines t) + ;;#### FSF 21.2 (print-escape-nonascii t) + (p (point outbuf)) + p2) + (mapcar #'(lambda (elt) + (prin1 elt outbuf) + (princ " " outbuf)) + form) + (with-current-buffer outbuf + (setq p2 (point-marker)) + (goto-char p) + (save-match-data + (while (search-forward "\^L" p2 t) + (delete-char -1) + (insert "\\^L"))) + (goto-char p2))) + (princ "\"\\\n" outbuf) + (let ((begin (point outbuf))) + (princ (substring (prin1-to-string (car elt)) 1) outbuf) + ;; Insert a backslash before each ( that appears at the beginning + ;; of a line in the doc string. + (with-current-buffer outbuf + (save-excursion + (while (search-backward start-string begin t) + (forward-char 1) + (insert "\\")))) + (if (null (cdr elt)) + (princ ")" outbuf) + (princ " " outbuf) + (princ (substring (prin1-to-string (cdr elt)) 1) outbuf)) + (terpri outbuf) + (princ margin outbuf))) + ;; XEmacs change: another ^L hack + (let ((p (point outbuf)) + (print-escape-newlines t) + ;;#### FSF 21.2 (print-escape-nonascii t) p2) - (mapcar #'(lambda (elt) - (prin1 elt outbuf) - (princ " " outbuf)) - autoload) - (save-excursion - (set-buffer outbuf) + (print form outbuf) + (with-current-buffer outbuf (setq p2 (point-marker)) (goto-char p) (save-match-data (while (search-forward "\^L" p2 t) (delete-char -1) (insert "\\^L"))) - (goto-char p2))) - (princ "\"\\\n" outbuf) - (let ((begin (save-excursion - (set-buffer outbuf) - (point)))) - (princ (substring (prin1-to-string (car elt)) 1) outbuf) - ;; Insert a backslash before each ( that appears at the beginning - ;; of a line in the doc string. - (save-excursion - (set-buffer outbuf) - (save-excursion - (while (search-backward start-string begin t) - (forward-char 1) - (insert "\\")))) - (if (null (cdr elt)) - (princ ")" outbuf) - (princ " " outbuf) - (princ (substring (prin1-to-string (cdr elt)) 1) outbuf)) - (terpri outbuf) - (princ margin outbuf))) - ;; XEmacs change: another ^L hack - (let ((p (save-excursion - (set-buffer outbuf) - (point))) - (print-escape-newlines t) - p2) - (print autoload outbuf) - (save-excursion - (set-buffer outbuf) - (setq p2 (point-marker)) - (goto-char p) - (save-match-data - (while (search-forward "\^L" p2 t) - (delete-char -1) - (insert "\\^L"))) - (goto-char p2))))) + (goto-char p2)))))))) ;;; Forms which have doc-strings which should be printed specially. ;;; A doc-string-elt property of ELT says that (nth ELT FORM) is ;;; the doc-string in FORM. ;;; -;;; defvar and defconst should be also be marked in this way. There is -;;; no interference from make-docfile, which only processes those files -;;; that are loaded into the dumped Emacs, and those files should -;;; never have anything autoloaded here. Problems only occur with files +;;; There used to be the following note here: +;;; ;;; Note: defconst and defvar should NOT be marked in this way. +;;; ;;; We don't want to produce defconsts and defvars that +;;; ;;; make-docfile can grok, because then it would grok them twice, +;;; ;;; once in foo.el (where they are given with ;;;###autoload) and +;;; ;;; once in loaddefs.el. +;;; +;;; Counter-note: Yes, they should be marked in this way. +;;; make-docfile only processes those files that are loaded into the +;;; dumped Emacs, and those files should never have anything +;;; autoloaded here. The above-feared problem only occurs with files ;;; which have autoloaded entries *and* are processed by make-docfile; ;;; there should be no such files. @@ -597,11 +789,18 @@ (put 'defun 'doc-string-elt 3) (put 'defun* 'doc-string-elt 3) (put 'defvar 'doc-string-elt 3) +(put 'defcustom 'doc-string-elt 3) (put 'defconst 'doc-string-elt 3) (put 'defmacro 'doc-string-elt 3) (put 'defmacro* 'doc-string-elt 3) -(put 'define-skeleton 'doc-string-elt 3) +(put 'defsubst 'doc-string-elt 3) +(put 'define-skeleton 'doc-string-elt 2) (put 'define-derived-mode 'doc-string-elt 4) +(put 'easy-mmode-define-minor-mode 'doc-string-elt 2) +(put 'define-minor-mode 'doc-string-elt 2) +(put 'define-generic-mode 'doc-string-elt 7) +;; defin-global-mode has no explicit docstring. +(put 'easy-mmode-define-global-mode 'doc-string-elt 1000) (defun autoload-trim-file-name (file) "Returns relative pathname of FILE including the last directory. @@ -615,6 +814,27 @@ ;; #### is this a good idea? "\\\\" "/")) +(defun autoload-read-section-header () + "Read a section header form. +Since continuation lines have been marked as comments, +we must copy the text of the form and remove those comment +markers before we call `read'." + (save-match-data + (let ((beginning (point)) + string) + (forward-line 1) + (while (looking-at generate-autoload-section-continuation) + (forward-line 1)) + (setq string (buffer-substring beginning (point))) + (with-current-buffer (get-buffer-create " *autoload*") + (erase-buffer) + (insert string) + (goto-char (point-min)) + (while (search-forward generate-autoload-section-continuation nil t) + (replace-match " ")) + (goto-char (point-min)) + (read (current-buffer)))))) + ;;;###autoload (defun update-file-autoloads (file) "Update the autoloads for FILE in `generated-autoload-file' @@ -633,16 +853,42 @@ (trim-name (autoload-trim-file-name file)) section-begin form) (save-excursion + ;; FSF has: [[ We want to get a value for generated-autoload-file + ;; from the local variables section if it's there. ]] Not + ;; applicable in XEmacs, since we always keep the autoloads + ;; up-to-date. + + ;; #### FSF 21.2 adds: [[ We must read/write the file without any + ;; code conversion, but still decode EOLs. ]] Not clear if we need + ;; this. --ben + ;; (let ((coding-system-for-read 'raw-text)) (let ((find-file-hooks nil)) (set-buffer (or (get-file-buffer generated-autoload-file) (find-file-noselect generated-autoload-file)))) + ;; FSF 21.2 says: + + ;; [[ This is to make generated-autoload-file have Unix EOLs, so + ;; that it is portable to all platforms. ]] + ;; (setq buffer-file-coding-system 'raw-text-unix)) + ;; Not applicable in XEmacs, since we always keep the autoloads + ;; up-to-date and recompile when we build. + + ;; FSF 21.2: [not applicable to XEmacs] +; (or (> (buffer-size) 0) +; (error "Autoloads file %s does not exist" buffer-file-name)) +; (or (file-writable-p buffer-file-name) +; (error "Autoloads file %s is not writable" buffer-file-name)) + + ;; NOTE: The rest of this function is totally changed from FSF. + ;; Hence, not synched. + ;; Make sure we can scribble in it. (setq buffer-read-only nil) ;; First delete all sections for this file. (goto-char (point-min)) (while (search-forward generate-autoload-section-header nil t) (setq section-begin (match-beginning 0)) - (setq form (read (current-buffer))) + (setq form (autoload-read-section-header)) (when (string= (nth 2 form) load-name) (search-forward generate-autoload-section-trailer) (delete-region section-begin (point)))) @@ -651,7 +897,7 @@ (block find-insertion-point (goto-char (point-min)) (while (search-forward generate-autoload-section-header nil t) - (setq form (read (current-buffer))) + (setq form (autoload-read-section-header)) (when (string< trim-name (nth 3 form)) ;; Found alphabetically correct insertion point (goto-char (match-beginning 0)) @@ -661,65 +907,15 @@ (goto-char (point-max)))) ; Append. ;; Add in new sections for file - (generate-file-autoloads file)) + (funcall generate-autoload-function file)) (when (interactive-p) (save-buffer))))) -;;;###autoload -(defun update-autoloads-here () - "Update sections of the current buffer generated by `update-file-autoloads'." - (interactive) - (let ((generated-autoload-file (buffer-file-name))) - (save-excursion - (goto-char (point-min)) - (while (search-forward generate-autoload-section-header nil t) - (let* ((form (condition-case () - (read (current-buffer)) - (end-of-file nil))) - (file (nth 3 form))) - ;; XEmacs change: if we can't find the file as specified, look - ;; around a bit more. - (cond ((and (stringp file) - (or (get-file-buffer file) - (file-exists-p file)))) - ((and (stringp file) - (save-match-data - (let ((loc (locate-file (file-name-nondirectory file) - load-path))) - (if (null loc) - nil - (setq loc (expand-file-name - (autoload-trim-file-name loc) - "..")) - (if (or (get-file-buffer loc) - (file-exists-p loc)) - (setq file loc) - nil)))))) - (t - (setq file - (if (y-or-n-p - (format - "Can't find library `%s'; remove its autoloads? " - (nth 2 form) file)) - t - (condition-case () - (read-file-name - (format "Find `%s' load file: " - (nth 2 form)) - nil nil t) - (quit nil)))))) - (if file - (let ((begin (match-beginning 0))) - (search-forward generate-autoload-section-trailer) - (delete-region begin (point)))) - (if (stringp file) - (generate-file-autoloads file))))))) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Utilities for batch updates ;;;###autoload -(defun autoload-update-directory-autoloads () +(defun batch-update-directory-autoloads () "Update the autoloads for a directory, using a specified feature prefix. Must be used only with -batch. The feature prefix and directory to update are taken from the first and second elements of `command-line-args-left', @@ -731,15 +927,32 @@ #### The API and semantics of this function are subject to change." (unless noninteractive - (error "autoload-batch-update-autoloads: may be used only with -batch")) - (let* ((autoload-feature-prefix (car command-line-args-left)) - (dir (cadr command-line-args-left)) - (generated-autoload-file (expand-file-name autoload-file-name dir))) - (update-autoload-files (list dir) t t) - (setq command-line-args-left (cddr command-line-args-left)))) + (error "batch-update-directory-autoloads: may be used only with -batch")) + (update-autoload-files (list (cadr command-line-args-left)) + (car command-line-args-left) nil t) + (setq command-line-args-left (cddr command-line-args-left))) ;;;###autoload -(defun update-autoload-files (files-or-dirs &optional all-into-one-file force) +(defun batch-update-directory-custom-defines () + "Update the custom defines for a directory, using a specified feature prefix. +Must be used only with -batch. The feature prefix and directory to update +are taken from the first and second elements of `command-line-args-left', +respectively, and they are then removed from `command-line-args-left'. + +Runs `update-file-autoloads' on each file in the given directory. Always +rewrites the autoloads file, even if unchanged. Makes a feature name by +applying `autoload-make-feature-name' to the specified feature prefix. + +#### The API and semantics of this function are subject to change." + (unless noninteractive + (error "batch-update-directory-custom-defines: may be used only with -batch")) + (update-custom-define-files (list (cadr command-line-args-left)) + (car command-line-args-left) nil t) + (setq command-line-args-left (cddr command-line-args-left))) + +;;;###autoload +(defun update-autoload-files (files-or-dirs feature-prefix + &optional into-file force) "Update all the autoload files associated with FILES-OR-DIRS. FILES-OR-DIRS is a list of files and/or directories to be processed. @@ -747,98 +960,144 @@ each element of FILES-OR-DIRS. Fixup code testing for the autoload file's feature and to provide the feature is added. -If optional ALL-INTO-ONE-FILE is non-`nil', `generated-autoload-file' -should be set to the name of an autoload file and all autoloads will be -placed in that file. `autoload-feature-prefix' should be set to an -appropriate prefix which will be concatenated with \"-autoloads\" to -produce the feature name. Otherwise the appropriate autoload file for -each file or directory (located in that directory, or in the directory of -the specified file) will be updated with the directory's or file's -autoloads and the protective forms will be added, and the files will be -saved. Use of the default here is unreliable, and therefore deprecated. +If optional INTO-FILE is non-`nil', it should specify a file into which +the autoloads will be placed. Otherwise, the autoloads will be placed into +a file named `auto-autoloads.el' in the directory of each element in +FILES-OR-DIRS. + +FEATURE-PREFIX should be set to an appropriate prefix which will +be concatenated with \"-autoloads\" to produce the feature name. Otherwise +the appropriate autoload file for each file or directory (located in that +directory, or in the directory of the specified file) will be updated with +the directory's or file's autoloads and the protective forms will be added, +and the files will be saved. Use of the default here is unreliable, and +therefore deprecated. Note that if some of FILES-OR-DIRS are directories, recursion goes only one level deep. If FORCE is non-nil, always save out the autoload files even if unchanged." + (or (listp files-or-dirs) (setq files-or-dirs (list files-or-dirs))) (let ((defdir (directory-file-name default-directory)) ;; value for all-into-one-file - (autoload-feature-name (autoload-make-feature-name)) - (enable-local-eval nil)) ; Don't query in batch mode. + (autoload-feature-name (autoload-make-feature-name feature-prefix)) + (enable-local-eval nil) ; Don't query in batch mode. + (autoload-feature-prefix feature-prefix) + ;; protect from change + (generated-autoload-file generated-autoload-file)) (dolist (arg files-or-dirs) (setq arg (expand-file-name arg defdir)) (cond ((file-directory-p arg) + (setq generated-autoload-file + (or into-file (expand-file-name autoload-file-name arg))) (message "Updating autoloads for directory %s..." arg) - (update-autoloads-from-directory arg)) + (let ((simple-dir (file-name-as-directory + (file-name-nondirectory + (directory-file-name arg)))) + (enable-local-eval nil)) + (save-excursion + (let ((find-file-hooks nil)) + (set-buffer (find-file-noselect generated-autoload-file))) + (goto-char (point-min)) + (while (search-forward generate-autoload-section-header nil t) + (let* ((begin (match-beginning 0)) + (form (autoload-read-section-header)) + (file (nth 3 form))) + (when (and (stringp file) + (string= (file-name-directory file) simple-dir) + (not (file-exists-p + (expand-file-name + (file-name-nondirectory file) arg)))) + ;; Remove the obsolete section. + (search-forward generate-autoload-section-trailer) + (delete-region begin (point))))) + ;; Update or create autoload sections for existing files. + (mapcar 'update-file-autoloads + (directory-files arg t "^[^=].*\\.\\(el\\|c\\)$"))))) ((file-exists-p arg) + (setq generated-autoload-file + (or into-file (expand-file-name autoload-file-name + (file-name-directory arg)))) (update-file-autoloads arg)) (t (error "No such file or directory: %s" arg))) - (when (not all-into-one-file) + (when (not into-file) (autoload-featurep-protect-autoloads (autoload-make-feature-name - (file-name-nondirectory (directory-file-name arg)))) + (or feature-prefix + (file-name-nondirectory (directory-file-name arg))))) (if force (set-buffer-modified-p t (find-file-noselect generated-autoload-file))))) - (when all-into-one-file + (when into-file (autoload-featurep-protect-autoloads autoload-feature-name) (if force (set-buffer-modified-p - t (find-file-noselect generated-autoload-file)))) + t (find-file-noselect into-file)))) (save-some-buffers t) )) ;;;###autoload -(defun update-autoloads-from-directory (dir) - "Update `generated-autoload-file' with all the current autoloads from DIR. -This runs `update-file-autoloads' on each .el and .c file in DIR. -Obsolete autoload entries for files that no longer exist are deleted. -Note that, if this function is called from `batch-update-directory', -`generated-autoload-file' was rebound in that function. - -You don't really want to be calling this function. Try using -`update-autoload-files' instead." - (interactive "DUpdate autoloads for directory: ") - (setq dir (expand-file-name dir)) - (let ((simple-dir (file-name-as-directory - (file-name-nondirectory - (directory-file-name dir)))) - (enable-local-eval nil)) - (save-excursion - (let ((find-file-hooks nil)) - (set-buffer (find-file-noselect generated-autoload-file))) - (goto-char (point-min)) - (while (search-forward generate-autoload-section-header nil t) - (let* ((begin (match-beginning 0)) - (form (condition-case () - (read (current-buffer)) - (end-of-file nil))) - (file (nth 3 form))) - (when (and (stringp file) - (string= (file-name-directory file) simple-dir) - (not (file-exists-p - (expand-file-name - (file-name-nondirectory file) dir)))) - ;; Remove the obsolete section. - (search-forward generate-autoload-section-trailer) - (delete-region begin (point))))) - ;; Update or create autoload sections for existing files. - (mapcar 'update-file-autoloads - (directory-files dir t "^[^=].*\\.\\(el\\|c\\)$")) - (unless noninteractive - (save-buffer))))) +(defun update-custom-define-files (files-or-dirs feature-prefix + &optional into-file force) + "Update all the custom-define files associated with FILES-OR-DIRS. +Works just like `update-file-autoloads'." + (let* ((autoload-feature-suffix "-custom-defines") + (autoload-file-name "custom-defines.el") + (generate-autoload-function #'generate-custom-defines)) + (update-autoload-files files-or-dirs feature-prefix into-file force))) (defun autoload-featurep-protect-autoloads (sym) (save-excursion (set-buffer (find-file-noselect generated-autoload-file)) (goto-char (point-min)) - (if (and (not (= (point-min) (point-max))) - (not (looking-at ";;; DO NOT MODIFY THIS FILE"))) - (progn - (insert ";;; DO NOT MODIFY THIS FILE\n") - (insert "(if (featurep '" sym ")") - (insert " (error \"Feature " sym " already loaded\"))\n") - (goto-char (point-max)) - (insert "\n(provide '" sym ")\n"))))) + (cond ((eq (point-min) (point-max)) nil) + ;; if there's some junk in the file but no sections, just + ;; delete everything. the junk might be stuff inserted by + ;; an older version of this function. + ((not (search-forward generate-autoload-section-header nil t)) + (delete-region (point-min) (point-max))) + (t + (goto-char (point-min)) + (when (looking-at ";;; DO NOT MODIFY THIS FILE") + (delete-region (point-min) + (progn + (search-forward generate-autoload-section-header) + (match-beginning 0)))) + ;; Determine and set the coding system for the file if under Mule. + ;; If there are any extended characters in the input file, use + ;; `escape-quoted' to make sure that both binary and extended + ;; characters are output properly and distinguished properly. + ;; Otherwise, use `raw-text' for maximum portability with non-Mule + ;; Emacsen. + (if (or (featurep '(not mule)) ;; Don't scan if no Mule support + (progn + (goto-char (point-min)) + ;; mrb- There must be a better way than skip-chars-forward + (skip-chars-forward (concat (char-to-string 0) "-" + (char-to-string 255))) + (eq (point) (point-max)))) + (setq buffer-file-coding-system 'raw-text-unix) + (setq buffer-file-coding-system 'escape-quoted)) + (goto-char (point-min)) + (insert ";;; DO NOT MODIFY THIS FILE") + ;; NOTE: XEmacs prior to 21.5.12 or so had a bug in that it + ;; recognized only one of the two magic-cookie styles (the -*- kind) + ;; in find-file, but both of them in load. We go ahead and put both + ;; in, just to be safe. + (when (eq buffer-file-coding-system 'escape-quoted) + (insert " -*- coding: escape-quoted; -*- +\(or (featurep 'mule) (error \"Loading this file requires Mule support\")) +;;;###coding system: escape-quoted")) + (insert "\n(if (featurep '" sym ")") + (insert " (error \"Feature " sym " already loaded\"))\n") + (goto-char (point-max)) + (save-excursion + (forward-line -1) + (when (looking-at "(provide") + (delete-region (point) (point-max)))) + (unless (bolp) (insert "\n")) + (unless (eq (char-before (1- (point))) ?\^L) + (insert "\^L\n")) + (insert "(provide '" sym ")\n"))))) (defun autoload-make-feature-name (&optional prefix) "Generate the feature name to protect this auto-autoloads file from PREFIX. @@ -864,19 +1123,23 @@ (file-name-directory generated-autoload-file)))) (t (error 'invalid-argument "Could not compute a feature name"))) - "-autoloads")) + autoload-feature-suffix)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Deprecated entry points ;; A grep of the core and packages shows use of `batch-update-autoloads' ;; by XEmacs.rules, pcomplete, eshell, oort-gnus; `batch-update-directory' -;; by liece. +;; by liece. The other two entry points (`batch-update-one-directory', +;; `batch-force-update-one-directory') were not used at all. +;; +;; All except the first are now history. liece has been updated. +;; XEmacs.rules has been updated. The others will be, eventually. + +;; There don't seem to be very many packages that use the first one (the +;; "all-into-one-file" variety), and do they actually rely on this +;; functionality? --ben -;; #### these entry points below are a big mess, especially the -;; first two. there don't seem to be very many packages that use the -;; first one (the "all-into-one-file" variety), and do they actually -;; rely on this functionality? --ben ;; but XEmacs.rules does, though maybe it doesn't "rely" on it, and ;; modules do now, and that relies on it. --sjt @@ -891,59 +1154,15 @@ on the command line." (unless noninteractive (error "batch-update-autoloads is to be used only with -batch")) - (update-autoload-files command-line-args-left t) + (update-autoload-files command-line-args-left autoload-feature-prefix nil t) (kill-emacs 0)) -;;;###autoload -(defun batch-update-directory () - "Update the autoloads for the directories on the command line. -Runs `update-file-autoloads' on each file in the given directory, and must -be used only with -batch. - -Uses and removes the first element of `command-line-args-left'." - (unless noninteractive - (error "batch-update-directory is to be used only with -batch")) - (update-autoload-files command-line-args-left) - ;; (kill-emacs 0) - (setq command-line-args-left nil)) - -;;;###autoload -(defun batch-update-one-directory () - "Update the autoloads for a single directory on the command line. -Runs `update-file-autoloads' on each file in the given directory, and must -be used only with -batch." - (unless noninteractive - (error "batch-update-one-directory is to be used only with -batch")) - (let ((arg (car command-line-args-left))) - (setq command-line-args-left (cdr command-line-args-left)) - (update-autoload-files (list arg)))) - -;;;###autoload -(defun batch-force-update-one-directory () - "Update the autoloads for a single directory on the command line. -Runs `update-file-autoloads' on each file in the given directory, and must -be used only with -batch. Always rewrites the autoloads file, even if -unchanged. - -Uses and removes the first element of `command-line-args-left'." - (unless noninteractive - (error "batch-force-update-directory is to be used only with -batch")) - (let ((arg (car command-line-args-left))) - (setq command-line-args-left (cdr command-line-args-left)) - (update-autoload-files (list arg) nil t))) - ;; Declare obsolescence (make-obsolete-variable 'autoload-target-directory "Don't use this. Bind `generated-autoload-file' to an absolute path.") (make-obsolete 'batch-update-autoloads 'autoload-update-directory-autoloads) -(make-obsolete 'batch-update-directory - 'autoload-update-directory-autoloads) -(make-obsolete 'batch-update-one-directory - 'autoload-update-directory-autoloads) -(make-obsolete 'batch-force-update-one-directory - 'autoload-update-directory-autoloads) (provide 'autoload) diff --text -u 'xemacs-21.5.18/lisp/behavior-defs.el' 'xemacs-21.5.19/lisp/behavior-defs.el' Index: ./lisp/behavior-defs.el --- ./lisp/behavior-defs.el Fri Mar 15 16:43:18 2002 +++ ./lisp/behavior-defs.el Thu Feb 3 14:26:41 2005 @@ -1,6 +1,6 @@ ;;; behavior-defs.el --- definitions of specific behaviors -;; Copyright (C) 2000, 2001, 2002 Ben Wing. +;; Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. ;; Author: Ben Wing ;; Maintainer: XEmacs Development Team @@ -31,475 +31,27 @@ ;;; Commentary: -;; This file will be dumped with XEmacs. +;; This file is dumped with XEmacs. ;;; Code: -(require 'behavior) - -(define-behavior 'scroll-in-place -"This package provides improved vertical scrolling commands for XEmacs. -These new commands offer the following features: - -+ When a scrolling command is executed, XEmacs tries to keep point as - close as possible to its original window position (window line and - column). This is what \"scroll in place\" means: point stays \"in place\" - within the window. (There are times when point must be moved from its - original window position in order to execute the scroll; see below.) - - The variable `scroll-in-place', which is true by default, determines - whether or not the standard XEmacs scrolling commands (`scroll-down', - `scroll-up', `scroll-other-window-down', and `scroll-other-window') use - the \"in place\" features listed here. When `scroll-in-place' is `nil' - the standard XEmacs scrolling commands essentially just call the - original versions of themselves. (Note that even when `scroll-in-place' - is `nil' the new versions of `scroll-down' and `scroll-up' have slightly - different behavior when a minibuffer window is the selected window. See - below.) - - It is possible to turn off (or turn on) \"in place\" scrolling for certain - buffers by making buffer-local bindings of the variable `scroll-in- - place' for those buffers. The variable `scroll-in-place' is not usually - buffer-local, but you can make it so if you desire. - -+ Because the improved scrolling commands keep point at its original - window position, these scrolling commands are \"reversible.\" The - `scroll-up' command undoes the effect of the immediately previous - `scroll-down' command (if any) and vice versa. In other words, if you - scroll up and then immediately scroll back down, the window config- - uration is restored to its exact original state. This allows you to - browse through a buffer more easily, as you can always get back to the - original configuration. - - Note, however, that the improved scrolling commands are guaranteed to be - reversible only if there are no intervening non-scrolling commands. - Also, if you give a prefix argument to a scrolling command (in order to - specify the number of lines to scroll by), previous scrolling commands - may no longer be reversible. More specifically, if the new prefix - argument has a different magnitude than the previous scrolling distance, - then any previous scrolling commands are not reversible. The new prefix - argument takes precedence. - - You might find it useful to think of the scrolling commands as forming - \"chains.\" A scrolling command either starts or continues a chain. By - issuing a non-scrolling command or by changing the number of lines to be - scrolled, you break the chain. (Note that simply changing the scrolling - direction won't break the chain; changing the absolute number of lines - to be scrolled is what breaks the chain.) Scrolling commands are - guaranteed to be reversible only within the current chain. Hopefully - that's clear enough. - -+ When a scrolling command is given a prefix argument (which specifies the - number of lines to scroll by), then that argument becomes the default - scrolling distance for all immediately subsequent scrolling commands. - This means that you can easily set the scrolling distance for a chain - of scrolling commands. Note that a new prefix argument or any non- - scrolling command breaks the chain (as described above), and any further - scrolling commands will use the usual defaults (or the prefix argument - you specify at that time, of course). - - However, there are cases in which one doesn't want the current scrolling - command to use the default scrolling distance that was set by the - previous scrolling command. For example, suppose that you had special - commands that scrolled one line up and one line down. When you invoke - one of these commands, the \"in place\" scrolling routines set the default - scrolling distance to be just one line. Now suppose that you use one of - your special commands and then immediately invoke `scroll-up' (`C-v'), - expecting it to scroll by a near windowful of text. You would be - disappointed --- because the previous command set the default scrolling - distance to be just one line, `scroll-up' just scrolls by one line. - - To solve this problem, \"scroll-in-place\" allows you to divide scrolling - commands into separate \"groups.\" Commands in a group can only form - chains with (and therefore, inherit defaults from) commands in the same - group. (Note that no command can be in more than one group.) If you - invoke a scrolling command that is not in the same group as that of the - immediately previous scrolling command, then the previous chain is - broken and you start a new chain --- with a new set of defaults. - - So to solve the problem described above, you could put your one-line - scrolling commands in their own group. Once that is done, the standard - scrolling commands will not form chains with your one-line scrolling - commands, and therefore will not use the default scrolling distance set - by those commands. Problem solved! - - By default, all \"in place\" scrolling commands are in a single group. If - you want to partition some commands into separate groups, you must do - that yourself *before* any \"in place\" commands are invoked. For more - information about grouping commands, see the documentation for the - variables `scroll-command-groups' and `scroll-default-command-group'. - -+ The improved scrolling commands will avoid displaying empty lines past - the end of the buffer when possible. In other words, just as you can't - see \"dead space\" before the beginning of the buffer text, the new - scrolling commands try to avoid displaying \"dead space\" past the end of - the buffer text. This behavior is somewhat configurable; see the - documentation for the variable `scroll-allow-blank-lines-past-eob'. - - Dead space will be displayed if it is necessary in order to make a - previous scrolling action reversible, however. - -+ If the scrolling commands cannot keep point at its initial window - position (because a buffer boundary is on screen and the window can't be - scrolled as far as necessary to keep point at the right place), point is - allowed to temporarily stray from its initial window position. That is, - point moves the correct number of window lines, even if it means that it - has to stray from its desired window position. This straying is undone - when (and if) the scrolling action is reversed. - -+ If a scrolling command tries to move point past a buffer boundary, point - is instead moved to the boundary (the beginning or the end of the buffer - as appropriate) and an appropriate message is displayed. This motion is - reversible, of course. - - However, if point was already at the buffer boundary when the scrolling - command was invoked, the command signals an appropriate error instead. - -+ When a minibuffer window is the selected window, the new versions of - `scroll-up' and `scroll-down' either scroll the window in the variable - `minibuffer-scroll-window' (which is usually the window of completions) - or the `next-window' if there is no `minibuffer-scroll-window'. This is - usually much more useful than scrolling the minibuffer itself. (Note - that this feature is available even when the variable `scroll-in-place' - is `nil'.) - -+ When a scrolling command is scrolling a window other than the selected - window, it will signal an appropriate buffer boundary error if the - window cannot be scrolled (because the appropriate buffer boundary is - already visible). This means that an error is signalled even in cases - that would be allowed (by \"straying\" point or by moving it to the buffer - boundary) if the window were selected. - - (If an error were not signalled in these cases, then there would be many - cases in which the last scroll in a particular direction would appear to - do nothing because only the point position would change --- the - displayed text would stay the same! To avoid these cases the scrolling - commands signal boundary errors \"prematurely\" when the window to be - scrolled is not selected.)" - :short-doc "Keep cursor on same line when scrolling" - :require 'scroll-in-place - :enable #'turn-on-scroll-in-place - :disable #'turn-off-scroll-in-place) - -(define-behavior 'mouse-avoidance -"For those who are annoyed by the mouse pointer obscuring text, -this mode moves the mouse pointer - either just a little out of -the way, or all the way to the corner of the frame. - -Customize `mouse-avoidance-mode' to one of the symbols `banish', -`exile', `jump', `animate', `cat-and-mouse', `proteus', or `none'. - -Effects of the different modes: - * banish: Move the mouse to the upper-right corner on any keypress. - * exile: Move the mouse to the corner only if the cursor gets too close, - and allow it to return once the cursor is out of the way. - * jump: If the cursor gets too close to the mouse, displace the mouse - a random distance & direction. - * animate: As `jump', but shows steps along the way for illusion of motion. - * cat-and-mouse: Same as `animate'. - * proteus: As `animate', but changes the shape of the mouse pointer too. - -Whenever the mouse is moved, the frame is also raised. - -\(see `mouse-avoidance-threshold' for definition of \"too close\", -and `mouse-avoidance-nudge-dist' and `mouse-avoidance-nudge-var' for -definition of \"random distance\".)" - :short-doc "Keep mouse away from cursor" - :enable #'(lambda () - (mouse-avoidance-mode 'animate)) - :disable #'(lambda () - (mouse-avoidance-mode 'none))) - -(define-behavior 'jka-compr - "This package implements low-level support for reading, writing, -and loading compressed files. It hooks into the low-level file -I/O functions (including write-region and insert-file-contents) so -that they automatically compress or uncompress a file if the file -appears to need it (based on the extension of the file name). -Packages like Rmail, VM, GNUS, and Info should be able to work -with compressed files without modification." - :short-doc "Transparently handle compressed files" - :enable #'jka-compr-install - :disable #'jka-compr-uninstall) - -(define-behavior 'efs -"EFS is a system for transparent file-transfer between remote VMS, CMS, -MTS, MVS, Twenex, Explorer (the last two are Lisp machines), TOPS-20, -DOS (running the Distinct, Novell, FTP software, NCSA, Microsoft in both -unix and DOS mode, Super TCP, and Hellsoft FTP servers), Windows NT -\(running the Microsoft or Hummingbird ftp servers), Unix descriptive -listings (dl), KA9Q, OS/2 hosts using FTP. This means that you can edit, -copy and otherwise manipulate files on any machine you have access to -from within Emacs as if it were a local file. EFS works by introducing -an extended filename syntax, and overloading functions such as -`insert-file-contents' so that accessing a remote file causes -appropriate commands to be sent to an FTP process. - -The syntax to use is like this: - -\(for anonymous:) /ftp.xemacs.org:/pub/xemacs/ -\(for non-anonymous:) /ben@gwyn.tux.org:/etc/mail/xemacs/aliases-xemacs - -You can specify either a file or a directory (in the latter case, -Dired will be brought up). All operations in XEmacs on such files -should work exactly as on any other files, modulo the additional -slowness." - :short-doc "Transparent file access over FTP" - :require 'efs-auto - :enable #'ignore - ;; can't :disable - ) - - -(define-behavior 'resize-minibuffer - "When this behavior is enabled, the minibuffer is dynamically resized to -contain the entire region of text put in it as you type. - -The maximum height to which the minibuffer can grow is controlled by the -variable `resize-minibuffer-window-max-height'. - -The variable `resize-minibuffer-window-exactly' determines whether the -minibuffer window should ever be shrunk to make it no larger than needed to -display its contents. - -When using a window system, it is possible for a minibuffer to be the sole -window in a frame. Since that window is already its maximum size, the only -way to make more text visible at once is to increase the size of the frame. -The variable `resize-minibuffer-frame' controls whether this should be -done. The variables `resize-minibuffer-frame-max-height' and -`resize-minibuffer-frame-exactly' are analogous to their window -counterparts." - :short-doc "Resize minibuffer automatically" - :enable #'(lambda () - (resize-minibuffer-mode 1)) - :disable #'(lambda () - (resize-minibuffer-mode -1))) - -(define-behavior 'func-menu - "Suppose you have a file with a lot of functions in it. Well, this -package makes it easy to jump to any of those functions. The names of -the functions in the current buffer are automatically put into menubar -menu, you select one of the function-names and the point is moved to -that very function. The mark is pushed on the mark-ring, so you can -easily go back to where you were. Alternatively, you can use enter the -name of the desired function via the minibuffer which offers -completing read input. In addition, the name of the function before -point is optionally displayed in the modeline." - :short-doc "Add a menu of defined functions" - :require 'func-menu - :enable #'(lambda () - (add-hook 'find-file-hooks 'fume-add-menubar-entry) - (mapc #'(lambda (buffer) - (with-current-buffer buffer - (setq fume-display-in-modeline-p t) - (fume-add-menubar-entry))) - (buffer-list))) - :disable #'(lambda () - (remove-hook 'find-file-hooks 'fume-add-menubar-entry) - (fset 'widen (symbol-function 'fume-widen)) - (fset 'narrow-to-region (symbol-function 'narrow-to-region)) - (mapc #'(lambda (buffer) - (with-current-buffer buffer - (fume-remove-menubar-entry) - (setq fume-display-in-modeline-p nil) - (fume-remove-post-command-hook - 'fume-tickle-modeline) - (fume-remove-post-command-hook - 'fume-maybe-install-modeline-feature) - (fume-remove-post-command-hook - 'fume-rescan-buffer-trigger))) - (buffer-list)))) - -(define-behavior 'mwheel - "This code enables the use of the infamous 'wheel' on the new -crop of mice. Under XFree86 and the XSuSE X Servers, the wheel -events are sent as button4/button5 events, which are automatically -set up to do scrolling in the expected way. The actual way that the -scrolling works can be controlled by `mwheel-scroll-amount' and -`mwheel-follow-mouse'." - :short-doc "Mouse wheel support for X Windows" - :enable 'mwheel-install) - -(define-behavior 'recent-files -"Recent-files adds the menu \"Recent Files\" (or whatever name you -choose, see \"Customization:\" below) to Emacs's menubar. Its -entries are the files (and directories) that have recently been -opened by Emacs. You can open one of these files again by -selecting its entry in the \"Recent Files\" menu. The list of file -entries in this menu is preserved from one Emacs session to -another. You can prevent Emacs from saving this list by selecting -\"Don't save recent-files list on exit\" from the menu. If you have -disabled saving, you can re-enable it by selecting \"Save -recent-files list on exit\". - -The menu has permanent and non-permanent entries. Permanent -entries are marked with an asterisk in front of the filename. The -non-permanent entries are hidden in a submenu. - -Each time you open a file in Emacs, it is added as a non-permanent -entry to the menu. The value of `recent-files-number-of-entries' -determines how many non-permanent entries are held in the -menu. When the number of non-permanent entries reaches this value, -the least recently added non-permanent entry is removed from the -menu when another non-permanent entry is added. It is not removed -from the list, though; it may reappear when entries are deleted -from the list. The number of entries saved to disk is the value of -the variable `recent-files-number-of-saved-entries'. - -Permanent entries are not removed from the menu. You can make a -file entry permanent by selecting \"Make <buffer> permanent\" (where -<buffer> is the name of the current buffer) when the current -buffer holds this file. \"Make <buffer> non-permanent\" makes the -file entry of the current buffer non-permanent. - -The command \"Kill buffer <buffer> and delete entry\" is handy when -you have accidently opened a file but want to keep neither the -buffer nor the entry. - -You can erase the list of non-permanent entries by selecting -\"Erase non-permanent entries\" from the menu. - -Customization: - -There are lots of variables to control the behaviour of -recent-files. You do not have to change any of them if you like it -as it comes out of the box. However, you may want to look at these -options to make it behave different. - -`recent-files-number-of-entries' - Controls how many non-permanent entries are shown in the - recent-files list. The default is 15. - -`recent-files-number-of-saved-entries' - Controls how many non-permanent entries are saved to disk when - Emacs exits or recent-files-save-the-list is called. The - default is 50. - -`recent-files-save-file' - The name of the file where the recent-files list is saved - between Emacs session. You probably don't need to change this. - The default is \".recent-files.el\" in your home directory. - -`recent-files-dont-include' - A list of regular expressions for files that should not be - included into the recent-files list. This list is empty by - default. For instance, a list to exclude all .newsrc - files, all auto-save-files, and all files in the /tmp - directory (but not the /tmp directory itself) would look - like this: - (setq recent-files-dont-include - '(\"/\\.newsrc\" \"~$\" \"^/tmp/.\")) - The default is empty. - -`recent-files-use-full-names' - If the value of this variable is non-nil, the full pathnames of - the files are shown in the recent-files menu. Otherwise only - the filename part (or the last name component if it is a - directory) is shown in the menu. The default it t, i.e. show - full names. - -`recent-files-filename-replacements' - This is a list of pairs of regular expressions and replacement - strings. If a filename matches one of the regular expressions, - the matching part is replaced by the replacement string for - display in the recent-files menu. - Example: My home directory is \"/users/mmc/nickel/\". I want to - replace it with \"~/\". I also want to replace the directory - \"/imports/teleservices/mmc/avc2/\", where I work a lot, with - \".../avc2/\". The list then looks like - (setq recent-files-filename-replacements - '((\"/users/mmc/nickel/\" . \"~/\") - (\"/imports/teleservices/mmc/avc2/\" . \".../avc2/\"))) - Only the first match is replaced. So, if you have several - entries in this list that may match a filename simultaneously, - put the one you want to match (usually the most special) in - front of the others. The default is to replace the home - directory with \"~\". - -`recent-files-sort-function' - Contains a function symbol to sort the display of filenames in - the recent-files menu. Supplied are two functions, - 'recent-files-dont-sort and 'recent-files-sort-alphabetically. - The first, which is the default, preserves the order of \"most - recent on top\". - -`recent-files-permanent-submenu' - If this variable is non-nil, the permanent entries are put into - a separate submenu of the recent-files menu. The default is - nil. - -`recent-files-non-permanent-submenu' - If this variable is non-nil, the non-permanent entries are put - into a separate submenu of the recent-files menu. The default - is nil. (You can set both `recent-files-permanent-submenu' and - `recent-files-non-permanent-submenu' to t to have both lists in - separate submenus.) - -`recent-files-commands-submenu' - If this variable is non-nil, the commands if recent-files are - placed in a submenu of the recent-files menu. The default is - nil. - -`recent-files-commands-submenu-title' - If the commands are placed in a submenu, this string is used as - the title of the submenu. The default is \"Commands...\". - -`recent-files-actions-on-top' - If this variable is non-nil, the \"action\" menu entries (\"Make - <buffer> permanent\" etc.) are put on top of the menu. Otherwise - they appear below the file entries or submenus. The default is - nil. - -`recent-files-permanent-first' - If this variable is t, the permanent entries are put first in - the recent-files menu, i.e. above the non-permanent entries. If - the value is nil, non-permanent entries appear first. If the - value is neither t nor nil, the entries are sorted according to - recent-files-sort-function. The default is 'sort. - -`recent-files-find-file-command' - This variable contains to commandto execute when a file entry - is selected from the menu. Usually this will be `find-file', - which is the default. - -KNOWN BUG: - - recent-files overwrites the recent-files-save-file - unconditionally when Emacs exits. If you have two Emacs - processes running, the one exiting later will overwrite the - file without merging in the new entries from the other Emacs - process. This can be avoided by disabling the save on exit from - the menu." - :short-doc "`Recent Files' menu" - :enable 'recent-files-initialize) - -(define-behavior 'filladapt - "These functions enhance the default behavior of Emacs' Auto Fill -mode and the commands `fill-paragraph', `lisp-fill-paragraph', -`fill-region-as-paragraph' and `fill-region'. - -The chief improvement is that the beginning of a line to be -filled is examined and, based on information gathered, an -appropriate value for fill-prefix is constructed. Also the -boundaries of the current paragraph are located. This occurs -only if the fill prefix is not already non-nil. - -The net result of this is that blurbs of text that are offset -from left margin by asterisks, dashes, and/or spaces, numbered -examples, included text from USENET news articles, etc. are -generally filled correctly with no fuss." - :short-doc "Adaptive (smart) filling" - :require 'filladapt - :enable #'(lambda () - (setq-default filladapt-mode t) - (mapc #'(lambda (buffer) - (with-current-buffer buffer - (unless filladapt-mode - (filladapt-mode 1)))) - (buffer-list))) - :disable #'(lambda () - (setq-default filladapt-mode nil) - (mapc #'(lambda (buffer) - (with-current-buffer buffer - (when filladapt-mode - (filladapt-mode -1)))) - (buffer-list)))) +(define-behavior-group 'tty) +(define-behavior-group 'toolbars) +(define-behavior-group 'menus) +(define-behavior-group 'mouse) +(define-behavior-group 'editing) +(define-behavior-group 'keyboard) +(define-behavior-group 'files) +(define-behavior-group 'games) +(define-behavior-group 'processes) +(define-behavior-group 'display) +(define-behavior-group 'programming) +(define-behavior-group 'international) +(define-behavior-group 'buffers-and-windows) +(define-behavior-group 'internet) + +(define-behavior 'compose-mail + "Not documented." + :group 'internet + :commands + '(["Send %_Mail..." compose-mail])) diff --text -u 'xemacs-21.5.18/lisp/behavior.el' 'xemacs-21.5.19/lisp/behavior.el' Index: ./lisp/behavior.el --- ./lisp/behavior.el Sun Mar 9 11:27:32 2003 +++ ./lisp/behavior.el Thu Feb 3 14:26:40 2005 @@ -1,6 +1,6 @@ -;;; behavior.el --- consistent interface onto behaviors +;;; behavior.el --- consistent interface onto packages -;; Copyright (C) 2000, 2001, 2002 Ben Wing. +;; Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. ;; Author: Ben Wing ;; Maintainer: XEmacs Development Team @@ -31,13 +31,152 @@ ;;; Commentary: -;; This file will be dumped with XEmacs. +;; This file is dumped with XEmacs. + +;; This file is part of the "Behaviors" project and is a work in progress. +;; The purpose of the project is to provide (a) a consistent interface (at +;; the API level) onto the functionality provided by packages, and (b) an +;; easy-to-use user interface for this functionality, something that +;; *really works*. +;; +;; First, what characteristics do/should packages have? (NOTE: In this +;; discussion below, `package' and `behavior' are being used more or less +;; interchangeably. Eventually this will get resolved.) + +;; 1) A file, or one or more file, containing the code of the package. In +;; addition, a "head" file in the case that the package needs to be +;; loaded in order to get its functionality (e.g. "load-to-enable" +;; packages -- an abomination that is tolerated only with severe +;; displeasure). +;; 2) A Lisp name -- a fairly short symbol (2-3 words max), uncapitalized, +;; without use of excessive abbreviation and with words set off by +;; dashes. This should be the same as the name of the topmost custom +;; group associated with the package (see next item), and preferably the +;; same as the common prefix used for variables defined by your package +;; and the name of the head file of the package. +;; 3) Associated custom group listing the settings associated with the package. +;; 4) Enable and disable methods for turning on or off the functionality of +;; the package, if it's amenable to such a model. Most packages are of two +;; types: +;; +;; (a) They add some functionality to XEmacs, which is incorporated +;; into and makes changes to the normal functionality of XEmacs. Once the +;; package is enabled, the user doesn't have to do anything specific for +;; the package to do its thing -- it happens automatically if the user is +;; using the area whose behavior has been changed. These include packages +;; such as `avoid' (which makes the mouse poointer move when the cursor +;; gets too close), EFS (which adds the ability to treat an FTP site as +;; part of the local file system), the packages that supply the +;; mode-specific handling for various files, etc +;; +;; (b) They provide functionality in the form of specific command to be +;; invoked. This can be as simple as the `hippie-expand' command (tries +;; lots of different expansion methods for the text before point, to +;; try and get a result) and as complicated as GNUS or VM. +;; +;; Some packages might provide both -- you can enable them and they +;; incorporate some functionality into the XEmacs base, but while +;; they're enabled they provide certain commands. #### We need some +;; thought here, and case-by-case analysis, to determine if this really +;; makes sense -- can the enable/disable be removed and whatever needs +;; to happen incorporated as part of the command? can the +;; enable/disable just added to the commands? +;; +;; 5) Packages of type (b) just above will have a list of commands that can be +;; run. They should be in standard menubar format -- i.e. just like a +;; submenu, but without the initial string indidicating the name of the +;; menu. +;; 6) Short doc string, for use in a menu item. *NOT* necessarily the same +;; as the documentation for the Custom group, which is often too long. +;; 7) Long documentation. +;; +;; Good package etiquette: +;; +;; +;; -- Never mess with the menu yourself, or try to "cheat" by putting yourself +;; high up in the hierarchy, e.g. at the top-level or directly off a +;; top-level group that expects to contain only groups of groups, not +;; end-level groups. +;; +;; -- Never use the `override-behavior' commands or the like for specifying +;; (in an overriding fashion) the exact appearance of the hierarchies. +;; +;; -- For type (a), with enable/disable methods: +;; +;; (a) Loading the file should NOT DO ANYTHING. Not enable, not add hooks, +;; nothing. +;; (b) Both enable and disable hooks must exist. The disable hook must +;; completely reset the environment to how it was before the package +;; was enabled. This includes restoring the prior bindings for +;; modified key bindings. #### We need some helper function to assist +;; with remembering the old key bindings and putting them back only +;; when new key bindings haven't been made -- but recognize when those +;; new key bondings were attached as a result of loading another +;; package, so that after any order of loading and unloading a series +;; of packages, the original bindings will eventually occur. (Something +;; like `advice' for key definitions.) Replacement of functions should +;; happen through `advice'. +;; +;; We recognize that many packages out there don't follow these precepts at +;; all. Many or most of them are install-only, often happening +;; automatically when the file is loaded. Converting these will be a step +;; at a time: First, redo the latter type so that the initialization code +;; is put into a function and not run automatically upon load. Next step, +;; try to provide some sort of disable. Third step, work on making sure +;; that disable removes *everything* and enable puts it all back. Fourth +;; step, work on properly advising keys and functions. +;; + +;; Comparison/Integration with Custom: + +;; Custom only handles variable settings, and has no concept of standard +;; enable/disable methods for a package, a standard way of specifying +;; package documentation, or a list of commands associated with a package. +;; Also, its groups do not always map very well onto packages and the +;; resulting hierarchy is too big, confusing, difficult-to-navigate, and +;; incoherent. More generally it does not address at all the basic problem +;; that a hierarchy created in a decentralized fashion -- and by a large +;; number of authors, some more competent than others -- will inevitably be +;; incoherent when put together. +;; + +;; In general, ease-of-use was not the overarching goal of Custom. The +;; primary goal of Custom seems to have been to provide a consistent interface +;; and get all the packages to use it. Ease-of-use -- or even following +;; established user-interface standards -- has taken a far-distant second, and +;; appears in many respects to be an afterthought that never had any serious +;; effort investigated into it. +;; +;; The eventual intent of this project is to integrate with custom. The final +;; intent of integration is that this project subsumes Custom completely, +;; making Custom the unified, user-friendly means of controlling XEmacs that +;; has never properly existed. However, that will take a lot of work. For +;; the meantime, the plan is to develop the Behavior subsystem independent of +;; Custom, with ease-of-use as the primary goal, and get it to the point where +;; it encompasses most packages out there, has stabilized its interface, and +;; works well. At that point, we will consider integration with Custom. (Note +;; that the hard part of the Behavior work is not actually behaviorizing the +;; packages, but developing the interface itself.) +;; +;; As for integrating with Custom -- ideally that would mean simply extending +;; defgroup, but that is not really possible given that backward-compatibility +;; would not work -- existing versions of `defgroup' give an error when +;; presented with an unknown keyword. In practice, then, this might mean that +;; a separate `define-behavior' command (or `defpackage', or the like) will +;; still exist. ;;; Code: ;; Hash table mapping behavior names to property lists, with entries for -;; :short-doc, :require, :enable, and :disable. +;; :group, :custom-group, :short-doc, :require, :enable, :disable, +;; and :commands. (defconst behavior-hash-table (make-hash-table)) +;; Hash table mapping groups to property lists (entries for :group, :children, +;; :short-doc). +(defconst behavior-group-hash-table (make-hash-table)) +;; Hash table with override information for groups. +;; :short-doc). +(defconst behavior-override-hash-table (make-hash-table)) (defvar within-behavior-enabling-disabling nil) @@ -68,40 +207,137 @@ (defvar behavior-history nil "History of entered behaviors.") -(defun define-behavior (name doc-string &rest cl-keys) +(defun behavior-group-p (group) + "Non-nil if GROUP is the name of a valid behavior group." + (not (null (gethash group behavior-group-hash-table)))) + +(defun check-behavior-group (group) + "Verify that GROUP is a valid behavior group, or nil. +Return GROUP if so." + (or (behavior-group-p group) + (error 'invalid-argument "Invalid behavior group" group)) + group) + +(defun* define-behavior (name doc-string &key + group custom-group + (short-doc + (capitalize-string-as-title + (replace-in-string (symbol-name name) "-" " "))) + require enable disable commands + &allow-other-keys) + ;; We allow other keys to allow for the possibility of extensions by + ;; later versions of XEmacs. Packages should be able to support those + ;; extensions without worrying about causing problems with older versions + ;; of XEmacs. "Define a behavior named NAME. DOC-STRING must be specified, a description of what the behavior does when it's enabled and how to further control it (typically through custom variables). Accepted keywords are +:group Symbol naming the behavior group this behavior is within. +:custom-group Symbol naming the custom group containing the options that + can be set in association with this behavior. If not specified, + the custom group with the same name as the behavior will be + used, if it exists. :short-doc A \"pretty\" version of the name, for use in menus. If omitted a prettified name will be generated. :require A single symbol or a list of such symbols, which need to be present at enable time, or will be loaded using `require'. :enable A function of no variables, which turns the behavior on. :disable A function of no variables, which turns the behavior off. +:commands A list of interactive commands that can be invoked in + conjunction with the behavior. These will appear in a submenu + along with the rest of the items for the behavior. Behaviors are assumed to be global, and to take effect immediately; if the underlying package is per-buffer, it may have to scan all existing buffers and frob them. When a behavior is disabled, it should completely go away *everywhere*, as if it were never invoked at all. -The :disable keywords can be missing, although this is considered bad +The :disable keyword can be missing, although this is considered bad practice. In such a case, attempting to disable the behavior will signal -an error unless you use the `force' option." - (cl-parsing-keywords - ((:short-doc (capitalize-string-as-title (replace-in-string - (symbol-name name) "-" " "))) - :require - :enable - :disable) - t - (let ((entry (list :short-doc cl-short-doc :require cl-require - :enable cl-enable :disable cl-disable))) - (puthash name entry behavior-hash-table)))) +an error unless you use the `force' option. + +The :enable keyword can be missing. This is useful for behaviors that +are really a series of related commands without anything semantically +corresponding to \"turning on\" or \"turning off\" the behavior. + +A behavior with no :enable and no :command is possible. This might be +used, for example, by a behavior that encapsulates a series of related +Lisp functions. Such behaviors may be handled specially, e.g. not +displayed in the menus or displayed in a separate location, since they +have no user-invocable behavior." + (let ((entry (list :group (check-behavior-group group) + :custom-group custom-group + :short-doc short-doc :require require + :enable enable :disable disable + :commands commands))) + (puthash name entry behavior-hash-table)) + ;; update the children list of the group we're in (maybe nil). + (unless (member name (getf (gethash group behavior-group-hash-table) + :children)) + (push name (getf (gethash group behavior-group-hash-table) :children)))) + +(defun* override-behavior (name &key + short-doc + group + include + demote-others) + "Override the default properties of a behavior group NAME. +Normally, groups are created and assigned properties by individual packages. +The resulting hierarchy may not make much sense globally. This function +allows the hierarchy and appearance of a group to be specified globally, +and will take precendence over the properties assigned by `define-behavior-group'. This allows a global organization to be imposed on groups, while still allowing for graceful handling of new or unknown groups. + +NAME can be a symbol specifying a group name, or a list of +\(PARENT [...] NAME), where a path from a particular parent is explicitly +given. (This latter form allows the same name to be assigned to more than one +group.) + +Accepted keywords are + +:short-doc A \"pretty\" version of the name, for use in menus. +:group Parent group, if any. Should not be given if the parents are + explicitly specified in NAME. +:include A list of behaviors that are specifically included in this + group, in addition to those that are included by the behaviors + themselves. +:demote-others If non-nil, exclude all behaviors not specified in the :include + list and put them instead (i.e. \"demote\" them) to another group, + usually a subgroup." + (let ((entry (list :group (check-behavior-group group) + :short-doc short-doc + :include include + :demote-others demote-others))) + (puthash name entry behavior-override-hash-table))) + +(defun* define-behavior-group (name &key + (short-doc + (capitalize-string-as-title + (replace-in-string (symbol-name name) "-" + " "))) + group) + "Define a behavior group NAME. + +NAME can be a symbol specifying a group name, or a list of +\(PARENT [...] NAME), where a path from a particular parent is explicitly +given. (This latter form allows the same name to be assigned to more than one +group.) + +Accepted keywords are + +:short-doc A \"pretty\" version of the name, for use in menus. If omitted + a prettified name will be generated. +:group Parent group, if any. Should not be given if the parents are + explicitly specified in NAME." + (let ((entry (list :group (check-behavior-group group) + :short-doc short-doc))) + (puthash name entry behavior-group-hash-table)) + ;; update the children list of the parent (maybe nil). + (push name (getf (gethash group behavior-group-hash-table) :children))) (defun read-behavior (prompt &optional must-match initial-contents history - default-value) + default-value) "Return a behavior symbol from the minibuffer, prompting with string PROMPT. If non-nil, optional second arg INITIAL-CONTENTS is a string to insert in the minibuffer before reading. @@ -119,12 +355,10 @@ behavior-hash-table) (nreverse lis)))) (mapc #'(lambda (aentry) - (setcar aentry (symbol-name - (car aentry)))) + (setcar aentry (symbol-name (car aentry)))) table) table) - nil must-match initial-contents - (or history 'behavior-history) + nil must-match initial-contents (or history 'behavior-history) default-value))) (if (and result (stringp result)) (intern result) @@ -179,6 +413,99 @@ (customize-set-variable 'enabled-behavior-list (delq behavior enabled-behavior-list)))))) +(defun compute-behavior-group-children (group hash) + "Compute the actual children for GROUP and its subgroups. +This takes into account the override information specified." + (let* ((group-plist (gethash group behavior-group-hash-table)) + (override (gethash group behavior-override-hash-table)) + (children (getf group-plist :children))) + ) + ) + +(defun behavior-menu-filter-1 (menu group) + (submenu-generate-accelerator-spec + (let* ( + ;;options + ;;help + (enable + (menu-split-long-menu + (menu-sort-menu + (let ((group-plist (gethash group behavior-group-hash-table))) + (loop for behavior in (getf group-plist :children) + nconc (if (behavior-group-p behavior) + (list + (cons (getf + (gethash behavior behavior-group-hash-table) + :short-doc) + (behavior-menu-filter-1 menu behavior))) + (let* ((plist (gethash behavior behavior-hash-table)) + (commands (getf plist :commands))) + (nconc + (if (getf plist :enable) + `([,(format "%s (%s) [toggle]" + (getf plist :short-doc) + behavior) + (if (memq ',behavior + enabled-behavior-list) + (disable-behavior ',behavior) + (enable-behavior ',behavior)) + :active ,(if (getf plist :disable) t + (not (memq + ',behavior + enabled-behavior-list))) + :style toggle + :selected (memq ',behavior + enabled-behavior-list)])) + (cond ((null commands) nil) + ((and (eq (length commands) 1) + (vectorp (elt commands 0))) + (let ((comm (copy-sequence + (elt commands 0)))) + (setf (elt comm 0) + (format "%s (%s)" + (elt comm 0) behavior)) + (list comm))) + (t (list + (cons (format "%s (%s) Commands" + (getf plist :short-doc) + behavior) + commands))))))))) + )) + ) + ) + enable) + '(?p))) + +(defun behavior-menu-filter (menu) + (append + '(("%_Package Utilities" + ("%_Set Download Site" + ("%_Official Releases" + :filter (lambda (&rest junk) + (menu-split-long-menu + (submenu-generate-accelerator-spec + (package-ui-download-menu))))) + ("%_Pre-Releases" + :filter (lambda (&rest junk) + (menu-split-long-menu + (submenu-generate-accelerator-spec + (package-ui-pre-release-download-menu))))) + ("%_Site Releases" + :filter (lambda (&rest junk) + (menu-split-long-menu + (submenu-generate-accelerator-spec + (package-ui-site-release-download-menu)))))) + "--:shadowEtchedIn" + ["%_Update Package Index" package-get-update-base] + ["%_List and Install" pui-list-packages] + ["U%_pdate Installed Packages" package-get-update-all] + ["%_Help" (Info-goto-node "(xemacs)Packages")]) + "----") + (behavior-menu-filter-1 menu nil))) + +;; Initialize top-level group. +(puthash nil '(:children nil :short-doc "Root") behavior-group-hash-table) + (provide 'behavior) ;;; finder-inf.el ends here diff --text -u 'xemacs-21.5.18/lisp/buffer.el' 'xemacs-21.5.19/lisp/buffer.el' Index: ./lisp/buffer.el --- ./lisp/buffer.el Fri Apr 13 03:21:11 2001 +++ ./lisp/buffer.el Wed Feb 16 20:07:30 2005 @@ -71,7 +71,12 @@ another window even if BUFNAME is already visible in the selected window. If optional third arg is non-nil, it is the frame to pop to this buffer on. -If `focus-follows-mouse' is non-nil, keyboard focus is left unchanged." +If `focus-follows-mouse' is non-nil, keyboard focus is left unchanged. + +Buffers with names that are members of the `same-window-buffer-names' +list, or that match an element of the `same-window-regexps' list are +treated specially by this function--they are always selected in the +same window rather than in a different one." ;; #ifdef I18N3 ;; #### Doc string should indicate that the buffer name will get ;; translated. diff --text -u 'xemacs-21.5.18/lisp/bytecomp-runtime.el' 'xemacs-21.5.19/lisp/bytecomp-runtime.el' Index: ./lisp/bytecomp-runtime.el --- ./lisp/bytecomp-runtime.el Tue Sep 3 14:36:52 2002 +++ ./lisp/bytecomp-runtime.el Sat Dec 18 03:11:29 2004 @@ -92,10 +92,12 @@ ; (list 'put (list 'quote name) ; ''byte-optimizer ''byte-compile-inline-expand)))) -(defun make-obsolete (fn new) +(defun make-obsolete (fn new &optional when) "Make the byte-compiler warn that function FN is obsolete. The warning will say that NEW should be used instead. -If NEW is a string, that is the `use instead' message." +If NEW is a string, that is the `use instead' message. +If provided, WHEN should be a string indicating when the function +was first made obsolete, for example a date or a release number." (interactive "aMake function obsolete: \nxObsoletion replacement: ") (let ((handler (get fn 'byte-compile))) (if (eq 'byte-compile-obsolete handler) @@ -104,10 +106,12 @@ (put fn 'byte-compile 'byte-compile-obsolete))) fn) -(defun make-obsolete-variable (var new) +(defun make-obsolete-variable (var new &optional when) "Make the byte-compiler warn that variable VAR is obsolete, and NEW should be used instead. If NEW is a string, then that is the -`use instead' message." +`use instead' message. +If provided, WHEN should be a string indicating when the variable +was first made obsolete, for example a date or a release number." (interactive (list (let ((str (completing-read "Make variable obsolete: " obarray 'boundp t))) diff --text -u 'xemacs-21.5.18/lisp/cl-extra.el' 'xemacs-21.5.19/lisp/cl-extra.el' Index: ./lisp/cl-extra.el --- ./lisp/cl-extra.el Sun Jun 27 06:25:24 2004 +++ ./lisp/cl-extra.el Fri Nov 5 08:05:54 2004 @@ -71,9 +71,9 @@ ((and (eq type 'integer) (characterp x)) (char-int x)) ((eq type 'float) (float x)) ;; XEmacs addition: enhanced numeric type coercions - ((and (featurep 'number-types) - (memq type '(integer ratio bigfloat)) - (coerce-number x type))) + ((and-fboundp 'coerce-number + (memq type '(integer ratio bigfloat)) + (coerce-number x type))) ;; XEmacs addition: bit-vector coercion ((eq type 'bit-vector) (if (bit-vector-p x) x (apply 'bit-vector (append x nil)))) diff --text -u 'xemacs-21.5.18/lisp/cl.el' 'xemacs-21.5.19/lisp/cl.el' Index: ./lisp/cl.el --- ./lisp/cl.el Sun Jun 27 06:25:24 2004 +++ ./lisp/cl.el Wed Jan 26 18:53:32 2005 @@ -307,8 +307,8 @@ (defun cl-random-time () (let* ((time (copy-sequence (current-time-string))) (i (length time)) (v 0)) (while (>= (decf i) 0) (setq v (+ (* v 3) (aref time i)))) - (if (featurep 'bignum) - (coerce-number v 'fixnum) + (if-fboundp 'coerce-number + (coerce-number v 'fixnum) v))) (defvar *gensym-counter* (* (logand (cl-random-time) 1023) 100)) diff --text -u 'xemacs-21.5.18/lisp/code-init.el' 'xemacs-21.5.19/lisp/code-init.el' Index: ./lisp/code-init.el --- ./lisp/code-init.el Wed Sep 22 11:05:49 2004 +++ ./lisp/code-init.el Wed Jan 26 18:51:23 2005 @@ -62,14 +62,11 @@ if you do this." (dolist (x '(buffer-file-coding-system-for-read keyboard - default-process-coding-system-read)) + default-process-coding-system-read + no-conversion-coding-system-mapping)) (set-coding-system-variable x (coding-system-change-eol-conversion (get-coding-system-variable x) - (if flag nil 'lf)))) - (set-coding-category-system - 'no-conversion - (coding-system-change-eol-conversion (coding-category-system 'no-conversion) - (if flag nil 'lf)))) + (if flag nil 'lf))))) (defun coding-system-current-system-configuration () (cond ((memq system-type '(windows-nt cygwin32)) @@ -117,7 +114,8 @@ keyboard terminal default-process-coding-system-read - default-process-coding-system-write)) + default-process-coding-system-write + no-conversion-coding-system-mapping)) (defun get-coding-system-variable (var) "Return the value of a basic coding system variable. @@ -134,6 +132,8 @@ (terminal (coding-system-aliasee 'terminal)) (default-process-coding-system-read (car default-process-coding-system)) (default-process-coding-system-write (cdr default-process-coding-system)) + (no-conversion-coding-system-mapping + (coding-category-system 'no-conversion)) (t (error 'invalid-constant "Invalid coding system variable" var)))) (defun set-coding-system-variable (var value) @@ -156,6 +156,8 @@ (default-process-coding-system-write (setq default-process-coding-system (cons (car default-process-coding-system) value))) + (no-conversion-coding-system-mapping + (set-coding-category-system 'no-conversion value)) (t (error 'invalid-constant "Invalid coding system variable" var)))) (defun coding-system-variable-default-value (var &optional config) diff --text -u 'xemacs-21.5.18/lisp/code-process.el' 'xemacs-21.5.19/lisp/code-process.el' Index: ./lisp/code-process.el --- ./lisp/code-process.el Sun Apr 4 05:00:26 2004 +++ ./lisp/code-process.el Thu Oct 28 20:31:11 2004 @@ -165,27 +165,27 @@ The read/write coding systems used for process I/O on the process are the same as for `call-process'." - ;; We used to delete the text before calling call-process; that was when - ;; a temporary file was used to pass the text to call-process. Now that - ;; we don't do that, we delete the text afterward; if it's being inserted - ;; in the same buffer, make sure we track the insertion, and don't get - ;; any of it in the deleted region. We keep marker s before the - ;; insertion and e afterward. Finally we delete the regions before - ;; and after the insertion. - (let ((s (and deletep (copy-marker (point)))) - (e (and deletep (copy-marker (point) t)))) - (let ((retval - (apply #'call-process program (list (current-buffer) start end) - buffer displayp args))) - ;; If start and end were the same originally, e will be beyond s now - (when (and deletep (> e s)) - ;; APA: Is it always correct to honor narrowing, which affects - ;; (point-min) and (point-max)? - ;; Delete region before insertion. - (delete-region (point-min) s) - ;; Delete region after insertion. - (delete-region e (point-max))) - retval))) + + ;; We can't delete the region before feeding it to `call-process', so we + ;; take care not to delete the insertion when we delete the region. START + ;; and END may not be markers; copy them. (point) will end up after the + ;; insertion. A copy of (point) tracks the beginning of the insertion. + + (let ((s (and deletep (copy-marker start))) ; Only YOU can + (e (and deletep (copy-marker end t))) ; prevent + (p (and deletep (copy-marker (point)))) ; excess consing! + (retval + (apply #'call-process program (list (current-buffer) start end) + buffer displayp args))) + (when deletep + (if (<= s p e) + ;; region was split by insertion + ;; the order checks are gilt lilies + (progn (when (< (point) e) (delete-region (point) e)) + (when (< s p) (delete-region s p))) + ;; insertion was outside of region + (delete-region s e))) + retval)) (defun start-process (name buffer program &rest program-args) "Start a program in a subprocess. Return the process object for it. diff --text -u 'xemacs-21.5.18/lisp/cus-dep.el' 'xemacs-21.5.19/lisp/cus-dep.el' Index: ./lisp/cus-dep.el --- ./lisp/cus-dep.el Fri Feb 14 21:05:07 2003 +++ ./lisp/cus-dep.el Thu Feb 3 13:29:33 2005 @@ -173,11 +173,8 @@ )) (cond ((zerop (hash-table-count hash)) - (if (not (file-exists-p cusload-file)) - (message "(No customization dependencies)") - (message "(No customization dependencies, deleting %s)" - cusload-file) - (delete-file cusload-file))) + (message "(No customization dependencies)") + (write-region "" nil cusload-file)) (t (message "Generating %s...\n" cusload-base-file) (with-temp-file cusload-file diff --text -u 'xemacs-21.5.18/lisp/cus-edit.el' 'xemacs-21.5.19/lisp/cus-edit.el' Index: ./lisp/cus-edit.el --- ./lisp/cus-edit.el Thu Jun 10 21:20:01 2004 +++ ./lisp/cus-edit.el Thu Feb 3 13:29:33 2005 @@ -1,6 +1,7 @@ ;;; cus-edit.el --- Tools for customizating Emacs and Lisp packages. ;; ;; Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. +;; Copyright (C) 2003 Ben Wing. ;; ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> ;; Maintainer: Hrvoje Niksic <hniksic@xemacs.org> @@ -1656,23 +1657,121 @@ (while loads (setq load (car loads) loads (cdr loads)) - (cond ((symbolp load) - (condition-case nil - (require load) - (error nil))) - ;; Don't reload a file already loaded. - ((and (boundp 'preloaded-file-list) - (member load preloaded-file-list))) - ((assoc load load-history)) - ((assoc (locate-library load) load-history)) - (t - (condition-case nil - ;; Without this, we would load cus-edit recursively. - ;; We are still loading it when we call this, - ;; and it is not in load-history yet. - (or (equal load "cus-edit") - (load-library load)) - (error nil)))))))) + (custom-load-symbol-1 load))))) + +(defun custom-load-symbol-1 (load) + (cond ((symbolp load) + (condition-case nil + (require load) + (error nil))) + ;; Don't reload a file already loaded. + ((and (boundp 'preloaded-file-list) + (member load preloaded-file-list))) + ((assoc load load-history)) + ((assoc (locate-library load) load-history)) + (t + (condition-case nil + ;; Without this, we would load cus-edit recursively. + ;; We are still loading it when we call this, + ;; and it is not in load-history yet. + (or (equal load "cus-edit") + (load-library load)) + (error nil))))) + +(defvar custom-already-loaded-custom-defines nil + "List of already-loaded `custom-defines' files.") +(defvar custom-define-current-source-file nil) +(defvar custom-warn-when-reloading-necessary nil + "For package-debugging purposes: Warn when an error hit in custom-defines.el. +When this happens, the file from which the defcustom or defgroup was taken +is loaded, and custom-defines.el is then reloaded. This works in most +cases, but may not be completely safe. It's better if the package itself +arranges for the necessary functions and variables to be available, using +\;;;###autoload declarations. When this variable is non-nil, warnings are +issued (with backtrace), to aid in tracking down the problems.") + +(defun custom-load-custom-defines (symbol) + "Load custom-defines for SYMBOL." + (unless custom-load-recursion + (let ((custom-load-recursion t) + (loads (get symbol 'custom-loads)) + load) + (while loads + (setq load (car loads) + loads (cdr loads)) + (let* ((found (locate-library + (if (symbolp load) (symbol-name load) load))) + (dir (and found (file-name-directory found)))) + ;; If we find a custom-defines file, assume the package is smart + ;; enough to have put all its defcustoms and defgroups here, and + ;; load it instead of the file itself. Otherwise, do it the + ;; hard way. + (if (and found (or (file-exists-p + (expand-file-name "custom-defines.elc" dir)) + (file-exists-p + (expand-file-name "custom-defines.el" dir)))) + (when (not (member dir custom-already-loaded-custom-defines)) + (push dir custom-already-loaded-custom-defines) + (custom-load-custom-defines-1 dir)))))))) + +(defun custom-load-custom-defines-1 (dir) + ;; Actually load the custom-defines.el file in DIR. + + ;; If we get an error loading the custom-defines, it may be because of a + ;; reference to something (e.g. a constant) that hasn't yet been defined + ;; yet. Properly, these should have been marked, so they either go into + ;; the custom-defines.el file or are autoloaded. But not everyone is so + ;; careful, so for the moment we try to load the file that the + ;; error-generating defcustom came from, and then reload the + ;; custom-defines.el file. We might loop a number of times if we have + ;; various files that need loading. If at any point we get an error that + ;; can't be solved just by loading the appropriate file (e.g. we hit the + ;; same error as before, the file is already loaded, etc.) then we signal + ;; it as a real error. + (let (source) + ;; here's how this works: if we get an error loading custom-defines, + ;; the condition handler is called; if we need to reload, we + ;; `return-from', which throws out of the handler and returns nil from + ;; the `block', which continues the while statement, executing the + ;; `load' at the bottom of this function and then entering the block + ;; again. if the condition handler doesn't throw, but instead returns + ;; normally, `signal' will continue as if nothing happened, and end up + ;; signalling the error normally. + (while + (not + (block custom-load + ;; Use call-with-condition-handler so the error can be seen + ;; with the stack intact. + (call-with-condition-handler + #'(lambda (__custom_load_cd1__) + (when (and + custom-define-current-source-file + (progn + (setq source (expand-file-name + custom-define-current-source-file + dir)) + (let ((nondir (file-name-nondirectory source))) + (and (file-exists-p source) + (not (assoc source load-history)) + (not (assoc nondir load-history)) + (not (and (boundp 'preloaded-file-list) + (member nondir + preloaded-file-list))))))) + (if custom-warn-when-reloading-necessary + (lwarn 'custom-defines 'warning + "Error while loading custom-defines, fetching source and reloading ...\n +Error: %s\n +Source file: %s\n\n +Backtrace follows:\n\n%s" + (error-message-string __custom_load_cd1__) + source + (backtrace-in-condition-handler-eliminating-handler + '__custom_load_cd1__))) + (return-from custom-load nil))) + #'(lambda () + (load (expand-file-name "custom-defines" dir)))))) + ;; we get here only from the `return-from'; see above + (load source)))) (defun custom-load-widget (widget) "Load all dependencies for WIDGET." @@ -3709,31 +3808,33 @@ (defun custom-menu-create (symbol) "Create menu for customization group SYMBOL. The menu is in a format applicable to `easy-menu-define'." - (let* ((item (vector (custom-unlispify-menu-entry symbol) - `(customize-group ',symbol) - t))) - ;; Item is the entry for creating a menu buffer for SYMBOL. - ;; We may nest, if the menu is not too big. - (custom-load-symbol symbol) - (if (< (length (get symbol 'custom-group)) widget-menu-max-size) - ;; The menu is not too big. - (let ((custom-prefix-list (custom-prefix-add symbol - custom-prefix-list)) - (members (custom-sort-items (get symbol 'custom-group) - custom-menu-sort-alphabetically - custom-menu-order-groups))) - ;; Create the menu. - `(,(custom-unlispify-menu-entry symbol t) - ,item - "--" - ,@(mapcar (lambda (entry) - (widget-apply (if (listp (nth 1 entry)) - (nth 1 entry) - (list (nth 1 entry))) - :custom-menu (nth 0 entry))) - members))) - ;; The menu was too big. - item))) + (menu-split-long-menu + (let* ((item (vector (custom-unlispify-menu-entry symbol) + `(customize-group ',symbol) + t))) + ;; Item is the entry for creating a menu buffer for SYMBOL. + ;; We may nest, if the menu is not too big. + (custom-load-custom-defines symbol) + (if t ;(< (length (get symbol 'custom-group)) widget-menu-max-size) + ;; The menu is not too big. + (let ((custom-prefix-list (custom-prefix-add symbol + custom-prefix-list)) + (members (custom-sort-items (get symbol 'custom-group) + custom-menu-sort-alphabetically + custom-menu-order-groups))) + ;; Create the menu. + `(,(custom-unlispify-menu-entry symbol t) + ,item + "--" + ,@(mapcar (lambda (entry) + (widget-apply (if (listp (nth 1 entry)) + (nth 1 entry) + (list (nth 1 entry))) + :custom-menu (nth 0 entry))) + members))) + ; else ;; The menu was too big. + item + )))) ;;;###autoload (defun customize-menu-create (symbol &optional name) diff --text -u 'xemacs-21.5.18/lisp/custom.el' 'xemacs-21.5.19/lisp/custom.el' Index: ./lisp/custom.el --- ./lisp/custom.el Mon Mar 3 19:17:40 2003 +++ ./lisp/custom.el Thu Feb 3 13:29:33 2005 @@ -1,12 +1,10 @@ -;;; custom.el -- Tools for declaring and initializing options. - -;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. - +;;; custom.el --- tools for declaring and initializing options +;; +;; Copyright (C) 1996, 1997, 1999, 2001, 2002 Free Software Foundation, Inc. +;; ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> -;; Maintainer: Hrvoje Niksic <hniksic@xemacs.org> +;; Maintainer: XEmacs Development Group ;; Keywords: help, faces, dumped -;; Version: 1.9960-x -;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ ;; This file is part of XEmacs. @@ -25,17 +23,18 @@ ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. -;;; Synched with: ??? Partially synched to 21.2 by Ben Wing. +;;; Synched with: FSF 21.3. ;;; Commentary: ;; This file is dumped with XEmacs. -;; This file only contain the code needed to declare and initialize -;; user options. The code to customize options is autoloaded from -;; `cus-edit.el'. ;; -;; The code implementing face declarations is in `cus-face.el' +;; This file only contains the code needed to declare and initialize +;; user options. The code to customize options is autoloaded from +;; `cus-edit.el' and is documented in the XEmacs Lisp Reference manual. + +;; The code implementing face declarations is in `cus-face.el'. ;;; Code: @@ -44,8 +43,6 @@ ;; prevent require/provide loop with custom and cus-face. (provide 'custom) -;; BEGIN SYNC WITH FSF 21.2 - (eval-when-compile (load "cl-macs" nil t) ;; To elude warnings. @@ -60,6 +57,14 @@ ;; Customize information for this option is in `cus-edit.el'. "Hook called after defining each customize option.") +(defvar custom-dont-initialize nil + "Non-nil means `defcustom' should not initialize the variable. +That is used for the sake of `custom-make-dependencies'. +Users should not set it.") + +(defvar custom-current-group-alist nil + "Alist of (FILE . GROUP) indicating the current group to use for FILE.") + ;;; The `defcustom' Macro. (defun custom-initialize-default (symbol value) @@ -131,8 +136,16 @@ (defun custom-declare-variable (symbol default doc &rest args) "Like `defcustom', but SYMBOL and DEFAULT are evaluated as normal arguments. DEFAULT should be an expression to evaluate to compute the default value, -not the default value itself." - ;; Remember the standard setting. +not the default value itself. + +DEFAULT is stored as SYMBOL's value in the standard theme. See +`custom-known-themes' for a list of known themes. For backwards +compatibility, DEFAULT is also stored in SYMBOL's property +`standard-value'. At the same time, SYMBOL's property `force-value' is +set to nil, as the value is no longer rogue." + ;; Remember the standard setting. The value should be in the standard + ;; theme, not in this property. However, his would require changeing + ;; the C source of defvar and others as well... (put symbol 'standard-value (list default)) ;; Maybe this option was rogue in an earlier version. It no longer is. (when (eq (get symbol 'force-value) 'rogue) @@ -141,43 +154,46 @@ (when doc (put symbol 'variable-documentation doc)) (let ((initialize 'custom-initialize-reset) - (requests nil)) + (requests nil)) + (unless (memq :group args) + (custom-add-to-group (custom-current-group) symbol 'custom-variable)) (while args (let ((arg (car args))) - (setq args (cdr args)) + (setq args (cdr args)) (check-argument-type 'keywordp arg) - (let ((keyword arg) - (value (car args))) - (unless args + (let ((keyword arg) + (value (car args))) + (unless args (signal 'error (list "Keyword is missing an argument" keyword))) - (setq args (cdr args)) - (cond ((eq keyword :initialize) - (setq initialize value)) - ((eq keyword :set) - (put symbol 'custom-set value)) - ((eq keyword :get) - (put symbol 'custom-get value)) - ((eq keyword :require) - (setq requests (cons value requests))) - ((eq keyword :type) - (put symbol 'custom-type value)) - ((eq keyword :options) - (if (get symbol 'custom-options) - ;; Slow safe code to avoid duplicates. - (mapc (lambda (option) - (custom-add-option symbol option)) - value) - ;; Fast code for the common case. - (put symbol 'custom-options (copy-sequence value)))) - (t - (custom-handle-keyword symbol keyword value - 'custom-variable)))))) + (setq args (cdr args)) + (cond ((eq keyword :initialize) + (setq initialize value)) + ((eq keyword :set) + (put symbol 'custom-set value)) + ((eq keyword :get) + (put symbol 'custom-get value)) + ((eq keyword :require) + (push value requests)) + ((eq keyword :type) + (put symbol 'custom-type (purecopy value))) + ((eq keyword :options) + (if (get symbol 'custom-options) + ;; Slow safe code to avoid duplicates. + (mapc (lambda (option) + (custom-add-option symbol option)) + value) + ;; Fast code for the common case. + (put symbol 'custom-options (copy-sequence value)))) + (t + (custom-handle-keyword symbol keyword value + 'custom-variable)))))) (put symbol 'custom-requests requests) ;; Do the actual initialization. - (funcall initialize symbol default)) + (unless custom-dont-initialize + (funcall initialize symbol default))) ;; #### This is a rough equivalent of LOADHIST_ATTACH. However, ;; LOADHIST_ATTACH also checks for `initialized'. - (push symbol current-load-list) + (push (cons 'defvar symbol) current-load-list) (run-hooks 'custom-define-hook) symbol) @@ -193,16 +209,43 @@ The following keywords are meaningful: -:type VALUE should be a widget type for editing the symbols value. +:type VALUE should be a widget type for editing the symbol's value. The default is `sexp'. :options VALUE should be a list of valid members of the widget type. :group VALUE should be a customization group. Add SYMBOL to that group. +:link LINK-DATA + Include an external link after the documentation string for this + item. This is a sentence containing an active field which + references some other documentation. + + There are three alternatives you can use for LINK-DATA: + + (custom-manual INFO-NODE) + Link to an Info node; INFO-NODE is a string which specifies + the node name, as in \"(emacs)Top\". The link appears as + `[manual]' in the customization buffer. + + (info-link INFO-NODE) + Like `custom-manual' except that the link appears in the + customization buffer with the Info node name. + + (url-link URL) + Link to a web page; URL is a string which specifies the URL. + The link appears in the customization buffer as URL. + + You can specify the text to use in the customization buffer by + adding `:tag NAME' after the first element of the LINK-DATA; for + example, (info-link :tag \"foo\" \"(emacs)Top\") makes a link to the + Emacs manual which appears in the buffer as `foo'. + + An item can have more than one external link; however, most items + have none at all. :initialize - VALUE should be a function used to initialize the - variable. It takes two arguments, the symbol and value - given in the `defcustom' call. The default is - `custom-initialize-reset' + VALUE should be a function used to initialize the + variable. It takes two arguments, the symbol and value + given in the `defcustom' call. The default is + `custom-initialize-reset'. :set VALUE should be a function to set the value of the symbol. It takes two arguments, the symbol to set and the value to give it. The default choice of function is `custom-set-default'. @@ -219,16 +262,21 @@ VALUE should be a string specifying that the variable was first introduced, or its default value was changed, in Emacs version VERSION. -:set-after VARIABLE - Specifies that SYMBOL should be set after VARIABLE when - both have been customized. +:tag LABEL + Use LABEL, a string, instead of the item's name, to label the item + in customization menus and buffers. +:load FILE + Load file FILE (a string) before displaying this customization + item. Loading is done with `load', and only if the file is + not already loaded. +:set-after VARIABLES + Specifies that SYMBOL should be set after the list of variables + VARIABLES when both have been customized. Read the section about customization in the Emacs Lisp manual for more information." `(custom-declare-variable (quote ,symbol) (quote ,value) ,doc ,@args)) -;; END SYNC WITH FSF 21.2 - ;;; The `defface' Macro. (defmacro defface (face spec doc &rest args) @@ -278,12 +326,14 @@ ;;; The `defgroup' Macro. +(defun custom-current-group () + (cdr (assoc load-file-name custom-current-group-alist))) + (defun custom-declare-group (symbol members doc &rest args) "Like `defgroup', but SYMBOL is evaluated as a normal argument." (while members (apply 'custom-add-to-group symbol (car members)) (pop members)) - (put symbol 'custom-group (nconc members (get symbol 'custom-group))) (when doc (put symbol 'group-documentation doc)) (while args @@ -291,15 +341,19 @@ (setq args (cdr args)) (check-argument-type 'keywordp arg) (let ((keyword arg) - (value (car args))) + (value (car args))) (unless args (signal 'error (list "Keyword is missing an argument" keyword))) - (setq args (cdr args)) - (cond ((eq keyword :prefix) - (put symbol 'custom-prefix value)) - (t - (custom-handle-keyword symbol keyword value - 'custom-group)))))) + (setq args (cdr args)) + (cond ((eq keyword :prefix) + (put symbol 'custom-prefix value)) + (t + (custom-handle-keyword symbol keyword value + 'custom-group)))))) + ;; Record the group on the `current' list. + (let ((elt (assoc load-file-name custom-current-group-alist))) + (if elt (setcdr elt symbol) + (push (cons load-file-name symbol) custom-current-group-alist))) (run-hooks 'custom-define-hook) symbol) @@ -318,13 +372,24 @@ [KEYWORD VALUE]... -The following KEYWORD's are defined: +The following KEYWORDs are defined: :group VALUE should be a customization group. Add SYMBOL to that group. Read the section about customization in the Emacs Lisp manual for more information." + + ;; XEmacs: Evidently a purposeful omission from the docs: +;:version VALUE should be a string specifying that the group was introduced +; in Emacs version VERSION. +; + + ;; FSF: (not a problem for XEmacs) + ;; It is better not to use backquote in this file, + ;; because that makes a bootstrapping problem + ;; if you need to recompile all the Lisp files using interpreted code. +; (nconc (list 'custom-declare-group (list 'quote symbol) members doc) args)) `(custom-declare-group (quote ,symbol) ,members ,doc ,@args)) (defvar custom-group-hash-table (make-hash-table :size 300 :test 'eq) @@ -332,19 +397,31 @@ (defun custom-add-to-group (group option widget) "To existing GROUP add a new OPTION of type WIDGET. -If there already is an entry for that option, overwrite it." - (let* ((members (get group 'custom-group)) - (old (assq option members))) - (if old - (setcar (cdr old) widget) - (put group 'custom-group (nconc members (list (list option widget)))))) +If there already is an entry for OPTION and WIDGET, nothing is done." + (let ((members (get group 'custom-group)) + (entry (list option widget))) + (unless (member entry members) + (put group 'custom-group (nconc members (list entry))))) (puthash group t custom-group-hash-table)) +(defun custom-group-of-mode (mode) + "Return the custom group corresponding to the major or minor MODE. +If no such group is found, return nil." + (or (get mode 'custom-mode-group) + (if (or (get mode 'custom-group) + (and (string-match "-mode\\'" (symbol-name mode)) + (get (setq mode (intern (substring (symbol-name mode) + 0 (match-beginning 0)))) + 'custom-group))) + mode))) + ;;; Properties. (defun custom-handle-all-keywords (symbol args type) "For customization option SYMBOL, handle keyword arguments ARGS. Third argument TYPE is the custom option type." + (unless (memq :group args) + (custom-add-to-group (custom-current-group) symbol type)) (while args (let ((arg (car args))) (setq args (cdr args)) @@ -420,78 +497,195 @@ (unless (member load loads) (put symbol 'custom-loads (cons load loads))))) -;;; deftheme macro +(defun custom-autoload (symbol load) + "Mark SYMBOL as autoloaded custom variable and add dependency LOAD." + (put symbol 'custom-autoload t) + (custom-add-load symbol load)) + +;; This test is also in the C code of `user-variable-p'. +(defun custom-variable-p (variable) + "Return non-nil if VARIABLE is a custom variable." + (or (get variable 'standard-value) + (get variable 'custom-autoload))) + +;;; Loading files needed to customize a symbol. +;;; This is in custom.el because menu-bar.el needs it for toggle cmds. + +(defvar custom-load-recursion nil + "Hack to avoid recursive dependencies.") + +(defun custom-load-symbol (symbol) + "Load all dependencies for SYMBOL." + (unless custom-load-recursion + (let ((custom-load-recursion t)) + (dolist (load (get symbol 'custom-loads)) + (cond ((symbolp load) (condition-case nil (require load) (error nil))) + ;; This is subsumed by the test below, but it's much faster. + ((assoc load load-history)) + ;; This was just (assoc (locate-library load) load-history) + ;; but has been optimized not to load locate-library + ;; if not necessary. + ((let ((regexp (concat "\\(\\`\\|/\\)" (regexp-quote load) + "\\(\\'\\|\\.\\)")) + (found nil)) + (dolist (loaded load-history) + (and (stringp (car loaded)) + (string-match regexp (car loaded)) + (setq found t))) + found)) + ;; Without this, we would load cus-edit recursively. + ;; We are still loading it when we call this, + ;; and it is not in load-history yet. + ((equal load "cus-edit")) + (t (condition-case nil (load load) (error nil)))))))) (defvar custom-known-themes '(user standard) - "Themes that have been defthemed.") - -;; #### add strings for group -;; #### during bootstrap we cannot use cl-macs stuff -(defun* custom-define-theme (theme feature &optional doc - &key short-description immediate variable-reset-string - variable-set-string face-set-string face-reset-string - &allow-other-keys) - (push theme custom-known-themes) + "Themes that have been define with `deftheme'. +The default value is the list (user standard). The theme `standard' +contains the Emacs standard settings from the original Lisp files. The +theme `user' contains all the the settings the user customized and saved. +Additional themes declared with the `deftheme' macro will be added to +the front of this list.") + +(defun custom-declare-theme (theme feature &optional doc &rest args) + "Like `deftheme', but THEME is evaluated as a normal argument. +FEATURE is the feature this theme provides. This symbol is created +from THEME by `custom-make-theme-feature'." + (add-to-list 'custom-known-themes theme) (put theme 'theme-feature feature) - (put theme 'theme-documentation doc) - (if immediate (put theme 'theme-immediate immediate)) - (if variable-reset-string - (put theme 'theme-variable-reset-string variable-reset-string )) - (if variable-set-string - (put theme 'theme-variable-set-string variable-set-string )) - (if face-reset-string - (put theme 'theme-face-reset-string face-reset-string )) - (if face-set-string - (put theme 'theme-face-set-string face-set-string )) - (if short-description - (put theme 'theme-short-description short-description ))) + (when doc + (put theme 'theme-documentation doc)) + (while args + (let ((arg (car args))) + (setq args (cdr args)) + (check-argument-type 'keywordp arg) + (let ((keyword arg) + (value (car args))) + (unless args + (signal 'error (list "Keyword is missing an argument" keyword))) + (setq args (cdr args)) + (cond ((eq keyword :short-description) + (put theme 'theme-short-description value)) + ((eq keyword :immediate) + (put theme 'theme-immediate value)) + ((eq keyword :variable-set-string) + (put theme 'theme-variable-set-string value)) + ((eq keyword :variable-reset-string) + (put theme 'theme-variable-reset-string value)) + ((eq keyword :face-set-string) + (put theme 'theme-face-set-string value)) + ((eq keyword :face-reset-string) + (put theme 'theme-face-reset-string value))))))) + +(defmacro deftheme (theme &optional doc &rest args) + "Declare custom theme THEME. +The optional argument DOC is a doc string describing the theme. +The remaining arguments should have the form -(defun custom-make-theme-feature (theme) - (intern (concat (symbol-name theme) "-theme"))) + [KEYWORD VALUE]... -(defmacro deftheme (theme &rest body) - "(deftheme THEME &optional DOC &key KEYWORDS) +The following KEYWORD's are defined: + +:short-description + VALUE is a short (one line) description of the theme. If not + given, DOC is used. +:immediate + If VALUE is non-nil, variables specified in this theme are set + immediately when loading the theme. +:variable-set-string + VALUE is a string used to indicate that a variable takes its + setting from this theme. It is passed to FORMAT with the name + of the theme as an additional argument. If not given, a + generic description is used. +:variable-reset-string + VALUE is a string used in the case a variable has been forced + to its value in this theme. It is passed to FORMAT with the + name of the theme as an additional argument. If not given, a + generic description is used. +:face-set-string + VALUE is a string used to indicate that a face takes its + setting from this theme. It is passed to FORMAT with the name + of the theme as an additional argument. If not given, a + generic description is used. +:face-reset-string + VALUE is a string used in the case a face has been forced to + its value in this theme. It is passed to FORMAT with the name + of the theme as an additional argument. If not given, a + generic description is used. -Define a theme labeled by SYMBOL THEME. The optional argument DOC is a -doc string describing the theme. It is optionally followed by the -following keyword arguments - -:short-description DESC - DESC is a short (one line) description of the theme. If not given DOC - is used. -:immediate FLAG - If FLAG is non-nil variables set in this theme are bound - immediately when loading the theme. -:variable-set-string VARIABLE_-SET-STRING - A string used by the UI to indicate that the value takes it - setting from this theme. It is passed to FORMAT with the - name of the theme a additional argument. - If not given, a generic description is used. -:variable-reset-string VARIABLE-RESET-STRING - As above but used in the case the variable has been forced to - the value in this theme. -:face-set-string FACE-SET-STRING -:face-reset-string FACE-RESET-STRING - As above but for faces." +Any theme `foo' should be defined in a file called `foo-theme.el'; +see `custom-make-theme-feature' for more information." (let ((feature (custom-make-theme-feature theme))) - `(custom-define-theme (quote ,theme) (quote ,feature) ,@body))) + ;; It is better not to use backquote in this file, + ;; because that makes a bootstrapping problem + ;; if you need to recompile all the Lisp files using interpreted code. + (nconc (list 'custom-declare-theme + (list 'quote theme) + (list 'quote feature) + doc) args))) + +(defun custom-make-theme-feature (theme) + "Given a symbol THEME, create a new symbol by appending \"-theme\". +Store this symbol in the `theme-feature' property of THEME. +Calling `provide-theme' to provide THEME actually puts `THEME-theme' +into `features'. + +This allows for a file-name convention for autoloading themes: +Every theme X has a property `provide-theme' whose value is \"X-theme\". +\(require-theme X) then attempts to load the file `X-theme.el'." + (intern (concat (symbol-name theme) "-theme"))) (defsubst custom-theme-p (theme) "Non-nil when THEME has been defined." (memq theme custom-known-themes)) (defsubst custom-check-theme (theme) - "Check whether THEME is valid and signal an error if NOT." + "Check whether THEME is valid, and signal an error if it is not." (unless (custom-theme-p theme) (error "Unknown theme `%s'" theme))) - -; #### do we need to deftheme 'user and/or 'standard here to make the -; code in cus-edit cleaner?. - ;;; Initializing. (defun custom-push-theme (prop symbol theme mode value) + "Add (THEME MODE VALUE) to the list in property PROP of SYMBOL. +If the first element in that list is already (THEME ...), +discard it first. + +MODE can be either the symbol `set' or the symbol `reset'. If it is the +symbol `set', then VALUE is the value to use. If it is the symbol +`reset', then VALUE is the mode to query instead. + +In the following example for the variable `goto-address-url-face', the +theme `subtle-hacker' uses the same value for the variable as the theme +`gnome2': + + \((standard set bold) + \(gnome2 set info-xref) + \(jonadab set underline) + \(subtle-hacker reset gnome2)) + + +If a value has been stored for themes A B and C, and a new value +is to be stored for theme C, then the old value of C is discarded. +If a new value is to be stored for theme B, however, the old value +of B is not discarded because B is not the car of the list. + +For variables, list property PROP is `theme-value'. +For faces, list property PROP is `theme-face'. +This is used in `custom-do-theme-reset', for example. + +The list looks the same in any case; the examples shows a possible +value of the `theme-face' property for the face `region': + + \((gnome2 set ((t (:foreground \"cyan\" :background \"dark cyan\")))) + \(standard set ((((class color) (background dark)) + \(:background \"blue\")) + \(t (:background \"gray\"))))) + +This records values for the `standard' and the `gnome2' themes. +The user has not customized the face; had he done that, +the list would contain an entry for the `user' theme, too. +See `custom-known-themes' for a list of known themes." (let ((old (get symbol prop))) (if (eq (car-safe (car-safe old)) theme) (setq old (cdr old))) @@ -508,13 +702,14 @@ (defun custom-set-variables (&rest args) "Initialize variables according to user preferences. The settings are registered as theme `user'. -Each argument should be a list of the form: +The arguments should each be a list of the form: (SYMBOL VALUE [NOW [REQUEST [COMMENT]]]) The unevaluated VALUE is stored as the saved value for SYMBOL. If NOW is present and non-nil, VALUE is also evaluated and bound as the default value for the SYMBOL. + REQUEST is a list of features we must 'require for SYMBOL. COMMENT is a comment string about SYMBOL." (apply 'custom-theme-set-variables 'user args)) @@ -523,69 +718,168 @@ "Initialize variables according to settings specified by args. Records the settings as belonging to THEME. -See `custom-set-variables' for a description of the arguments ARGS." +The arguments should be a list where each entry has the form: + + (SYMBOL VALUE [NOW [REQUEST [COMMENT]]]) + +The unevaluated VALUE is stored as the saved value for SYMBOL. +If NOW is present and non-nil, VALUE is also evaluated and bound as +the default value for the SYMBOL. +REQUEST is a list of features we must 'require for SYMBOL. +COMMENT is a comment string about SYMBOL. + +Several properties of THEME and SYMBOL are used in the process: + +If THEME property `theme-immediate' is non-nil, this is equivalent of +providing the NOW argument to all symbols in the argument list: SYMBOL +is bound to the evaluated VALUE. The only difference is SYMBOL property +`force-value': if NOW is non-nil, SYMBOL's property `force-value' is set to +the symbol `rogue', else if THEME's property `theme-immediate' is non-nil, +FACE's property `force-face' is set to the symbol `immediate'. + +VALUE itself is saved unevaluated as SYMBOL property `saved-value' and +in SYMBOL's list property `theme-value' \(using `custom-push-theme')." (custom-check-theme theme) - (setq args - (sort args - (lambda (a1 a2) - (let* ((sym1 (car a1)) - (sym2 (car a2)) - (1-then-2 (memq sym1 (get sym2 'custom-dependencies))) - (2-then-1 (memq sym2 (get sym1 'custom-dependencies)))) - (cond ((and 1-then-2 2-then-1) - (error "Circular custom dependency between `%s' and `%s'" - sym1 sym2)) - (1-then-2 t) - (2-then-1 nil) - ;; Put symbols with :require last. The macro - ;; define-minor-mode generates a defcustom - ;; with a :require and a :set, where the - ;; setter function calls the mode function. - ;; Putting symbols with :require last ensures - ;; that the mode function will see other - ;; customized values rather than default - ;; values. - (t (nth 3 a2))))))) (let ((immediate (get theme 'theme-immediate))) + (setq args + (sort args + (lambda (a1 a2) + (let* ((sym1 (car a1)) + (sym2 (car a2)) + (1-then-2 (memq sym1 (get sym2 'custom-dependencies))) + (2-then-1 (memq sym2 (get sym1 'custom-dependencies)))) + (cond ((and 1-then-2 2-then-1) + (error "Circular custom dependency between `%s' and `%s'" + sym1 sym2)) + (2-then-1 nil) + ;; Put symbols with :require last. The macro + ;; define-minor-mode generates a defcustom + ;; with a :require and a :set, where the + ;; setter function calls the mode function. + ;; Putting symbols with :require last ensures + ;; that the mode function will see other + ;; customized values rather than default + ;; values. + (t (nth 3 a2))))))) (while args (let ((entry (car args))) - (if (listp entry) - (let* ((symbol (nth 0 entry)) - (value (nth 1 entry)) - (now (nth 2 entry)) - (requests (nth 3 entry)) - (comment (nth 4 entry)) - (set (or (get symbol 'custom-set) 'custom-set-default))) - (put symbol 'saved-value (list value)) + (if (listp entry) + (let* ((symbol (nth 0 entry)) + (value (nth 1 entry)) + (now (nth 2 entry)) + (requests (nth 3 entry)) + (comment (nth 4 entry)) + set) + (when requests + (put symbol 'custom-requests requests) + (mapc 'require requests)) + (setq set (or (get symbol 'custom-set) 'custom-set-default)) + (put symbol 'saved-value (list value)) + (put symbol 'saved-variable-comment comment) (custom-push-theme 'theme-value symbol theme 'set value) - (put symbol 'saved-variable-comment comment) - ;; Allow for errors in the case where the setter has - ;; changed between versions, say, but let the user know. - (condition-case data - (cond ((or now immediate) - ;; Rogue variable, set it now. - (put symbol 'force-value (if now 'rogue 'immediate)) - (funcall set symbol (eval value))) - ((default-boundp symbol) - ;; Something already set this, overwrite it. - (funcall set symbol (eval value)))) - (error + ;; Allow for errors in the case where the setter has + ;; changed between versions, say, but let the user know. + (condition-case data + (cond ((or now immediate) + ;; Rogue variable, set it now. + (put symbol 'force-value (if now 'rogue 'immediate)) + (funcall set symbol (eval value))) + ((default-boundp symbol) + ;; Something already set this, overwrite it. + (funcall set symbol (eval value)))) + (error (message "Error setting %s: %s" symbol data))) - (and (or now (default-boundp symbol)) - (put symbol 'variable-comment comment)) - (when requests - (put symbol 'custom-requests requests) - (mapc 'require requests)) - (setq args (cdr args))) - ;; Old format, a plist of SYMBOL VALUE pairs. - (message "Warning: old format `custom-set-variables'") - (ding) - (sit-for 2) - (let ((symbol (nth 0 args)) - (value (nth 1 args))) - (put symbol 'saved-value (list value)) + (setq args (cdr args)) + (and (or now (default-boundp symbol)) + (put symbol 'variable-comment comment))) + ;; Old format, a plist of SYMBOL VALUE pairs. + (message "Warning: old format `custom-set-variables'") + (ding) + (sit-for 2) + (let ((symbol (nth 0 args)) + (value (nth 1 args))) + (put symbol 'saved-value (list value)) (custom-push-theme 'theme-value symbol theme 'set value)) - (setq args (cdr (cdr args)))))))) + (setq args (cdr (cdr args)))))))) + +(defun custom-set-default (variable value) + "Default :set function for a customizable variable. +Normally, this sets the default value of VARIABLE to VALUE, +but if `custom-local-buffer' is non-nil, +this sets the local binding in that buffer instead." + (if custom-local-buffer + (with-current-buffer custom-local-buffer + (set variable value)) + (set-default variable value))) + +(defun custom-quote (sexp) + "Quote SEXP iff it is not self quoting." + (if (or (memq sexp '(t nil)) + (keywordp sexp) + (and (listp sexp) + (memq (car sexp) '(lambda))) + (stringp sexp) + (numberp sexp) + (vectorp sexp) +;;; (and (fboundp 'characterp) +;;; (characterp sexp)) + ) + sexp + (list 'quote sexp))) + +(defun customize-mark-to-save (symbol) + "Mark SYMBOL for later saving. + +If the default value of SYMBOL is different from the standard value, +set the `saved-value' property to a list whose car evaluates to the +default value. Otherwise, set it to nil. + +To actually save the value, call `custom-save-all'. + +Return non-nil iff the `saved-value' property actually changed." + (let* ((get (or (get symbol 'custom-get) 'default-value)) + (value (funcall get symbol)) + (saved (get symbol 'saved-value)) + (standard (get symbol 'standard-value)) + (comment (get symbol 'customized-variable-comment))) + ;; Save default value iff different from standard value. + (if (or (null standard) + (not (equal value (condition-case nil + (eval (car standard)) + (error nil))))) + (put symbol 'saved-value (list (custom-quote value))) + (put symbol 'saved-value nil)) + ;; Clear customized information (set, but not saved). + (put symbol 'customized-value nil) + ;; Save any comment that might have been set. + (when comment + (put symbol 'saved-variable-comment comment)) + (not (equal saved (get symbol 'saved-value))))) + +(defun customize-mark-as-set (symbol) + "Mark current value of SYMBOL as being set from customize. + +If the default value of SYMBOL is different from the saved value if any, +or else if it is different from the standard value, set the +`customized-value' property to a list whose car evaluates to the +default value. Otherwise, set it to nil. + +Return non-nil iff the `customized-value' property actually changed." + (let* ((get (or (get symbol 'custom-get) 'default-value)) + (value (funcall get symbol)) + (customized (get symbol 'customized-value)) + (old (or (get symbol 'saved-value) (get symbol 'standard-value)))) + ;; Mark default value as set iff different from old value. + (if (or (null old) + (not (equal value (condition-case nil + (eval (car old)) + (error nil))))) + (put symbol 'customized-value (list (custom-quote value))) + (put symbol 'customized-value nil)) + ;; Changed? + (not (equal customized (get symbol 'customized-value))))) + +;;; Theme Manipulation (defvar custom-loaded-themes nil "Themes in the order they are loaded.") @@ -595,103 +889,138 @@ (memq theme custom-loaded-themes)) (defun provide-theme (theme) - "Indicate that this file provides THEME." + "Indicate that this file provides THEME. +Add THEME to `custom-loaded-themes' and `provide' whatever +is stored in THEME's property `theme-feature'. + +Usually the theme-feature property contains a symbol created +by `custom-make-theme-feature'." (custom-check-theme theme) (provide (get theme 'theme-feature)) - (push theme custom-loaded-themes)) + (setq custom-loaded-themes (nconc (list theme) custom-loaded-themes))) -(defun require-theme (theme &optional soft) - "Try to load a theme by requiring its feature." +(defun require-theme (theme) + "Try to load a theme by requiring its feature. +THEME's feature is stored in THEME's `theme-feature' property. + +Usually the `theme-feature' property contains a symbol created +by `custom-make-theme-feature'." ;; Note we do no check for validity of the theme here. ;; This allows to pull in themes by a file-name convention - (require (get theme 'theme-feature (custom-make-theme-feature theme)))) + (require (or (get theme 'theme-feature) + (custom-make-theme-feature theme)))) + +(defun custom-remove-theme (spec-alist theme) + "Delete all elements from SPEC-ALIST whose car is THEME." + (let ((elt (assoc theme spec-alist))) + (while elt + (setq spec-alist (delete elt spec-alist) + elt (assoc theme spec-alist)))) + spec-alist) (defun custom-do-theme-reset (theme) - ; #### untested! slow! + "Undo all settings defined by THEME. + +A variable remains unchanged if its property `theme-value' does not +contain a value for THEME. A face remains unchanged if its property +`theme-face' does not contain a value for THEME. In either case, all +settings for THEME are removed from the property and the variable or +face is set to the `user' theme. + +See `custom-known-themes' for a list of known themes." (let (spec-list) (mapatoms (lambda (symbol) + ;; This works even if symbol is both a variable and a + ;; face. (setq spec-list (get symbol 'theme-value)) (when spec-list - (setq spec-list (delete-if (lambda (elt) - (eq (car elt) theme)) - spec-list)) - (put symbol 'theme-value spec-list) + (put symbol 'theme-value (custom-remove-theme spec-list theme)) (custom-theme-reset-internal symbol 'user)) (setq spec-list (get symbol 'theme-face)) (when spec-list - (setq spec-list (delete-if (lambda (elt) - (eq (car elt) theme)) - spec-list)) - (put symbol 'theme-face spec-list) + (put symbol 'theme-face (custom-remove-theme spec-list theme)) (custom-theme-reset-internal-face symbol 'user)))))) (defun custom-theme-load-themes (by-theme &rest body) - "Load the themes specified by BODY and record them as required by -theme BY-THEME. BODY is a sequence of - - a SYMBOL - require the theme SYMBOL - - a list (reset THEME) - Undo all the settings made by THEME. - - a list (hidden THEME) - require the THEME but hide it from the user." + "Load the themes specified by BODY. +Record them as required by theme BY-THEME. BODY is a sequence of either + +THEME + BY-THEME requires THEME +\(reset THEME) + Undo all the settings made by THEME +\(hidden THEME) + Require THEME but hide it from the user + +All the themes loaded for BY-THEME are recorded in BY-THEME's property +`theme-loads-themes'. Any theme loaded with the hidden predicate will +be given the property `theme-hidden' unless it has been loaded before. +Whether a theme has been loaded before is determined by the function +`custom-theme-loaded-p'." (custom-check-theme by-theme) - (dolist (theme body) - (cond ((and (consp theme) (eq (car theme) 'reset)) - (custom-do-theme-reset (cadr theme))) - ((and (consp theme) (eq (car theme) 'hidden)) - (require-theme (cadr theme)) - (unless (custom-theme-loaded-p (cadr theme)) - (put (cadr theme) 'theme-hidden t))) - (t - (require-theme theme) - (remprop theme 'theme-hidden))) - (push theme (get by-theme 'theme-loads-themes)))) + (let ((theme) + (themes-loaded (get by-theme 'theme-loads-themes))) + (while theme + (setq theme (car body) + body (cdr body)) + (cond ((and (consp theme) (eq (car theme) 'reset)) + (custom-do-theme-reset (cadr theme))) + ((and (consp theme) (eq (car theme) 'hidden)) + (require-theme (cadr theme)) + (unless (custom-theme-loaded-p (cadr theme)) + (put (cadr theme) 'theme-hidden t))) + (t + (require-theme theme) + (put theme 'theme-hidden nil))) + (setq themes-loaded (nconc (list theme) themes-loaded))) + (put by-theme 'theme-loads-themes themes-loaded))) (defun custom-load-themes (&rest body) "Load themes for the USER theme as specified by BODY. -BODY is as with custom-theme-load-themes." - (apply #'custom-theme-load-themes 'user body)) +See `custom-theme-load-themes' for more information on BODY." + (apply 'custom-theme-load-themes 'user body)) +; (defsubst copy-upto-last (elt list) +; "Copy all the elements of the list upto the last occurrence of elt" +; ;; Is it faster to do more work in C than to do less in elisp? +; (nreverse (cdr (member elt (reverse list))))) +(defun custom-theme-value (theme theme-spec-list) + "Determine the value for THEME defined by THEME-SPEC-LIST. +Returns a list with the original value if found; nil otherwise. +THEME-SPEC-LIST is an alist with themes as its key. As new themes are +installed, these are added to the front of THEME-SPEC-LIST. +Each element has the form -(defsubst copy-upto-last (elt list) - "Copy all the elements of the list upto the last occurrence of elt." - ;; Is it faster to do more work in C than to do less in elisp? - (nreverse (cdr (member elt (reverse list))))) + \(THEME MODE VALUE) -(defun custom-theme-value (theme theme-spec-list) - "Determine the value for THEME defined by THEME-SPEC-LIST. -Returns (list value) if found. Nil otherwise." +MODE is either the symbol `set' or the symbol `reset'. See +`custom-push-theme' for more information on the format of +THEME-SPEC-LIST." ;; Note we do _NOT_ signal an error if the theme is unknown ;; it might have gone away without the user knowing. - (let ((theme-or-lower (memq theme (cons 'user custom-loaded-themes))) - value) - (mapc #'(lambda (theme-spec) - (when (member (car theme-spec) theme-or-lower) - (setq value (cdr theme-spec)) - ;; We need to continue because if theme =A and we found - ;; B then if the load order is B A C B - ;; we actually want the value in C. - (setq theme-or-lower (copy-upto-last (car theme-spec) - theme-or-lower)) - ;; We could should circuit if this is now nil. - )) - theme-spec-list) + (let ((value (cdr (assoc theme theme-spec-list)))) (if value (if (eq (car value) 'set) - (list (cadr value)) - ;; Yet another reset spec. car value = reset + (cdr value) (custom-theme-value (cadr value) theme-spec-list))))) - (defun custom-theme-variable-value (variable theme) - "Return (list value) value of VARIABLE in THEME if the THEME modifies the -VARIABLE. Nil otherwise." + "Return (list value) indicating value of VARIABLE in THEME. +If THEME does not define a value for VARIABLE, return nil. The value +definitions per theme are stored in VARIABLE's property `theme-value'. +The actual work is done by function `custom-theme-value', which see. +See `custom-push-theme' for more information on how these definitions +are stored." (custom-theme-value theme (get variable 'theme-value))) (defun custom-theme-reset-internal (symbol to-theme) + "Reset SYMBOL to the value defined by TO-THEME. +If SYMBOL is not defined in TO-THEME, reset SYMBOL to the standard +value. See `custom-theme-variable-value'. The standard value is +stored in SYMBOL's property `standard-value'." (let ((value (custom-theme-variable-value symbol to-theme)) was-in-theme) (setq was-in-theme value) @@ -699,46 +1028,37 @@ (when value (put symbol 'saved-value was-in-theme) (if (or (get 'force-value symbol) (default-boundp symbol)) - (funcall (get symbol 'custom-set 'set-default) symbol + (funcall (or (get symbol 'custom-set) 'set-default) symbol (eval (car value))))) value)) - (defun custom-theme-reset-variables (theme &rest args) "Reset the value of the variables to values previously defined. Associate this setting with THEME. ARGS is a list of lists of the form - (variable to-theme) + (VARIABLE TO-THEME) -This means reset variable to its value in to-theme." +This means reset VARIABLE to its value in TO-THEME." (custom-check-theme theme) - (mapc #'(lambda (arg) - (apply #'custom-theme-reset-internal arg) - (custom-push-theme 'theme-value (car arg) theme 'reset (cadr arg))) - args)) + (mapcar '(lambda (arg) + (apply 'custom-theme-reset-internal arg) + (custom-push-theme 'theme-value (car arg) theme 'reset (cadr arg))) + args)) (defun custom-reset-variables (&rest args) - "Reset the value of the variables to values previously defined. -Associate this setting with the `user' theme. + "Reset the value of the variables to values previously saved. +This is the setting associated the `user' theme. -The ARGS are as in `custom-theme-reset-variables'." - (apply #'custom-theme-reset-variables 'user args)) +ARGS is a list of lists of the form -(defun custom-set-default (variable value) - "Default :set function for a customizable variable. -Normally, this sets the default value of VARIABLE to VALUE, -but if `custom-local-buffer' is non-nil, -this sets the local binding in that buffer instead." - (if custom-local-buffer - (with-current-buffer custom-local-buffer - (set variable value)) - (set-default variable value))) + (VARIABLE TO-THEME) -;;; The End. +This means reset VARIABLE to its value in TO-THEME." + (apply 'custom-theme-reset-variables 'user args)) -;; BEGIN SYNC WITH FSF 21.2 +;;; The End. ;; Process the defcustoms for variables loaded before this file. ;; `custom-declare-variable-list' is defvar'd in subr.el. Utility programs @@ -748,6 +1068,4 @@ (apply 'custom-declare-variable (car custom-declare-variable-list)) (setq custom-declare-variable-list (cdr custom-declare-variable-list))) -;; END SYNC WITH FSF 21.2 - ;; custom.el ends here diff --text -u 'xemacs-21.5.18/lisp/dialog-gtk.el' 'xemacs-21.5.19/lisp/dialog-gtk.el' Index: ./lisp/dialog-gtk.el --- ./lisp/dialog-gtk.el Sat May 15 16:31:44 2004 +++ ./lisp/dialog-gtk.el Fri Nov 5 08:05:54 2004 @@ -45,7 +45,8 @@ gtk-box-set-spacing gtk-dialog-vbox gtk-container-add gtk-label-new gtk-button-new-with-label gtk-widget-set-sensitive gtk-widget-show gtk-dialog-action-area - gtk-label-parse-uline gtk-widget-add-accelerator gtk-accel-group-new)) + gtk-label-parse-uline gtk-widget-add-accelerator gtk-accel-group-new + gtk-misc-set-alignment gtk-button-new gtk-window-add-accel-group)) (defun gtk-popup-convert-underscores (str) ;; Convert the XEmacs button accelerator representation to Gtk mnemonic diff --text -u 'xemacs-21.5.18/lisp/dumped-lisp.el' 'xemacs-21.5.19/lisp/dumped-lisp.el' Index: ./lisp/dumped-lisp.el --- ./lisp/dumped-lisp.el Sun Mar 2 18:38:39 2003 +++ ./lisp/dumped-lisp.el Thu Feb 10 12:26:15 2005 @@ -6,6 +6,17 @@ This includes every package that is loaded directly by a package listed in dumped-lisp.el and is not itself listed.") + +;; WARNING WARNING WARNING: None of the files below, until where it says +;; "All files after this can have extended characters in them", can have +;; extended (non-ASCII characters) of any sort in them! Unfortunately, you +;; will not get any error at load-time; however, you may get a later very +;; cryptic error "Invalid opcode"! This is caused by the byte-code data +;; being encoded as escape-quoted, when we can't handle that yet. +;; +;; #### We should resurrect the check for the coding-system magic cookie in +;; fileio.c and put in an abort if we are not able to handle it yet. + (setq preloaded-file-list (list ;; do not defcustom any variables in these files @@ -94,7 +105,7 @@ "register" "iso8859-1" ; This must be before any modes ; (sets standard syntax table.) - "paragraphs" + "easy-mmode" ; Added for 21.5. "easymenu" ; Added for 20.3. "lisp-mode" "text-mode" @@ -147,23 +158,23 @@ "unicode" ;;;;;;;;;;;;;;;;;; MULE support (when (featurep 'mule) - '("mule-charset" - "mule-cmds" ; to sync with Emacs 20.1 - "mule-coding" - "mule-composite-stub" - "mule-composite" + '("mule/mule-charset" + "mule/mule-cmds" ; to sync with Emacs 20.1 + "mule/mule-coding" + "mule/mule-composite-stub" + "mule/mule-composite" )) ;; may initialize coding systems - (when (featurep '(and mule x)) "mule-x-init") - (when (featurep '(and mule tty)) "mule-tty-init") + (when (featurep '(and mule x)) "mule/mule-x-init") + (when (featurep '(and mule tty)) "mule/mule-tty-init") (when (and (featurep 'mule) (memq system-type '(windows-nt cygwin32))) - "mule-win32-init") + "mule/mule-win32-init") "code-init" ; set up defaults ;; All files after this can have extended characters in them. (when (featurep 'mule) - '("mule-category" - "mule-ccl" - "kinsoku" + '("mule/mule-category" + "mule/mule-ccl" + "mule/kinsoku" )) ;; after this goes the specific lisp routines for a particular input system @@ -185,35 +196,35 @@ ;; compile with -no-packages. (when (featurep 'mule) - '("arabic" - "chinese" - "cyrillic" - "english" - "ethiopic" - "european" - "greek" - "hebrew" - "indian" - "devanagari" ; must be loaded after indian.el - "japanese" - "korean" - "lao" - "latin" - "misc-lang" + '("mule/arabic" + "mule/chinese" + "mule/cyrillic" + "mule/english" + "mule/ethiopic" + "mule/european" + "mule/greek" + "mule/hebrew" + "mule/indian" + "mule/devanagari" ; must be loaded after indian.el + "mule/japanese" + "mule/korean" + "mule/lao" + "mule/latin" + "mule/misc-lang" ;; "thai" #### merge thai and thai-xtis!!! - "thai-xtis" - "tibetan" - "vietnamese" + "mule/thai-xtis" + "mule/tibetan" + "mule/vietnamese" )) ;; Specialized language support - (when (featurep '(and mule CANNA)) "canna-leim") + (when (featurep '(and mule CANNA)) "mule/canna-leim") ;; Egg/Its is now a package ; (when (featurep '(and mule wnn)) ; '("egg-leim" "egg-kwnn-leim" "egg-cwnn-leim")) -; (when (featurep 'mule) "egg-sj3-leim") +; (when (featurep 'mule) "mule/egg-sj3-leim") ;; SKK is now a package -; (when (featurep 'mule) "skk-leim") +; (when (featurep 'mule) "mule/skk-leim") ;; Enable Mule capability for Gnus, mail, etc... ;; Moved to sunpro-load.el - the default only for Sun. @@ -222,7 +233,7 @@ ;; needs access to the charsets created by the above ;; language-specific files. (when (and (featurep 'mule) (valid-console-type-p 'mswindows)) - "mule-msw-init-late") + "mule/mule-msw-init-late") ;;; mule-load.el ends here @@ -272,6 +283,7 @@ ;; "ediff-hook" ; Packaged. "fontl-hooks" "auto-show" + "paragraphs" ; needs easy-mmode, coding "resize-minibuffer" (when (featurep 'ldap) "ldap") diff --text -u /dev/null 'xemacs-21.5.19/lisp/easy-mmode.el' Index: ./lisp/easy-mmode.el --- ./lisp/easy-mmode.el Thu Jan 1 09:00:00 1970 +++ ./lisp/easy-mmode.el Thu Feb 3 16:11:20 2005 @@ -0,0 +1,601 @@ +;;; easy-mmode.el --- easy definition for major and minor modes + +;; Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc. + +;; Author: Georges Brun-Cottan <Georges.Brun-Cottan@inria.fr> +;; Maintainer: Stefan Monnier <monnier@gnu.org> + +;; Keywords: extensions lisp + +;; 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: GNU Emacs 21.3. + +;;; Commentary: + +;; Minor modes are useful and common. This package makes defining a +;; minor mode easy, by focusing on the writing of the minor mode +;; functionalities themselves. Moreover, this package enforces a +;; conventional naming of user interface primitives, making things +;; natural for the minor-mode end-users. + +;; For each mode, easy-mmode defines the following: +;; <mode> : The minor mode predicate. A buffer-local variable. +;; <mode>-map : The keymap possibly associated to <mode>. +;; <mode>-hook,<mode>-on-hook,<mode>-off-hook and <mode>-mode: +;; see `define-minor-mode' documentation +;; +;; eval +;; (pp (macroexpand '(define-minor-mode <your-mode> <doc>))) +;; to check the result before using it. + +;; The order in which minor modes are installed is important. Keymap +;; lookup proceeds down minor-mode-map-alist, and the order there +;; tends to be the reverse of the order in which the modes were +;; installed. Perhaps there should be a feature to let you specify +;; orderings. + +;; Additionally to `define-minor-mode', the package provides convenient +;; ways to define keymaps, and other helper functions for major and minor +;; modes. + +;;; Code: + +(eval-when-compile (require 'cl)) + +;;; This file uses two functions that did not exist in some versions of +;;; XEmacs: propertize and replace-regexp-in-string. We provide these +;;; functions here for such XEmacsen. +;;; +;;; FIXME: These function definitions should go into the future or +;;; forward-compat package, once that package exists. + +;; XEmacs <= 21.4 does not have propertize, but XEmacs >= 21.5 dumps it (it is +;; defined in subr.el). Therefore, it is either defined regardless of what +;; has been loaded already, or it won't be defined regardless of what is +;; loaded. +(if (not (fboundp 'propertize)) + (defun propertize (string &rest properties) + "Return a copy of STRING with text properties added. +First argument is the string to copy. +Remaining arguments form a sequence of PROPERTY VALUE pairs for text +properties to add to the result." + (let ((str (copy-sequence string))) + (add-text-properties 0 (length str) + properties + str) + str))) + +;; XEmacs <= 21.4 does not have replace-regexp-in-string, but XEmacs >= 21.5 +;; dumps it (it is defined in subr.el). Therefore, it is either defined +;; regardless of what has been loaded already, or it won't be defined +;; regardless of what is loaded. +(if (not (fboundp 'replace-regexp-in-string)) + (defun replace-regexp-in-string (regexp rep string &optional + fixedcase literal subexp start) + "Replace all matches for REGEXP with REP in STRING. + +Return a new string containing the replacements. + +Optional arguments FIXEDCASE, LITERAL and SUBEXP are like the +arguments with the same names of function `replace-match'. If START +is non-nil, start replacements at that index in STRING. + +REP is either a string used as the NEWTEXT arg of `replace-match' or a +function. If it is a function it is applied to each match to generate +the replacement passed to `replace-match'; the match-data at this +point are such that match 0 is the function's argument. + +To replace only the first match (if any), make REGEXP match up to \\' +and replace a sub-expression, e.g. + (replace-regexp-in-string \"\\(foo\\).*\\'\" \"bar\" \" foo foo\" nil nil 1) + => \" bar foo\" +" + (let ((l (length string)) + (start (or start 0)) + matches str mb me) + (save-match-data + (while (and (< start l) (string-match regexp string start)) + (setq mb (match-beginning 0) + me (match-end 0)) + ;; If we matched the empty string, make sure we advance by one char + (when (= me mb) (setq me (min l (1+ mb)))) + ;; Generate a replacement for the matched substring. + ;; Operate only on the substring to minimize string consing. + ;; Set up match data for the substring for replacement; + ;; presumably this is likely to be faster than munging the + ;; match data directly in Lisp. + (string-match regexp (setq str (substring string mb me))) + (setq matches + (cons (replace-match (if (stringp rep) + rep + (funcall rep (match-string 0 str))) + fixedcase literal str subexp) + (cons (substring string start mb) ; unmatched prefix + matches))) + (setq start me)) + ;; Reconstruct a string from the pieces. + (setq matches (cons (substring string start l) matches)) ; leftover + (apply #'concat (nreverse matches)))))) + + +(defun easy-mmode-pretty-mode-name (mode &optional lighter) + "Turn the symbol MODE into a string intended for the user. +If provided LIGHTER will be used to help choose capitalization." + (let* ((case-fold-search t) + (name (concat (replace-regexp-in-string + "-Minor" " minor" + (capitalize (replace-regexp-in-string + "-mode\\'" "" (symbol-name mode)))) + " mode"))) + (if (not (stringp lighter)) name + (setq lighter + (replace-regexp-in-string "\\`\\s-+\\|\\-s+\\'" "" lighter)) + (replace-regexp-in-string lighter lighter name t t)))) + +;; XEmacs change: add -on-hook, -off-hook, and macro parameter documentation. +;;;###no-autoload +(defalias 'easy-mmode-define-minor-mode 'define-minor-mode) +;;;###no-autoload +(defmacro define-minor-mode (mode doc &optional init-value lighter keymap &rest body) + "Define a new minor mode MODE. +This function defines the associated control variable MODE, keymap MODE-map, +toggle command MODE, and hook MODE-hook. + +DOC is the documentation for the mode toggle command. +Optional INIT-VALUE is the initial value of the mode's variable. +Optional LIGHTER is displayed in the modeline when the mode is on. +Optional KEYMAP is the default (defvar) keymap bound to the mode keymap. + If it is a list, it is passed to `easy-mmode-define-keymap' + in order to build a valid keymap. It's generally better to use + a separate MODE-map variable than to use this argument. +The above three arguments can be skipped if keyword arguments are +used (see below). + +BODY contains code that will be executed each time the mode is (de)activated. + It will be executed after any toggling but before running the hooks. + Before the actual body code, you can write + keyword arguments (alternating keywords and values). + These following keyword arguments are supported: +:group GROUP Custom group name to use in all generated `defcustom' forms. +:global GLOBAL If non-nil specifies that the minor mode is not meant to be + buffer-local, so don't make the variable MODE buffer-local. + By default, the mode is buffer-local. +:init-value VAL Same as the INIT-VALUE argument. +:lighter SPEC Same as the LIGHTER argument. +:require SYM Same as in `defcustom'. + +For backwards compatibility, these hooks are run each time the mode is +\(de)activated. When the mode is toggled, MODE-hook is always run before the +other hook. +MODE-hook: run if the mode is toggled. +MODE-on-hook: run if the mode is activated. +MODE-off-hook: run if the mode is deactivated. + +\(defmacro easy-mmode-define-minor-mode + (MODE DOC &optional INIT-VALUE LIGHTER KEYMAP &rest BODY)...\) + +For example, you could write + (define-minor-mode foo-mode \"If enabled, foo on you!\" + nil \"Foo \" foo-keymap + :require 'foo :global t :group 'inconvenience + ...BODY CODE...)" + + ;; Allow skipping the first three args. + (cond + ((keywordp init-value) + (setq body (list* init-value lighter keymap body) + init-value nil lighter nil keymap nil)) + ((keywordp lighter) + (setq body (list* lighter keymap body) lighter nil keymap nil)) + ((keywordp keymap) (push keymap body) (setq keymap nil))) + + (let* ((mode-name (symbol-name mode)) + (pretty-name (easy-mmode-pretty-mode-name mode lighter)) + (globalp nil) + (group nil) + (extra-args nil) + (require t) + (keymap-sym (if (and keymap (symbolp keymap)) keymap + (intern (concat mode-name "-map")))) + (hook (intern (concat mode-name "-hook"))) + (hook-on (intern (concat mode-name "-on-hook"))) + (hook-off (intern (concat mode-name "-off-hook")))) + + ;; Check keys. + (while (keywordp (car body)) + (case (pop body) + (:init-value (setq init-value (pop body))) + (:lighter (setq lighter (pop body))) + (:global (setq globalp (pop body))) + (:extra-args (setq extra-args (pop body))) + (:group (setq group (nconc group (list :group (pop body))))) + (:require (setq require (pop body))) + (t (pop body)))) + + (unless group + ;; We might as well provide a best-guess default group. + (setq group + `(:group ',(or (custom-current-group) + (intern (replace-regexp-in-string + "-mode\\'" "" mode-name)))))) + ;; Add default properties to LIGHTER. +;; #### FSF comments this out in 21.3. +; (unless (or (not (stringp lighter)) +; (get-text-property 0 'local-map lighter) +; (get-text-property 0 'keymap lighter)) +; (setq lighter +; (propertize lighter +; 'local-map modeline-minor-mode-map ; XEmacs change +; 'help-echo "mouse-3: minor mode menu"))) + + `(progn + ;; Define the variable to enable or disable the mode. + ,(if (not globalp) + `(progn + (defvar ,mode ,init-value ,(format "Non-nil if %s is enabled. +Use the command `%s' to change this variable." pretty-name mode)) + (make-variable-buffer-local ',mode)) + + (let ((curfile (or (and (boundp 'byte-compile-current-file) + byte-compile-current-file) + load-file-name))) + `(defcustom ,mode ,init-value + ,(format "Non-nil if %s is enabled. +See the command `%s' for a description of this minor-mode. +Setting this variable directly does not take effect; +use either \\[customize] or the function `%s'." + pretty-name mode mode) + :set (lambda (symbol value) (funcall symbol (or value 0))) + :initialize 'custom-initialize-default + ,@group + :type 'boolean + ,@(cond + ((not (and curfile require)) nil) + ((not (eq require t)) `(:require ,require)) + (t `(:require + ',(intern (file-name-nondirectory + (file-name-sans-extension curfile))))))))) + + ;; The actual function. + (defun ,mode (&optional arg ,@extra-args) + ,(or doc + (format (concat "Toggle %s on or off. +Interactively, with no prefix argument, toggle the mode. +With universal prefix ARG turn mode on. +With zero or negative ARG turn mode off. +\\{%s}") pretty-name keymap-sym)) + ;; Use `toggle' rather than (if ,mode 0 1) so that using + ;; repeat-command still does the toggling correctly. + (interactive (list (or current-prefix-arg 'toggle))) + ;; XEmacs addition: save the old mode + (let ((old-mode ,mode)) + (setq ,mode + (cond + ((eq arg 'toggle) (not ,mode)) + (arg (or (listp arg);; XEmacs addition: C-u alone + (> (prefix-numeric-value arg) 0))) + (t + (if (null ,mode) t + (message + "Toggling %s off; better pass an explicit argument." + ',mode) + nil)))) + ,@body + ;; The on/off hooks are here for backward compatibility only. + ;; The on/off hooks are here for backward compatibility only. + ;; XEmacs change: check mode before running hooks + (and ,hook + (not (equal old-mode ,mode)) + (run-hooks ',hook)) + (and ,hook-on + ,mode + (run-hooks ',hook-on)) + (and ,hook-off + (not ,mode) + (run-hooks ',hook-off))) + (if (interactive-p) + (progn + ,(if globalp `(customize-mark-as-set ',mode)) + (message ,(format "%s %%sabled" pretty-name) + (if ,mode "en" "dis")))) + (force-mode-line-update) + ;; Return the new setting. + ,mode) + + ;; Autoloading an easy-mmode-define-minor-mode autoloads + ;; everything up-to-here. + ;; + ;; XEmacs change: XEmacs does not support :autoload-end. On the other + ;; hand, I don't see why we need to support it. An autoload cookie + ;; just before a (define-minor-mode foo) form will generate an autoload + ;; form for the file with name foo. But that's exactly right, since + ;; the defun created just above here has the name foo. There are no + ;; other top-level forms created above here by the macro, so we're done. + ;; + ;;:autoload-end + + ;; The toggle's hook. + (defcustom ,hook nil + ,(format "Hook run at the end of function `%s'." mode-name) + ,@group + :type 'hook) + + ;; XEmacs addition: declare the on and off hooks also + (defcustom ,hook-on nil + ,(format "Hook to run when entering %s." mode-name) + :group ,(cadr group) + :type 'hook) + + (defcustom ,hook-off nil + ,(format "Hook to run when exiting %s." mode-name) + :group ,(cadr group) + :type 'hook) + + ;; Define the minor-mode keymap. + ,(unless (symbolp keymap) ;nil is also a symbol. + `(defvar ,keymap-sym + (let ((m ,keymap)) + (cond ((keymapp m) m) + ((listp m) (easy-mmode-define-keymap m)) + (t (error "Invalid keymap %S" ,keymap)))) + ,(format "Keymap for `%s'." mode-name))) + + (add-minor-mode ',mode ',lighter + ,(if keymap keymap-sym + `(if (boundp ',keymap-sym) + (symbol-value ',keymap-sym))) + ;; XEmacs change: supply the AFTER and TOGGLE-FUN args + t ',mode) + + ;; If the mode is global, call the function according to the default. + ,(if globalp + `(if (and load-file-name (not (equal ,init-value ,mode)) + ;; XEmacs addition: + (not purify-flag)) + (eval-after-load load-file-name '(,mode (if ,mode 1 -1)))))))) + +;;; +;;; make global minor mode +;;; + +;;;###no-autoload +(defmacro easy-mmode-define-global-mode (global-mode mode turn-on + &rest keys) + "Make GLOBAL-MODE out of the buffer-local minor MODE. +TURN-ON is a function that will be called with no args in every buffer + and that should try to turn MODE on if applicable for that buffer. +KEYS is a list of CL-style keyword arguments: +:group to specify the custom group." + (let* ((global-mode-name (symbol-name global-mode)) + (pretty-name (easy-mmode-pretty-mode-name mode)) + (pretty-global-name (easy-mmode-pretty-mode-name global-mode)) + (group nil) + (extra-args nil) + (buffers (intern (concat global-mode-name "-buffers"))) + (cmmh (intern (concat global-mode-name "-cmmh")))) + + ;; Check keys. + (while (keywordp (car keys)) + (case (pop keys) + (:extra-args (setq extra-args (pop keys))) + (:group (setq group (nconc group (list :group (pop keys))))) + (t (setq keys (cdr keys))))) + + (unless group + ;; We might as well provide a best-guess default group. + (setq group + `(:group ',(or (custom-current-group) + (intern (replace-regexp-in-string + "-mode\\'" "" (symbol-name mode))))))) + + `(progn + ;; The actual global minor-mode + (define-minor-mode ,global-mode + ,(format "Toggle %s in every buffer. +With prefix ARG, turn %s on if and only if ARG is positive. +%s is actually not turned on in every buffer but only in those +in which `%s' turns it on." + pretty-name pretty-global-name pretty-name turn-on) + :global t :extra-args ,extra-args ,@group + + ;; Setup hook to handle future mode changes and new buffers. + (if ,global-mode + ;; XEmacs: find-file-hooks not find-file-hook + (progn + (add-hook 'find-file-hooks ',buffers) + (add-hook 'change-major-mode-hook ',cmmh)) + (remove-hook 'find-file-hooks ',buffers) + (remove-hook 'change-major-mode-hook ',cmmh)) + + ;; Go through existing buffers. + (dolist (buf (buffer-list)) + (with-current-buffer buf + (if ,global-mode (,turn-on) (when ,mode (,mode -1)))))) + + ;; TODO: XEmacs does not support :autoload-end + ;; Autoloading easy-mmode-define-global-mode + ;; autoloads everything up-to-here. + :autoload-end + + ;; List of buffers left to process. + (defvar ,buffers nil) + + ;; The function that calls TURN-ON in each buffer. + (defun ,buffers () + (remove-hook 'post-command-hook ',buffers) + (while ,buffers + (let ((buf (pop ,buffers))) + (when (buffer-live-p buf) + (with-current-buffer buf (,turn-on)))))) + (put ',buffers 'definition-name ',global-mode) + + ;; The function that catches kill-all-local-variables. + (defun ,cmmh () + (add-to-list ',buffers (current-buffer)) + (add-hook 'post-command-hook ',buffers)) + (put ',cmmh 'definition-name ',global-mode)))) + +;;; +;;; easy-mmode-defmap +;;; + +(if (fboundp 'set-keymap-parents) + (defalias 'easy-mmode-set-keymap-parents 'set-keymap-parents) + (defun easy-mmode-set-keymap-parents (m parents) + (set-keymap-parent + m + (cond + ((not (consp parents)) parents) + ((not (cdr parents)) (car parents)) + (t (let ((m (copy-keymap (pop parents)))) + (easy-mmode-set-keymap-parents m parents) + m)))))) + +;;;###no-autoload +(defun easy-mmode-define-keymap (bs &optional name m args) + "Return a keymap built from bindings BS. +BS must be a list of (KEY . BINDING) where +KEY and BINDINGS are suitable for `define-key'. +Optional NAME is passed to `make-sparse-keymap'. +Optional map M can be used to modify an existing map. +ARGS is a list of additional keyword arguments." + (let (inherit dense ;suppress + ) + (while args + (let ((key (pop args)) + (val (pop args))) + (case key + (:name (setq name val)) + (:dense (setq dense val)) + (:inherit (setq inherit val)) + (:group) + ;;((eq key :suppress) (setq suppress val)) + (t (message "Unknown argument %s in defmap" key))))) + (unless (keymapp m) + (setq bs (append m bs)) + (setq m (if dense (make-keymap name) (make-sparse-keymap name)))) + (dolist (b bs) + (let ((keys (car b)) + (binding (cdr b))) + (dolist (key (if (consp keys) keys (list keys))) + (cond + ((symbolp key) + (substitute-key-definition key binding m global-map)) + ((null binding) + (unless (keymapp (lookup-key m key)) (define-key m key binding))) + ((let ((o (lookup-key m key))) + (or (null o) (numberp o) (eq o 'undefined))) + (define-key m key binding)))))) + (cond + ((keymapp inherit) (set-keymap-parent m inherit)) + ((consp inherit) (easy-mmode-set-keymap-parents m inherit))) + m)) + +;;;###no-autoload +(defmacro easy-mmode-defmap (m bs doc &rest args) + `(defconst ,m + (easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args)) + ,doc)) + + +;;; +;;; easy-mmode-defsyntax +;;; + +(defun easy-mmode-define-syntax (css args) + (let ((st (make-syntax-table (plist-get args :copy))) + (parent (plist-get args :inherit))) + (dolist (cs css) + (let ((char (car cs)) + (syntax (cdr cs))) + (if (sequencep char) + (mapcar (lambda (c) (modify-syntax-entry c syntax st)) char) + (modify-syntax-entry char syntax st)))) + ;; XEmacs change: we do not have set-char-table-parent + (if parent (derived-mode-merge-syntax-tables + (if (symbolp parent) (symbol-value parent) parent) st)) + st)) + +;;;###no-autoload +(defmacro easy-mmode-defsyntax (st css doc &rest args) + "Define variable ST as a syntax-table. +CSS contains a list of syntax specifications of the form (CHAR . SYNTAX)." + `(progn + (autoload 'easy-mmode-define-syntax "easy-mmode") + (defconst ,st (easy-mmode-define-syntax ,css ,(cons 'list args)) ,doc))) + + + +;;; +;;; easy-mmode-define-navigation +;;; + +;; XEmacs change: autoload +;;;###no-autoload +(defmacro easy-mmode-define-navigation (base re &optional name endfun) + "Define BASE-next and BASE-prev to navigate in the buffer. +RE determines the places the commands should move point to. +NAME should describe the entities matched by RE. It is used to build + the docstrings of the two functions. +BASE-next also tries to make sure that the whole entry is visible by + searching for its end (by calling ENDFUN if provided or by looking for + the next entry) and recentering if necessary. +ENDFUN should return the end position (with or without moving point)." + (let* ((base-name (symbol-name base)) + (prev-sym (intern (concat base-name "-prev"))) + (next-sym (intern (concat base-name "-next")))) + (unless name (setq name (symbol-name base-name))) + `(progn + (add-to-list 'debug-ignored-errors + ,(concat "^No \\(previous\\|next\\) " (regexp-quote name))) + (defun ,next-sym (&optional count) + ,(format "Go to the next COUNT'th %s." name) + (interactive) + (unless count (setq count 1)) + (if (< count 0) (,prev-sym (- count)) + (if (looking-at ,re) (incf count)) + (if (not (re-search-forward ,re nil t count)) + (if (looking-at ,re) + (goto-char (or ,(if endfun `(,endfun)) (point-max))) + (error ,(format "No next %s" name))) + (goto-char (match-beginning 0)) + (when (and (eq (current-buffer) (window-buffer (selected-window))) + (interactive-p)) + (let ((endpt (or (save-excursion + ,(if endfun `(,endfun) + `(re-search-forward ,re nil t 2))) + (point-max)))) + ;; XEmacs change: versions < 21.5.16 have a + ;; pos-visible-in-window-p that takes only 2 parameters + (unless + (if (eq (function-max-args #'pos-visible-in-window-p) 2) + (pos-visible-in-window-p endpt nil) + (pos-visible-in-window-p endpt nil t)) + (recenter '(0)))))))) + (defun ,prev-sym (&optional count) + ,(format "Go to the previous COUNT'th %s" (or name base-name)) + (interactive) + (unless count (setq count 1)) + (if (< count 0) (,next-sym (- count)) + (unless (re-search-backward ,re nil t count) + (error ,(format "No previous %s" name)))))))) + +(provide 'easy-mmode) + +;;; easy-mmode.el ends here diff --text -u 'xemacs-21.5.18/lisp/easymenu.el' 'xemacs-21.5.19/lisp/easymenu.el' Index: ./lisp/easymenu.el --- ./lisp/easymenu.el Sat May 5 07:42:01 2001 +++ ./lisp/easymenu.el Thu Feb 3 14:03:38 2005 @@ -181,7 +181,7 @@ (reverse easy-menu-all-popups)) (let ((same-as-menu (car easy-menu-all-popups))) - (cons (normalize-menu-item-name + (cons (normalize-menu-text (car same-as-menu)) (cdr same-as-menu))))) @@ -208,7 +208,7 @@ (reverse easy-menu-all-popups)) (let ((same-as-menu (car easy-menu-all-popups))) - (cons (normalize-menu-item-name + (cons (normalize-menu-text (car same-as-menu)) (cdr same-as-menu))))) diff --text -u 'xemacs-21.5.18/lisp/files.el' 'xemacs-21.5.19/lisp/files.el' Index: ./lisp/files.el --- ./lisp/files.el Mon Jun 7 08:58:44 2004 +++ ./lisp/files.el Sun Dec 12 11:47:09 2004 @@ -2107,7 +2107,7 @@ (save-excursion (with-temp-buffer (let ((coding-system-for-read 'raw-text)) - (insert-file-contents file nil 1 3001)) + (insert-file-contents file nil 0 3000)) (goto-char (point-min)) (or (and (looking-at "^[^\n]*-\\*-[^\n]*coding: \\([^ \t\n;]+\\)[^\n]*-\\*-") diff --text -u 'xemacs-21.5.18/lisp/fill.el' 'xemacs-21.5.19/lisp/fill.el' Index: ./lisp/fill.el --- ./lisp/fill.el Fri Mar 15 16:43:19 2002 +++ ./lisp/fill.el Wed Jan 26 18:56:06 2005 @@ -23,6 +23,10 @@ ;; 02111-1307, USA. ;;; Synched up with: FSF 19.34. +;;; NOTE: Merging past 19.34 is currently impossible. Later versions +;;; contain FSF's own Kinsoku processing, conflicting with the current code +;;; and depending on various features of their Mule implementation that +;;; do not currently exist. ;;; Commentary: @@ -201,9 +205,7 @@ ;; We insert before markers in case a caller such as ;; do-auto-fill has done a save-excursion with point at the end ;; of the line and wants it to stay at the end of the line. - (insert ? )))) -;; XEmacs: we don't have this function. -;; (insert-before-markers-and-inherit ? )))) + (insert-before-markers-and-inherit ? )))) ;; XEmacs -- added DONT-SKIP-FIRST. Port of older code changes by Stig. ;; #### probably this junk is broken -- do-auto-fill doesn't actually use @@ -377,8 +379,7 @@ ;; Make sure sentences ending at end of line get an extra space. ;; loses on split abbrevs ("Mr.\nSmith") (while (re-search-forward "[.?!][])}\"']*$" nil t) - ;; XEmacs change (no insert-and-inherit) - (or (eobp) (insert ?\ ?\ ))) + (or (eobp) (insert-and-inherit ?\ ?\ ))) (goto-char from) (skip-chars-forward " \t") ;; Then change all newlines to spaces. @@ -423,8 +424,7 @@ (canonically-space-region (or squeeze-after (point)) (point-max)) (goto-char (point-max)) (delete-horizontal-space) - ;; XEmacs change (no insert-and-inherit) - (insert " ")) + (insert-and-inherit " ")) (goto-char (point-min)) ;; This is the actual filling loop. @@ -572,7 +572,7 @@ ;; Set prefixcol so whitespace in the prefix won't get lost. (and fill-prefix (not (equal fill-prefix "")) (progn - (insert fill-prefix) + (insert-and-inherit fill-prefix) (setq prefixcol (current-column)))))) ;; Justify the line just ended, if desired. (if justify @@ -930,8 +930,7 @@ (find-space-insertable-point))) ;(search-backward " "))) (skip-chars-backward " ") (setq nmove (1- nmove)))) - ;; XEmacs change - (insert " ") + (insert-and-inherit " ") (skip-chars-backward " ") (setq ncols (1- ncols))))))) (t (error "Unknown justification value")))) @@ -1046,7 +1045,7 @@ fill-prefix-regexp (regexp-quote fill-prefix))) (forward-line 1) (if (bolp) - ;; If forward-line went past a newline + ;; If forward-line went past a newline, ;; move further to the left margin. (move-to-left-margin)) ;; Now stop the loop if end of paragraph. diff --text -u 'xemacs-21.5.18/lisp/find-paths.el' 'xemacs-21.5.19/lisp/find-paths.el' Index: ./lisp/find-paths.el --- ./lisp/find-paths.el Wed Sep 22 11:05:50 2004 +++ ./lisp/find-paths.el Sun Jan 16 00:17:36 2005 @@ -5,7 +5,7 @@ ;; Copyright (C) 1995 Board of Trustees, University of Illinois ;; Copyright (C) 2003 Ben Wing. -;; Author: Mike Sperber <sperber@informatik.uni-tuebingen.de> +;; Author: Mike Sperber <mike@xemacs.org> ;; Maintainer: XEmacs Development Team ;; Keywords: internal, dumped @@ -125,7 +125,10 @@ path))) (defun paths-construct-emacs-directory (root suffix base) - "Construct a directory name within the XEmacs hierarchy." + "Construct a directory name within the XEmacs hierarchy. +ROOT must be a an installation root. +SUFFIX is the subdirectory from there. +BASE is the base to look for." (file-name-as-directory (expand-file-name (concat @@ -133,9 +136,13 @@ suffix base)))) -(defun paths-find-emacs-directory (roots suffix base - &optional envvar default keep-suffix) - "Find a directory in the XEmacs hierarchy. + +(defun paths-for-each-emacs-directory (func + roots suffix base + &optional envvar default keep-suffix) + "Iterate over directories in the XEmacs hierarchy. +FUNC is a function that called for each directory, with the directory +as the only argument. ROOTS must be a list of installation roots. SUFFIX is the subdirectory from there. BASE is the base to look for. @@ -149,46 +156,160 @@ (if (and preferred-value (paths-file-readable-directory-p preferred-value)) (file-name-as-directory preferred-value) - (catch 'gotcha - (while roots - (let* ((root (car roots)) - ;; installed - (path (paths-construct-emacs-directory root suffix base))) - (if (paths-file-readable-directory-p path) - (throw 'gotcha path) - ;; in-place - (if (null keep-suffix) - (let ((path (paths-construct-emacs-directory root "" base))) - (if (paths-file-readable-directory-p path) - (throw 'gotcha path)))))) - (setq roots (cdr roots))) - nil)))) + (while roots + (let* ((root (car roots)) + ;; installed + (path (paths-construct-emacs-directory root suffix base))) + (if (paths-file-readable-directory-p path) + (funcall func path) + ;; in-place + (if (null keep-suffix) + (let ((path (paths-construct-emacs-directory root "" base))) + (if (paths-file-readable-directory-p path) + (funcall func path)))))) + (setq roots (cdr roots)))))) + +(defun paths-find-emacs-directories (roots + suffix base + &optional envvar default keep-suffix) + "Find a list of directories in the XEmacs hierarchy. +ROOTS must be a list of installation roots. +SUFFIX is the subdirectory from there. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value. +If KEEP-SUFFIX is non-nil, the suffix must be respected in searching +the directory." + (let ((l '())) + (paths-for-each-emacs-directory #'(lambda (dir) + (setq l (cons dir l))) + roots + suffix base + envvar default keep-suffix) + (reverse l))) + +(defun paths-find-emacs-directory (roots suffix base + &optional envvar default keep-suffix) + "Find a directory in the XEmacs hierarchy. +ROOTS must be a list of installation roots. +SUFFIX is the subdirectory from there. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value. +If KEEP-SUFFIX is non-nil, the suffix must be respected in searching +the directory." + (catch 'gotcha + (paths-for-each-emacs-directory #'(lambda (dir) + (throw 'gotcha dir)) + roots + suffix base + envvar default keep-suffix))) + +(defun paths-for-each-site-directory (func roots base &optional envvar default) + "Iterate over the site-specific directories in the XEmacs hierarchy. +FUNC is a function that called for each directory, with the directory +as the only argument. +ROOT must be a an installation root. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value." + (paths-for-each-emacs-directory func + roots + (file-name-as-directory + (paths-construct-path (list + "lib" + emacs-program-name))) + base + envvar default)) (defun paths-find-site-directory (roots base &optional envvar default) - "Find a site-specific directory in the XEmacs hierarchy." - (paths-find-emacs-directory roots - (file-name-as-directory - (paths-construct-path (list - "lib" - emacs-program-name))) - base - envvar default)) + "Find a site-specific directory in the XEmacs hierarchy. +ROOT must be a an installation root. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value." + (catch 'gotcha + (paths-for-each-site-directory #'(lambda (dir) + (throw 'gotcha dir)) + roots base + envvar default))) + +(defun paths-find-site-directories (roots base &optional envvar default) + "Find a list of site-specific directories in the XEmacs hierarchy. +ROOT must be a an installation root. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value." + (let ((l '())) + (paths-for-each-site-directory #'(lambda (dir) + (setq l (cons dir l))) + roots base + envvar default) + (reverse l))) + +(defun paths-for-each-version-directory (func roots base + &optional envvar default enforce-version) + "Iterate over version-specific directories in the XEmacs hierarchy. +FUNC is a function that called for each directory, with the directory +as the only argument. +ROOT must be a an installation root. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value. +If ENFORCE-VERSION is non-nil, the directory must contain the XEmacs version." + (paths-for-each-emacs-directory func + roots + (file-name-as-directory + (paths-construct-path + (list "lib" + (construct-emacs-version-name)))) + base + envvar default)) (defun paths-find-version-directory (roots base &optional envvar default enforce-version) "Find a version-specific directory in the XEmacs hierarchy. +ROOT must be a an installation root. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value. +If ENFORCE-VERSION is non-nil, the directory must contain the XEmacs version." + (catch 'gotcha + (paths-for-each-version-directory #'(lambda (dir) + (throw 'gotcha dir)) + roots base + envvar default))) + +(defun paths-find-version-directories (roots base + &optional envvar default enforce-version) + "Find a list of version-specific directories in the XEmacs hierarchy. +ROOT must be a an installation root. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value. If ENFORCE-VERSION is non-nil, the directory must contain the XEmacs version." - (paths-find-emacs-directory roots - (file-name-as-directory - (paths-construct-path - (list "lib" - (construct-emacs-version-name)))) - base - envvar default - enforce-version)) + (let ((l '())) + (paths-for-each-site-directory #'(lambda (dir) + (setq l (cons dir l))) + roots base + envvar default) + (reverse l))) (defun paths-find-architecture-directory (roots base &optional envvar default) - "Find an architecture-specific directory in the XEmacs hierarchy." + "Find an architecture-specific directory in the XEmacs hierarchy. +ROOT must be a an installation root. +BASE is the base to look for. +ENVVAR is the name of the environment variable that might also +specify the directory. +DEFAULT is the preferred value." (or ;; from more to less specific (paths-find-version-directory roots @@ -203,11 +324,12 @@ envvar))) (defun construct-emacs-version-name () - "Construct the raw XEmacs version number." + "Construct a string from the raw XEmacs version number." (concat emacs-program-name "-" emacs-program-version)) (defun paths-directories-which-exist (directories) - "Return the directories among DIRECTORIES." + "Return the directories among DIRECTORIES. +DIRECTORIES is a list of strings." (let ((reverse-directories '())) (while directories (if (paths-file-readable-directory-p (car directories)) @@ -218,7 +340,7 @@ (reverse reverse-directories))) (defun paths-uniq-append (list-1 list-2) - "Append LIST-1 and LIST-2, omitting duplicates." + "Append LIST-1 and LIST-2, omitting EQUAL duplicates." (let ((reverse-survivors '())) (while list-2 (if (null (member (car list-2) list-1)) diff --text -u 'xemacs-21.5.18/lisp/font-lock.el' 'xemacs-21.5.19/lisp/font-lock.el' Index: ./lisp/font-lock.el --- ./lisp/font-lock.el Fri Jun 13 09:08:41 2003 +++ ./lisp/font-lock.el Wed Jan 26 13:18:15 2005 @@ -2,7 +2,7 @@ ;; Copyright (C) 1992-1995, 1997 Free Software Foundation, Inc. ;; Copyright (C) 1995 Amdahl Corporation. -;; Copyright (C) 1996, 2000, 2001, 2002 Ben Wing. +;; Copyright (C) 1996, 2000, 2001, 2002, 2004 Ben Wing. ;; Author: Jamie Zawinski <jwz@jwz.org>, for the LISPM Preservation Society. ;; Minimally merged with FSF 19.34 by Barry Warsaw <bwarsaw@python.org> @@ -2027,7 +2027,7 @@ ;; "when" "unless" "do" "dolist" "dotimes" "flet" "labels" ;; "lambda" "block" "return" "return-from" "loop") t) ;; (setq last-kbd-macro - ;; (read-kbd-macro "\" C-7 C-1 <right> C-r \\\\| 3*<right> \" RET")) + ;; (read-kbd-macro "\" C-6 C-9 <right> C-r \\\\| 3*<right> \" RET")) "autoload\\|block\\|c\\(?:a\\(?:ll-with-condition-handler\\|tch\\)\\|" "ond\\(?:ition-case\\)?\\)\\|do\\(?:list\\|times\\)?\\|" "eval-\\(?:a\\(?:fter-load\\|nd-compile\\)\\|when-compile\\)\\|flet\\|" @@ -2174,6 +2174,12 @@ (defconst c-font-lock-keywords-3 nil "Gaudy level highlighting for C modes.") +(defconst xemacs-c-font-lock-keywords-2 nil + "Medium level highlighting for XEmacs C source code.") + +(defconst xemacs-c-font-lock-keywords-3 nil + "Gaudy level highlighting for XEmacs C source code.") + (defconst c++-font-lock-keywords-1 nil "Subdued level highlighting for C++ modes.") @@ -2205,14 +2211,35 @@ (let ((c-keywords ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while") "break\\|continue\\|do\\|else\\|for\\|if\\|return\\|switch\\|while") + (xemacs-c-type-types + ;(regexp-opt '("Ibyte" "CIbyte" "Extbyte" "UExtbyte" "WExtbyte" + ; "Ascbyte" "UAscbyte" "Rawbyte" "CRawbyte" "Binbyte" "CBinbyte" + ; "SBinbyte" "Boolbyte" "Ichar" "Raw_Ichar" "Itext" "Textcount" + ; "Bytecount" "Charcount" "Charbpos" "Bytebpos" "Membpos" "Charxpos" + ; "Bytexpos" "Memxpos" "Elemcount" "Hashcode" "EMACS_INT" "USID" + ; "face_index" "glyph_index" "Lisp_Object")) + ;; see below (search for last-kbd-macro) for how to auto-generate + ;; what's below from what's above. + (concat + "Ascbyte\\|B\\(?:inbyte\\|oolbyte\\|yte\\(?:bpos\\|count\\|" + "xpos\\)\\)\\|C\\(?:Binbyte\\|Ibyte\\|Rawbyte\\|har\\(?:bpos\\|" + "count\\|xpos\\)\\)\\|E\\(?:MACS_INT\\|lemcount\\|xtbyte\\)\\|" + "Hashcode\\|I\\(?:byte\\|char\\|text\\)\\|Lisp_Object\\|" + "Mem\\(?:bpos\\|xpos\\)\\|Raw\\(?:_Ichar\\|byte\\)\\|SBinbyte\\|" + "Textcount\\|U\\(?:Ascbyte\\|Extbyte\\|SID\\)\\|WExtbyte\\|" + "face_index\\|glyph_index")) (c-type-types ; ("auto" "extern" "register" "static" "typedef" "struct" "union" "enum" -; "signed" "unsigned" "short" "long" "int" "char" "float" "double" -; "void" "volatile" "const") +; "signed" "unsigned" "short" "long" "int" "char" "wchar_t" "float" +; "double" "void" "volatile" "const") + ;; This regexp is (just) 6 parens deep ... + ;; This regexp is (just) 6 parens deep ... + ;; This regexp is (just) 6 parens deep ... + ;; repeat ad nauseum (concat "auto\\|c\\(har\\|onst\\)\\|double\\|e\\(num\\|xtern\\)\\|" "float\\|int\\|long\\|register\\|" "s\\(hort\\|igned\\|t\\(atic\\|ruct\\)\\)\\|typedef\\|" - "un\\(ion\\|signed\\)\\|vo\\(id\\|latile\\)")) ; 6 ()s deep. + "un\\(ion\\|signed\\)\\|vo\\(id\\|latile\\)\\|wchar_t")) (c++-keywords ; ("break" "continue" "do" "else" "for" "if" "return" "switch" "while" ; "asm" "catch" "delete" "new" "operator" "sizeof" "this" "throw" "try" @@ -2317,62 +2344,110 @@ (1 font-lock-preprocessor-face) (2 font-lock-variable-name-face nil t)) )) - (setq c-font-lock-keywords-2 - (append c-font-lock-keywords-1 - (list - ;; - ;; Simple regexps for speed. - ;; - ;; Fontify all type specifiers. - (cons (concat "\\<\\(" c-type-types "\\)\\>") 'font-lock-type-face) - ;; - ;; Fontify all builtin keywords (except case, default and goto; see below). - (cons (concat "\\<\\(" c-keywords "\\)\\>") 'font-lock-keyword-face) - ;; - ;; Fontify case/goto keywords and targets, and case default/goto tags. - '("\\<\\(case\\|goto\\)\\>[ \t]*\\([^ \t\n:;]+\\)?" - (1 font-lock-keyword-face) (2 font-lock-reference-face nil t)) - '("^[ \t]*\\(\\sw+\\)[ \t]*:" 1 font-lock-reference-face) - ))) - - (setq c-font-lock-keywords-3 - (append c-font-lock-keywords-2 - ;; - ;; More complicated regexps for more complete highlighting for types. - ;; We still have to fontify type specifiers individually, as C is so hairy. - (list - ;; - ;; Fontify all storage classes and type specifiers, plus their items. - (list (concat "\\<\\(" c-type-types "\\)\\>" - "\\([ \t*&]+\\sw+\\>\\)*") - ;; Fontify each declaration item. - '(font-lock-match-c++-style-declaration-item-and-skip-to-next - ;; Start with point after all type specifiers. - (goto-char (or (match-beginning 8) (match-end 1))) - ;; Finish with point after first type specifier. - (goto-char (match-end 1)) - ;; Fontify as a variable or function name. + (let ((cflk2-part-1 + (list + ;; + ;; Simple regexps for speed. + ;; + ;; Fontify all type specifiers. + (cons (concat "\\<\\(" c-type-types "\\)\\>") 'font-lock-type-face))) + (cflk2-part-2 + (list + ;; Fontify all builtin keywords (except case, default and goto; + ;; see below). + (cons (concat "\\<\\(" c-keywords "\\)\\>") 'font-lock-keyword-face) + ;; + ;; Fontify case/goto keywords and targets, and case default/goto tags. + '("\\<\\(case\\|goto\\)\\>[ \t]*\\([^ \t\n:;]+\\)?" + (1 font-lock-keyword-face) (2 font-lock-reference-face nil t)) + '("^[ \t]*\\(\\sw+\\)[ \t]*:" 1 font-lock-reference-face))) + (cflk3-part-1 + ;; + ;; More complicated regexps for more complete highlighting for + ;; types. We still have to fontify type specifiers individually, + ;; as C is so hairy. + (list + ;; + ;; Fontify all storage classes and type specifiers, plus their items. + (list (concat "\\<\\(" c-type-types "\\)\\>" + "\\([ \t*&]+\\sw+\\>\\)*") + ;; Fontify each declaration item. + '(font-lock-match-c++-style-declaration-item-and-skip-to-next + ;; Start with point after all type specifiers. + (goto-char (or (match-beginning 8) (match-end 1))) + ;; Finish with point after first type specifier. + (goto-char (match-end 1)) + ;; Fontify as a variable or function name. + (1 (if (match-beginning 4) + font-lock-function-name-face + font-lock-variable-name-face)))))) + (cflk3-part-2 + (list + ;; + ;; Fontify structures, or typedef names, plus their items. + '("\\(}\\)[ \t*]*\\sw" + (font-lock-match-c++-style-declaration-item-and-skip-to-next + (goto-char (match-end 1)) nil (1 (if (match-beginning 4) font-lock-function-name-face font-lock-variable-name-face)))) - ;; - ;; Fontify structures, or typedef names, plus their items. - '("\\(}\\)[ \t*]*\\sw" - (font-lock-match-c++-style-declaration-item-and-skip-to-next - (goto-char (match-end 1)) nil - (1 (if (match-beginning 4) - font-lock-function-name-face - font-lock-variable-name-face)))) - ;; - ;; Fontify anything at beginning of line as a declaration or definition. - '("^\\(\\sw+\\)\\>\\([ \t*]+\\sw+\\>\\)*" - (1 font-lock-type-face) - (font-lock-match-c++-style-declaration-item-and-skip-to-next - (goto-char (or (match-beginning 2) (match-end 1))) nil - (1 (if (match-beginning 4) - font-lock-function-name-face - font-lock-variable-name-face)))) - ))) + ;; + ;; Fontify anything at beginning of line as a declaration or + ;; definition. + '("^\\(\\sw+\\)\\>\\([ \t*]+\\sw+\\>\\)*" + (1 font-lock-type-face) + (font-lock-match-c++-style-declaration-item-and-skip-to-next + (goto-char (or (match-beginning 2) (match-end 1))) nil + (1 (if (match-beginning 4) + font-lock-function-name-face + font-lock-variable-name-face)))))) + (xcflk2-part-1 + (list + ;; Fontify all simple type specifiers used in XEmacs code. + (cons (concat "\\<\\(" xemacs-c-type-types "\\)\\>") + 'font-lock-type-face))) + (xcflk3-part-1 + ;; + ;; More complicated regexps for more complete highlighting for + ;; types. We still have to fontify type specifiers individually, + ;; as C is so hairy. + (list + ;; + ;; Fontify all storage classes and type specifiers, plus their items. + (list (concat "\\<\\(" xemacs-c-type-types "\\)\\>" + "\\([ \t*&]+\\sw+\\>\\)*") + ;; Fontify each declaration item. + '(font-lock-match-c++-style-declaration-item-and-skip-to-next + ;; Start with point after all type specifiers. + (goto-char (or (match-beginning 8) (match-end 1))) + ;; Finish with point after first type specifier. + (goto-char (match-end 1)) + ;; Fontify as a variable or function name. + (1 (if (match-beginning 4) + font-lock-function-name-face + font-lock-variable-name-face))))))) + + (setq c-font-lock-keywords-2 + (append c-font-lock-keywords-1 + cflk2-part-1 + cflk2-part-2)) + + (setq c-font-lock-keywords-3 + (append c-font-lock-keywords-2 + cflk3-part-1 + cflk3-part-2)) + + (setq xemacs-c-font-lock-keywords-2 + (append c-font-lock-keywords-1 + cflk2-part-1 + xcflk2-part-1 + cflk2-part-2)) + + (setq xemacs-c-font-lock-keywords-3 + (append xemacs-c-font-lock-keywords-2 + cflk3-part-1 + xcflk3-part-1 + cflk3-part-2))) (setq c++-font-lock-keywords-1 (append diff --text -u 'xemacs-21.5.18/lisp/font-menu.el' 'xemacs-21.5.19/lisp/font-menu.el' Index: ./lisp/font-menu.el --- ./lisp/font-menu.el Wed Sep 22 11:05:50 2004 +++ ./lisp/font-menu.el Fri Jan 28 11:58:39 2005 @@ -113,7 +113,7 @@ ;;; ==> ;;; "-morisawa-ryumin light kl-light-r-normal--10-100-72-72-m-50-jisx0201.1976-0" ;;; -;;; (list-fonts "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*") +;;; (font-list "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*") ;;; ==> ;;; ("-dt-interface user-medium-r-normal-s sans-12-120-72-72-m-70-iso8859-1" ;;; "-dt-interface user-medium-r-normal-s-14-120-75-75-m-120-jisx0208.1983-0" diff --text -u 'xemacs-21.5.18/lisp/font.el' 'xemacs-21.5.19/lisp/font.el' Index: ./lisp/font.el --- ./lisp/font.el Sun Mar 9 11:27:33 2003 +++ ./lisp/font.el Fri Jan 28 11:58:40 2005 @@ -2,7 +2,7 @@ ;; Copyright (c) 1995, 1996 by William M. Perry (wmperry@cs.indiana.edu) ;; Copyright (c) 1996, 1997 Free Software Foundation, Inc. -;; Copyright (C) 2002 Ben Wing. +;; Copyright (C) 2002, 2004 Ben Wing. ;; Author: wmperry ;; Maintainer: XEmacs Development Team @@ -32,8 +32,7 @@ ;;; Code: (globally-declare-fboundp - '(x-list-fonts - mswindows-list-fonts ns-list-fonts internal-facep fontsetp get-font-info + '(internal-facep fontsetp get-font-info get-fontset-info mswindows-define-rgb-color cancel-function-timers mswindows-font-regexp mswindows-canonicalize-font-name mswindows-parse-font-style mswindows-construct-font-style @@ -60,13 +59,7 @@ (defmacro defcustom (var value doc &rest args) `(defvar ,var ,value ,doc)))) -(if (not (fboundp 'try-font-name)) - (defun try-font-name (fontname &rest args) - (case window-system - ((x pm) (car-safe (x-list-fonts fontname))) - (mswindows (car-safe (mswindows-list-fonts fontname))) - (ns (car-safe (ns-list-fonts fontname))) - (otherwise nil)))) +; delete alternate defn of try-font-name (if (not (fboundp 'facep)) (defun facep (face) @@ -932,7 +925,7 @@ (defun x-font-build-cache (&optional device) (let ((hash-table (make-hash-table :test 'equal :size 15)) (fonts (mapcar 'x-font-create-object - (x-list-fonts "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"))) + (font-list "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"))) (plist nil) (cur nil)) (while fonts @@ -1064,7 +1057,7 @@ (defun font-lookup-rgb-components (color) "Lookup COLOR (a color name) in rgb.txt and return a list of RGB values. The list (R G B) is returned, or an error is signaled if the lookup fails." - (let ((lib-list (if (boundp 'x-library-search-path) + (let ((lib-list (if-boundp 'x-library-search-path x-library-search-path ;; This default is from XEmacs 19.13 - hope it covers ;; everyone. diff --text -u 'xemacs-21.5.18/lisp/frame.el' 'xemacs-21.5.19/lisp/frame.el' Index: ./lisp/frame.el --- ./lisp/frame.el Tue Mar 9 00:22:49 2004 +++ ./lisp/frame.el Fri Jan 28 11:58:40 2005 @@ -415,7 +415,8 @@ '(t))) t)) ;; Create the new frame. - (let (props new) + (let (props ;new + ) ;; If the frame isn't visible yet, wait till it is. ;; If the user has to position the window, ;; Emacs doesn't know its real position until @@ -454,13 +455,14 @@ (if (lax-plist-member frame-initial-geometry-arguments 'top) (laxremf props 'top)) ;; Now create the replacement initial frame. - (setq new - (make-frame - ;; Use the geometry args that created the existing - ;; frame, rather than the props we get for it. - (append '(user-size t user-position t) - frame-initial-geometry-arguments - props))) + ;(setq new + (make-frame + ;; Use the geometry args that created the existing + ;; frame, rather than the props we get for it. + (append '(user-size t user-position t) + frame-initial-geometry-arguments + props)) + ;) ;; The initial frame, which we are about to delete, may be ;; the only frame with a minibuffer. If it is, create a ;; new one. @@ -992,7 +994,7 @@ (completion-ignore-case t) (font (completing-read "Font name: " (mapcar #'list - (list-fonts "*" frame)) + (font-list "*" frame)) nil nil nil nil (face-font-name 'default frame)))) (list font current-prefix-arg))) @@ -1184,11 +1186,10 @@ (case (framep-on-display display) ;; We assume X, NeXTstep, and GTK *always* have a pointing device ((x ns gtk) t) - (mswindows (> mswindows-num-mouse-buttons 0)) + (mswindows (> (declare-boundp mswindows-num-mouse-buttons) 0)) (tty - (and - (fboundp 'gpm-is-supported-p) - (gpm-is-supported-p (display-device display)))) + (and-fboundp 'gpm-is-supported-p + (gpm-is-supported-p (display-device display)))) (t nil))) (defun display-popup-menus-p (&optional display) @@ -1273,8 +1274,8 @@ The value is one of the symbols `static-gray', `gray-scale', `static-color', `pseudo-color', `true-color', or `direct-color'." (case (framep-on-display display) - (x (x-display-visual-class (display-device display))) - (gtk (gtk-display-visual-class (display-device display))) + (x (declare-fboundp (x-display-visual-class (display-device display)))) + (gtk (declare-fboundp (gtk-display-visual-class (display-device display)))) (mswindows (let ((planes (display-planes display))) (cond ((eq planes 1) 'static-gray) ((eq planes 4) 'static-color) diff --text -u 'xemacs-21.5.18/lisp/gnuserv.el' 'xemacs-21.5.19/lisp/gnuserv.el' Index: ./lisp/gnuserv.el --- ./lisp/gnuserv.el Sat Sep 20 02:07:07 2003 +++ ./lisp/gnuserv.el Tue Dec 14 18:56:48 2004 @@ -419,11 +419,14 @@ ;; backbone of gnuserv.el. (defun gnuserv-edit-files (type list &rest flags) "For each (line-number . file) pair in LIST, edit the file at line-number. -The visited buffers are memorized, so that when \\[gnuserv-edit] is invoked +The visited buffers are recorded, so that when \\[gnuserv-edit] is invoked in such a buffer, or when it is killed, or the client's device deleted, the -client will be invoked that the edit is finished. +client will be informed that the edit is finished. -TYPE should either be a (tty TTY TERM PID) list, or (x DISPLAY) list. +TYPE should be a list in one of the forms (tty TTY TERM PID), (x DISPLAY), +\(gtk DISPLAY), or (mswindows DISPLAY). Currently GTK and MS Windows do not +support multiple displays, so the DISPLAY member is ignored. Conventionally +it is set to nil. If a flag is `quick', just edit the files in Emacs. If a flag is `view', view the files read-only." (let (quick view) diff --text -u 'xemacs-21.5.18/lisp/gtk-font-menu.el' 'xemacs-21.5.19/lisp/gtk-font-menu.el' Index: ./lisp/gtk-font-menu.el --- ./lisp/gtk-font-menu.el Wed Sep 22 11:05:50 2004 +++ ./lisp/gtk-font-menu.el Fri Jan 28 11:58:40 2005 @@ -90,7 +90,7 @@ or if you change your font path, you can call this to re-initialize the menus." ;; by Stig@hackvan.com ;; #### - this should implement a `menus-only' option, which would - ;; recalculate the menus from the cache w/o having to do list-fonts again. + ;; recalculate the menus from the cache w/o having to do font-list again. (unless gtk-font-regexp-ascii (setq gtk-font-regexp-ascii (if (featurep 'mule) (declare-fboundp @@ -102,7 +102,7 @@ family size weight entry monospaced-p dev-cache cache families sizes weights) (dolist (name (cond ((null debug) ; debugging kludge - (list-fonts "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device)) + (font-list "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device)) ((stringp debug) (split-string debug "\n")) (t debug))) (when (and (string-match gtk-font-regexp-ascii name) diff --text -u 'xemacs-21.5.18/lisp/gtk-marshal.el' 'xemacs-21.5.19/lisp/gtk-marshal.el' Index: ./lisp/gtk-marshal.el --- ./lisp/gtk-marshal.el Sun May 2 13:06:52 2004 +++ ./lisp/gtk-marshal.el Fri Jan 28 09:32:20 2005 @@ -261,35 +261,6 @@ (insert "\n #include \"hash.h\" -static int -our_string_eq (const void *st1, const void *st2) -{ - if (!st1) - return st2 ? 0 : 1; - else if (!st2) - return 0; - else - return !strcmp ( (const char *) st1, (const char *) st2); -} - -static unsigned long -our_string_hash (const void *xv) -{ - unsigned int h = 0; - unsigned const char *x = (unsigned const char *) xv; - - if (!x) return 0; - - while (*x) - { - unsigned int g; - h = (h << 4) + *x++; - if ((g = h & 0xf0000000) != 0) - h = (h ^ (g >> 24)) ^ g; - } - - return h; -} static struct hash_table *marshaller_hashtable; @@ -297,7 +268,7 @@ { if (!marshaller_hashtable) { - marshaller_hashtable = make_general_hash_table (100, our_string_hash, our_string_eq); + marshaller_hashtable = make_string_hash_table (100); ") (mapc (lambda (x) diff --text -u 'xemacs-21.5.18/lisp/help.el' 'xemacs-21.5.19/lisp/help.el' Index: ./lisp/help.el --- ./lisp/help.el Wed Sep 15 17:30:26 2004 +++ ./lisp/help.el Tue Feb 1 05:08:45 2005 @@ -1,7 +1,7 @@ ;;; help.el --- help commands for XEmacs. ;; Copyright (C) 1985, 1986, 1992-4, 1997 Free Software Foundation, Inc. -;; Copyright (C) 2001, 2002 Ben Wing. +;; Copyright (C) 2001, 2002, 2003 Ben Wing. ;; Maintainer: FSF ;; Keywords: help, internal, dumped @@ -696,12 +696,17 @@ (defun describe-distribution () "Display info on how to obtain the latest version of XEmacs." (interactive) - (Help-find-file (locate-data-file "DISTRIB"))) + (save-window-excursion + (info) + (Info-find-node "xemacs-faq" "Q1.1.1")) + (switch-to-buffer "*info*")) (defun describe-beta () "Display info on how to deal with Beta versions of XEmacs." (interactive) - (Help-find-file (locate-data-file "BETA"))) + (save-window-excursion + (info "(beta)Top")) + (switch-to-buffer "*info*")) (defun describe-copying () "Display info on how you may redistribute copies of XEmacs." @@ -713,11 +718,6 @@ (interactive) (describe-bindings nil t)) -(defun describe-project () - "Display info on the GNU project." - (interactive) - (Help-find-file (locate-data-file "GNU"))) - (defun describe-no-warranty () "Display info on all the kinds of warranty XEmacs does NOT have." (interactive) diff --text -u 'xemacs-21.5.18/lisp/info.el' 'xemacs-21.5.19/lisp/info.el' Index: ./lisp/info.el --- ./lisp/info.el Wed Jan 21 18:54:27 2004 +++ ./lisp/info.el Mon Dec 6 12:51:21 2004 @@ -392,7 +392,7 @@ "*List of additional directories to search for Info documentation files. These directories are not searched for merging the `dir' file. An example might be something like: -\"/usr/local/lib/xemacs/packages/lisp/calc/\"" +\"/usr/local/lib/xemacs/xemacs-packages/lisp/calc/\"" :type '(repeat directory) :group 'info) diff --text -u 'xemacs-21.5.18/lisp/loadup.el' 'xemacs-21.5.19/lisp/loadup.el' Index: ./lisp/loadup.el --- ./lisp/loadup.el Sat Mar 1 16:25:27 2003 +++ ./lisp/loadup.el Mon Dec 27 21:25:14 2004 @@ -139,7 +139,7 @@ (external-debugging-output (format "\nLoad file %s: not found\n" file)) ;; Uncomment in case of trouble - ;;(print (format "late-packages: %S" late-packages)) + ;;(print (format "late-package-hierarchies: %S" late-package-hierarchies)) ;;(print (format "guessed-roots: %S" (paths-find-emacs-roots invocation-directory invocation-name #'paths-emacs-root-p))) ;;(print (format "guessed-data-roots: %S" (paths-find-emacs-roots invocation-directory invocation-name #'paths-emacs-data-root-p))) nil))) @@ -159,6 +159,13 @@ (defun toolbar-specifier-p (obj) "No toolbar support." nil)) (fmakunbound 'pureload)) + ;; We cannot do this in mule-cmds.el because not all the + ;; appropriate charsets are loaded yet. + (when (and (featurep 'mule) + load-unicode-tables-at-dump-time) + (let ((data-directory (expand-file-name "etc" source-root))) + (load-unicode-tables))) + (packages-load-package-dumped-lisps late-package-load-path) )) ;; end of call-with-condition-handler diff --text -u 'xemacs-21.5.18/lisp/make-docfile.el' 'xemacs-21.5.19/lisp/make-docfile.el' Index: ./lisp/make-docfile.el --- ./lisp/make-docfile.el Sun Mar 2 18:38:39 2003 +++ ./lisp/make-docfile.el Mon Dec 27 21:25:14 2004 @@ -170,7 +170,7 @@ (progn (message "Error: dumped file %s does not exist" arg0) ;; Uncomment in case of difficulties - ;;(message "late-packages: %S" late-packages) + ;;(message "late-package-hierarchies: %S" late-package-hierarchies) ;;(message "guessed-roots: %S" (paths-find-emacs-roots invocation-directory invocation-name #'paths-emacs-root-p)) ;;(message "guessed-data-roots: %S" (paths-find-emacs-roots invocation-directory invocation-name #'paths-emacs-data-root-p)) ) diff --text -u 'xemacs-21.5.18/lisp/map-ynp.el' 'xemacs-21.5.19/lisp/map-ynp.el' Index: ./lisp/map-ynp.el --- ./lisp/map-ynp.el Fri Apr 13 03:21:30 2001 +++ ./lisp/map-ynp.el Thu Feb 3 14:03:38 2005 @@ -231,8 +231,9 @@ (lambda (elt) (format "%c to %s" (nth 0 elt) - (normalize-menu-item-name - (nth 2 elt))))) + (downcase + (normalize-menu-text + (nth 2 elt)))))) action-alist ";\n") (if action-alist ";\n") diff --text -u 'xemacs-21.5.18/lisp/menubar-items.el' 'xemacs-21.5.19/lisp/menubar-items.el' Index: ./lisp/menubar-items.el --- ./lisp/menubar-items.el Mon Apr 19 17:54:50 2004 +++ ./lisp/menubar-items.el Thu Feb 3 14:03:38 2005 @@ -67,148 +67,6 @@ list (butlast list (- (length list) count))))) -(defun submenu-generate-accelerator-spec (list &optional omit-chars-list) - "Add auto-generated accelerator specifications to a submenu. -This can be used to add accelerators to the return value of a menu filter -function. It correctly ignores unselectable items. It will destructively -modify the list passed to it. If an item already has an auto-generated -accelerator spec, this will be removed before the new one is added, making -this function idempotent. - -If OMIT-CHARS-LIST is given, it should be a list of lowercase characters, -which will not be used as accelerators." - (let ((n 0)) - (dolist (item list list) - (cond - ((vectorp item) - (setq n (1+ n)) - (aset item 0 - (concat - (menu-item-generate-accelerator-spec n omit-chars-list) - (menu-item-strip-accelerator-spec (aref item 0))))) - ((consp item) - (setq n (1+ n)) - (setcar item - (concat - (menu-item-generate-accelerator-spec n omit-chars-list) - (menu-item-strip-accelerator-spec (car item))))))))) - -(defun menu-item-strip-accelerator-spec (item) - "Strip an auto-generated accelerator spec off of ITEM. -ITEM should be a string. This removes specs added by -`menu-item-generate-accelerator-spec' and `submenu-generate-accelerator-spec'." - (if (string-match "%_. " item) - (substring item 4) - item)) - -(defun menu-item-generate-accelerator-spec (n &optional omit-chars-list) - "Return an accelerator specification for use with auto-generated menus. -This should be concat'd onto the beginning of each menu line. The spec -allows the Nth line to be selected by the number N. '0' is used for the -10th line, and 'a' through 'z' are used for the following 26 lines. - -If OMIT-CHARS-LIST is given, it should be a list of lowercase characters, -which will not be used as accelerators." - (cond ((< n 10) (concat "%_" (int-to-string n) " ")) - ((= n 10) "%_0 ") - ((<= n 36) - (setq n (- n 10)) - (let ((m 0)) - (while (> n 0) - (setq m (1+ m)) - (while (memq (int-to-char (+ m (- (char-to-int ?a) 1))) - omit-chars-list) - (setq m (1+ m))) - (setq n (1- n))) - (if (<= m 26) - (concat - "%_" - (char-to-string (int-to-char (+ m (- (char-to-int ?a) 1)))) - " ") - ""))) - (t ""))) - -(defcustom menu-max-items 25 - "*Maximum number of items in generated menus. -If number of entries in such a menu is larger than this value, split menu -into submenus of nearly equal length (see `menu-submenu-max-items'). If -nil, never split menu into submenus." - :group 'menu - :type '(choice (const :tag "no submenus" nil) - (integer))) - -(defcustom menu-submenu-max-items 20 - "*Maximum number of items in submenus when splitting menus. -We split large menus into submenus of this many items, and then balance -them out as much as possible (otherwise the last submenu may have very few -items)." - :group 'menu - :type 'integer) - -(defcustom menu-submenu-name-format "%-12.12s ... %.12s" - "*Format specification of the submenu name when splitting menus. -Used by `menu-split-long-menu' if the number of entries in a menu is -larger than `menu-menu-max-items'. -This string should contain one %s for the name of the first entry and -one %s for the name of the last entry in the submenu. -If the value is a function, it should return the submenu name. The -function is be called with two arguments, the names of the first and -the last entry in the menu." - :group 'menu - :type '(choice (string :tag "Format string") - (function))) - -(defun menu-split-long-menu (menu) - "Split MENU according to `menu-max-items' and add accelerator specs. - -You should normally use the idiom - -\(menu-split-long-menu (menu-sort-menu menu)) - -See also `menu-sort-menu'." - (let ((len (length menu))) - (if (or (null menu-max-items) - (<= len menu-max-items)) - (submenu-generate-accelerator-spec menu) - (let* ((outer (/ (+ len (1- menu-submenu-max-items)) - menu-submenu-max-items)) - (inner (/ (+ len (1- outer)) outer)) - (result nil)) - (while menu - (let ((sub nil) - (from (car menu))) - (dotimes (foo (min inner len)) - (setq sub (cons (car menu) sub) - menu (cdr menu))) - (setq len (- len inner)) - (let ((to (car sub))) - (setq sub (nreverse sub)) - (setq result - (cons (cons (if (stringp menu-submenu-name-format) - (format menu-submenu-name-format - (menu-item-strip-accelerator-spec - (aref from 0)) - (menu-item-strip-accelerator-spec - (aref to 0))) - (funcall menu-submenu-name-format - (menu-item-strip-accelerator-spec - (aref from 0)) - (menu-item-strip-accelerator-spec - (aref to 0)))) - (submenu-generate-accelerator-spec sub)) - result))))) - (submenu-generate-accelerator-spec (nreverse result)))))) - -(defun menu-sort-menu (menu) - "Sort MENU alphabetically. - -You should normally use the idiom - -\(menu-split-long-menu (menu-sort-menu menu)) - -See also `menu-split-long-menu'." - (sort menu - #'(lambda (a b) (string-lessp (aref a 0) (aref b 0))))) (defun coding-system-menu-filter (fun active &optional dots) "Filter for menu entries with a submenu listing all coding systems. @@ -225,21 +83,20 @@ (lambda (entry) ...) (lambda (entry) ...)) " - (menu-split-long-menu - (menu-sort-menu - (mapcar - #'(lambda (_csmf_entry) - `[ ,(concat (coding-system-description _csmf_entry) - (if dots "..." "")) - (funcall ,fun ',_csmf_entry) - :active (funcall ,active ',_csmf_entry) - ]) - (delete-if - #'(lambda (name) - (or (coding-system-alias-p name) - (not (eq name (coding-system-name - (coding-system-base name)))))) - (coding-system-list)))))) + (menu-split-long-menu-and-sort + (mapcar + #'(lambda (_csmf_entry) + `[ ,(concat (coding-system-description _csmf_entry) + (if dots "..." "")) + (funcall ,fun ',_csmf_entry) + :active (funcall ,active ',_csmf_entry) + ]) + (delete-if + #'(lambda (name) + (or (coding-system-alias-p name) + (not (eq name (coding-system-name + (coding-system-base name)))))) + (coding-system-list))))) (defconst default-menubar ; (purecopy-menubar ;purespace is dead @@ -422,7 +279,6 @@ ) ) - ("C%_mds" ["Repeat Last Comple%_x Command..." repeat-complex-command] ["E%_valuate Lisp Expression..." eval-expression] @@ -504,13 +360,13 @@ ) "---" ["%_Cut Rectangle" kill-rectangle] + ["%_Prefix Rectangle..." string-rectangle] ("Other %_Rectangles/Register" ["%_Yank Rectangle" yank-rectangle] ["Rectangle %_to Register" copy-rectangle-to-register] ["Rectangle %_from Register" insert-register] ["%_Delete Rectangle" clear-rectangle] ["%_Open Rectangle" open-rectangle] - ["%_Prefix Rectangle..." string-rectangle] ["Rectangle %_Mousing" (customize-set-variable 'mouse-track-rectangle-p (not mouse-track-rectangle-p)) @@ -554,17 +410,27 @@ ["Tab to Tab %_Stop" tab-to-tab-stop] ["Edit Ta%_b Stops" edit-tab-stops] ) - "---" - ("S%_pell-Check" - ["%_Buffer" ispell-buffer - :active (fboundp 'ispell-buffer)] - "---" - ["%_Word" ispell-word] - ["%_Complete Word" ispell-complete-word] - ["%_Region" ispell-region] + "---" + ("%_Tags" + ["%_Find Tag..." find-tag] + ["Find %_Other Window..." find-tag-other-window] + ["%_Next Tag..." (find-tag nil)] + ["N%_ext Other Window..." (find-tag-other-window nil)] + ["Next %_File" next-file] + "-----" + ["Tags %_Search..." tags-search] + ["Tags %_Replace..." tags-query-replace] + ["%_Continue Search/Replace" tags-loop-continue] + "-----" + ["%_Pop stack" pop-tag-mark] + ["%_Apropos..." tags-apropos] + "-----" + ["%_Set Tags Table File..." visit-tags-table] ) ) - + + ;; #### Delete this entire menu as soon as the new package source is + ;; committed. ("%_Tools" ("%_Packages" ("%_Set Download Site" @@ -816,24 +682,10 @@ "----" ) - ("%_Options" - ("%_Behaviors" - :filter - (lambda (menu) - (menu-split-long-menu - (menu-sort-menu - (loop for behavior being the hash-keys in behavior-hash-table - using (hash-value plist) - collect (vector (format "%s (%s)" behavior - (getf plist :short-doc)) - `(if (memq ',behavior enabled-behavior-list) - (disable-behavior ',behavior) - (enable-behavior ',behavior)) - :style 'toggle - :selected `(memq ',behavior - enabled-behavior-list)) - ))))) +; ("%_Tools" +; :filter behavior-menu-filter) + ("%_Options" ("%_Advanced (Customize)" ("%_Emacs" :filter (lambda (&rest junk) (cdr (custom-menu-create 'emacs)))) @@ -1142,17 +994,16 @@ ("Set %_Language Environment" :filter (lambda (menu) - (menu-split-long-menu - (menu-sort-menu - (mapcar #'(lambda (entry) - `[ ,(car entry) - (set-language-environment ',(car entry)) - :style radio - :selected - ,(equal (car entry) - current-language-environment)]) - language-info-alist) - )))) + (menu-split-long-menu-and-sort + (mapcar #'(lambda (entry) + `[ ,(car entry) + (set-language-environment ',(car entry)) + :style radio + :selected + ,(equal (car entry) + current-language-environment)]) + language-info-alist) + ))) ["%_Toggle Input Method" toggle-input-method] ["Select %_Input Method" set-input-method] ))) @@ -1619,6 +1470,8 @@ ["%_Home Page (www.xemacs.org)" xemacs-www-page :active (fboundp 'browse-url)] ["What's %_New in XEmacs" view-emacs-news] + ["B%_eta Info" describe-beta + :included (string-match "beta" emacs-version)] "-----" ("%_Info (Online Docs)" ["%_Info Contents" (Info-goto-node "(dir)")] @@ -1679,18 +1532,17 @@ ("Describe %_Language Support" :filter (lambda (menu) - (menu-split-long-menu - (menu-sort-menu - (mapcar #'(lambda (entry) - `[ ,(car entry) - (describe-language-environment - ',(car entry)) + (menu-split-long-menu-and-sort + (mapcar #'(lambda (entry) + `[ ,(car entry) + (describe-language-environment + ',(car entry)) :style radio :selected ,(equal (car entry) current-language-environment)]) - language-info-alist) - )))) + language-info-alist) + ))) ["Describe %_Input Method" describe-input-method] ["Describe Current %_Coding Systems" describe-current-coding-system] @@ -1702,6 +1554,7 @@ ("%_Other" ["%_Current Installation Info" describe-installation :active (boundp 'Installation-string)] + ["%_Obtaining the Latest Version" describe-distribution] ["%_No Warranty" describe-no-warranty] ["XEmacs %_License" describe-copying] ["Find %_Packages" finder-by-keyword] @@ -1717,16 +1570,16 @@ (defun init-menubar-at-startup () "Don't call this. -Adds `Load .emacs' button to menubar when starting up with -q." - (when (and (not load-user-init-file-p) - (file-exists-p (expand-file-name ".emacs" "~"))) +Adds `Load init files' button to menubar when starting up with -q." + ;; load-user-init-file finds the init files itself now + (when (not load-user-init-file-p) (add-menu-button nil - ["%_Load .emacs" + ["%_Load init files" (progn (mapc #'(lambda (buf) (with-current-buffer buf - (delete-menu-item '("Load .emacs")))) + (delete-menu-item '("Load init files")))) (buffer-list)) (load-user-init-file)) ] @@ -2046,35 +1899,6 @@ 'list-buffers))) -;;; The Options menu - -;; We'll keep those variables here for a while, in order to provide a -;; function for porting the old options file that a user may own to Custom. - -(defvar options-save-faces nil - "*Non-nil value means save-options will save information about faces. -A nil value means save-options will not save face information. -Set this non-nil only if you use M-x edit-faces to change face -settings. If you use M-x customize-face or the \"Browse Faces...\" -menu entry, you will see a button in the Customize Face buffer that you -can use to permanently save your face changes. - -M-x edit-faces is deprecated. Support for it and this variable will -be discontinued in a future release.") - -(defvar save-options-init-file nil - "File into which to save forms to load the options file (nil for .emacs). -Normally this is nil, which means save into your .emacs file (the value -of `user-init-file'.") - -(defvar save-options-file ".xemacs-options" - "File to save options into. -This file is loaded from your .emacs file. -If this is a relative filename, it is put into the same directory as your -.emacs file.") - - - ;;; The Help menu (defun tutorials-menu-filter (menu-items) @@ -2136,27 +1960,6 @@ (setq-default mode-popup-menu default-popup-menu) -;; misc - -(defun xemacs-splash-buffer () - "Redisplay XEmacs splash screen in a buffer." - (interactive) - (let ((buffer (get-buffer-create "*Splash*")) - tmout) - (set-buffer buffer) - (setq buffer-read-only t) - (erase-buffer buffer) - (setq tmout (display-splash-frame)) - (when tmout - (make-local-hook 'kill-buffer-hook) - (add-hook 'kill-buffer-hook - `(lambda () - (disable-timeout ,tmout)) - nil t)) - (pop-to-buffer buffer) - (delete-other-windows))) - - ;;; backwards compatibility (provide 'x-menubar) (provide 'menubar-items) diff --text -u 'xemacs-21.5.18/lisp/menubar.el' 'xemacs-21.5.19/lisp/menubar.el' Index: ./lisp/menubar.el --- ./lisp/menubar.el Thu Dec 20 14:49:31 2001 +++ ./lisp/menubar.el Tue Feb 8 04:30:08 2005 @@ -2,7 +2,7 @@ ;; Copyright (C) 1991-4, 1997-1998 Free Software Foundation, Inc. ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. -;; Copyright (C) 1995, 1996 Ben Wing. +;; Copyright (C) 1995, 1996, 2003 Ben Wing. ;; Maintainer: XEmacs Development Team ;; Keywords: internal, extensions, dumped @@ -163,17 +163,27 @@ (setq menu (cdr menu))))) -;;; menu manipulation functions +;;; basic menu manipulation functions -(defun find-menu-item (menubar item-path-list &optional parent) - "Search MENUBAR for item given by ITEM-PATH-LIST starting from PARENT. +(defun menu-item-text (item &optional normalize) + "Return the text that is displayed for a menu item. +If ITEM is a string (unselectable text), it is returned; otherwise, +the first element of the cons or vector is returned. +If NORMALIZE is non-nil, pass the text through `normalize-menu-text' +before being returned, to remove accelerator specs and convert %% to %." + (let ((val (if (stringp item) item (elt item 0)))) + (if normalize (normalize-menu-text val) val))) + +(defun find-menu-item (menubar item-path-list) + "Search MENUBAR for item given by ITEM-PATH-LIST. Returns (ITEM . PARENT), where PARENT is the immediate parent of the item found. If the item does not exist, the car of the returned value is nil. If some menu in the ITEM-PATH-LIST does not exist, an error is signalled." + (find-menu-item-1 menubar item-path-list)) + +(defun find-menu-item-1 (menubar item-path-list &optional parent) (check-argument-type 'listp item-path-list) - (unless parent - (setq item-path-list (mapcar 'normalize-menu-item-name item-path-list))) (if (not (consp menubar)) nil (let ((rest menubar) @@ -184,20 +194,15 @@ (setq rest (cddr rest))) (while rest (if (and (car rest) - (equal (car item-path-list) - (normalize-menu-item-name - (cond ((vectorp (car rest)) - (aref (car rest) 0)) - ((stringp (car rest)) - (car rest)) - (t - (caar rest)))))) + (stringp (car item-path-list)) + (= 0 (compare-menu-text (car item-path-list) + (menu-item-text (car rest))))) (setq result (car rest) rest nil) (setq rest (cdr rest)))) (if (cdr item-path-list) (cond ((consp result) - (find-menu-item (cdr result) (cdr item-path-list) result)) + (find-menu-item-1 (cdr result) (cdr item-path-list) result)) (result (signal 'error (list (gettext "not a submenu") result))) (t @@ -208,7 +213,6 @@ (defun add-menu-item-1 (leaf-p menu-path new-item before in-menu) ;; This code looks like it could be cleaned up some more ;; Do we really need 6 calls to find-menu-item? - (when before (setq before (normalize-menu-item-name before))) (let* ((item-name (cond ((vectorp new-item) (aref new-item 0)) ((consp new-item) (car new-item)) @@ -464,6 +468,151 @@ (enable-menu-item-1 path t nil)) +;;; functions for manipulating whole menus -- adding accelerators, sorting, +;;; splitting long menus, etc. + +(defun submenu-generate-accelerator-spec (list &optional omit-chars-list) + "Add auto-generated accelerator specifications to a submenu. +This can be used to add accelerators to the return value of a menu filter +function. It correctly ignores unselectable items. It will destructively +modify the list passed to it. If an item already has an auto-generated +accelerator spec, this will be removed before the new one is added, making +this function idempotent. + +If OMIT-CHARS-LIST is given, it should be a list of lowercase characters, +which will not be used as accelerators." + (let ((n 0)) + (dolist (item list list) + (cond + ((or (vectorp item) (consp item)) + (incf n) + (setf (elt item 0) + (concat + (menu-item-generate-accelerator-spec n omit-chars-list) + (menu-item-strip-accelerator-spec (elt item 0))))))))) + +(defun menu-item-strip-accelerator-spec (item) + "Strip an auto-generated accelerator spec off of ITEM. +ITEM should be a string. This removes specs added by +`menu-item-generate-accelerator-spec' and `submenu-generate-accelerator-spec'." + (if (string-match "%_. " item) + (substring item 4) + item)) + +(defun menu-item-generate-accelerator-spec (n &optional omit-chars-list) + "Return an accelerator specification for use with auto-generated menus. +This should be concat'd onto the beginning of each menu line. The spec +allows the Nth line to be selected by the number N. '0' is used for the +10th line, and 'a' through 'z' are used for the following 26 lines. + +If OMIT-CHARS-LIST is given, it should be a list of lowercase characters, +which will not be used as accelerators." + (cond ((< n 10) (concat "%_" (int-to-string n) " ")) + ((= n 10) "%_0 ") + ((<= n 36) + (setq n (- n 10)) + (let ((m 0)) + (while (> n 0) + (setq m (1+ m)) + (while (memq (int-to-char (+ m (- (char-to-int ?a) 1))) + omit-chars-list) + (setq m (1+ m))) + (setq n (1- n))) + (if (<= m 26) + (concat + "%_" + (char-to-string (int-to-char (+ m (- (char-to-int ?a) 1)))) + " ") + ""))) + (t ""))) + +(defcustom menu-max-items 25 + "*Maximum number of items in generated menus. +If number of entries in such a menu is larger than this value, split menu +into submenus of nearly equal length (see `menu-submenu-max-items'). If +nil, never split menu into submenus." + :group 'menu + :type '(choice (const :tag "no submenus" nil) + (integer))) + +(defcustom menu-submenu-max-items 20 + "*Maximum number of items in submenus when splitting menus. +We split large menus into submenus of this many items, and then balance +them out as much as possible (otherwise the last submenu may have very few +items)." + :group 'menu + :type 'integer) + +(defcustom menu-submenu-name-format "%-12.12s ... %.12s" + "*Format specification of the submenu name when splitting menus. +Used by `menu-split-long-menu' if the number of entries in a menu is +larger than `menu-menu-max-items'. +This string should contain one %s for the name of the first entry and +one %s for the name of the last entry in the submenu. +If the value is a function, it should return the submenu name. The +function is be called with two arguments, the names of the first and +the last entry in the menu." + :group 'menu + :type '(choice (string :tag "Format string") + (function))) + +(defun menu-split-long-menu-and-sort (menu) + "Sort MENU, split according to `menu-max-items' and add accelerator specs. +This is useful for menus generated by filter functions, to make them look +nice. This is equivalent to + +\(menu-split-long-menu (menu-sort-menu menu)) + +and you can call those functions individually if necessary. +You can also call `submenu-generate-accelerator-spec' yourself to add +accelerator specs -- this works even if the specs have already been added." + (menu-split-long-menu (menu-sort-menu menu))) + +(defun menu-split-long-menu (menu) + "Split MENU according to `menu-max-items' and add accelerator specs. +If MENU already has accelerator specs, they will be removed and new ones +generated. You should normally use `menu-split-long-menu-and-sort' instead. +The menu should already be sorted to get meaningful results when it is +split, since the outer menus are of the format `FROM ... TO'." + (let ((len (length menu))) + (if (or (null menu-max-items) + (<= len menu-max-items)) + (submenu-generate-accelerator-spec menu) + (let* ((outer (/ (+ len (1- menu-submenu-max-items)) + menu-submenu-max-items)) + (inner (/ (+ len (1- outer)) outer)) + (result nil)) + (while menu + (let ((sub nil) + (from (car menu))) + (dotimes (foo (min inner len)) + (setq sub (cons (car menu) sub) + menu (cdr menu))) + (setq len (- len inner)) + (let* ((to (car sub)) + (ftext (menu-item-strip-accelerator-spec + (menu-item-text from))) + (ttext (menu-item-strip-accelerator-spec + (menu-item-text to)))) + (setq sub (nreverse sub)) + (setq result + (cons (cons (if (stringp menu-submenu-name-format) + (format menu-submenu-name-format + ftext ttext) + (funcall menu-submenu-name-format + ftext ttext)) + (submenu-generate-accelerator-spec sub)) + result))))) + (submenu-generate-accelerator-spec (nreverse result)))))) + +(defun menu-sort-menu (menu) + "Sort MENU alphabetically. +You should normally use `menu-split-long-menu-and-sort' instead." + (sort menu + #'(lambda (a b) (< (compare-menu-text + (menu-item-text a) (menu-item-text b)) + 0)))) + ;;;;;;; popup menus diff --text -u 'xemacs-21.5.18/lisp/minibuf.el' 'xemacs-21.5.19/lisp/minibuf.el' Index: ./lisp/minibuf.el --- ./lisp/minibuf.el Sat Apr 17 18:59:24 2004 +++ ./lisp/minibuf.el Fri Jan 28 11:58:40 2005 @@ -2181,75 +2181,8 @@ "Read the name of a face from the minibuffer and return it as a symbol." (intern (completing-read prompt obarray 'find-face must-match))) -;; #### - wrong place for this variable? Exactly. We probably want -;; `color-list' to be a console method, so `tty-color-list' becomes -;; obsolete, and `read-color-completion-table' conses (mapcar #'list -;; (color-list)), optionally caching the results. - -;; Ben wanted all of the possibilities from the `configure' script used -;; here, but I think this is way too many. I already trimmed the R4 variants -;; and a few obvious losers from the list. --Stig -(defvar x-library-search-path '("/usr/X11R6/lib/X11/" - "/usr/X11R5/lib/X11/" - "/usr/lib/X11R6/X11/" - "/usr/lib/X11R5/X11/" - "/usr/local/X11R6/lib/X11/" - "/usr/local/X11R5/lib/X11/" - "/usr/local/lib/X11R6/X11/" - "/usr/local/lib/X11R5/X11/" - "/usr/X11/lib/X11/" - "/usr/lib/X11/" - "/usr/local/lib/X11/" - "/usr/X386/lib/X11/" - "/usr/x386/lib/X11/" - "/usr/XFree86/lib/X11/" - "/usr/unsupported/lib/X11/" - "/usr/athena/lib/X11/" - "/usr/local/x11r5/lib/X11/" - "/usr/lpp/Xamples/lib/X11/" - "/usr/openwin/lib/X11/" - "/usr/openwin/share/lib/X11/") - "Search path used by `read-color' to find rgb.txt.") - -(defvar x-read-color-completion-table) - (defun read-color-completion-table () - (case (device-type) - ;; #### Evil device-type dependency - ((x gtk) - (if (boundp 'x-read-color-completion-table) - x-read-color-completion-table - (let ((rgb-file (locate-file "rgb.txt" x-library-search-path)) - clist color p) - (if (not rgb-file) - ;; prevents multiple searches for rgb.txt if we can't find it - (setq x-read-color-completion-table nil) - (with-current-buffer (get-buffer-create " *colors*") - (reset-buffer (current-buffer)) - (insert-file-contents rgb-file) - (while (not (eobp)) - ;; skip over comments - (while (looking-at "^!") - (end-of-line) - (forward-char 1)) - (skip-chars-forward "0-9 \t") - (setq p (point)) - (end-of-line) - (setq color (buffer-substring p (point)) - clist (cons (list color) clist)) - ;; Ugh. If we want to be able to complete the lowercase form - ;; of the color name, we need to add it twice! Yuck. - (let ((dcase (downcase color))) - (or (string= dcase color) - (push (list dcase) clist))) - (forward-char 1)) - (kill-buffer (current-buffer)))) - (setq x-read-color-completion-table clist) - x-read-color-completion-table))) - (mswindows - (mapcar #'list (declare-fboundp (mswindows-color-list)))) - (tty - (mapcar #'list (declare-fboundp (tty-color-list)))))) + (mapcar #'list (color-list))) (defun read-color (prompt &optional must-match initial-contents) "Read the name of a color from the minibuffer. diff --text -u 'xemacs-21.5.18/lisp/mouse.el' 'xemacs-21.5.19/lisp/mouse.el' Index: ./lisp/mouse.el --- ./lisp/mouse.el Fri Mar 29 13:46:33 2002 +++ ./lisp/mouse.el Wed Jan 26 13:47:14 2005 @@ -2,7 +2,7 @@ ;; Copyright (C) 1988, 1992-4, 1997 Free Software Foundation, Inc. ;; Copyright (C) 1995 Tinker Systems -;; Copyright (C) 1995, 1996, 2000, 2002 Ben Wing. +;; Copyright (C) 1995, 1996, 2000, 2002, 2004, 2005 Ben Wing. ;; Maintainer: XEmacs Development Team ;; Keywords: mouse, dumped @@ -507,11 +507,52 @@ :type '(choice integer (const :tag "Disabled" nil)) :group 'mouse) -(defcustom mouse-track-activate-strokes '(button1-double-click button2-click) - "List of mouse strokes that can cause \"activation\" of the text extent -under the mouse. The exact meaning of \"activation\" is dependent on the -text clicked on and the mode of the buffer, but typically entails actions -such as following a hyperlink or selecting an entry in a completion buffer. +(defcustom mouse-track-activate-strokes '(button1-click button1-double-click + button2-click) + "Mouse strokes causing \"activation\" of the text extent under the mouse. +The exact meaning of \"activation\" is dependent on the text clicked on and +the mode of the buffer, but typically entails actions such as following a +hyperlink or selecting an entry in a completion buffer. + +See also `mouse-track-conservative-activate-strokes'. + +Possible list entries are + +button1-click +button1-double-click +button1-triple-click +button1-down +button2-click +button2-double-click +button2-triple-click +button2-down + +As a general rule, you should not use the \"-down\" values, because this +makes it impossible to have other simultaneous actions, such as selection." + :type '(set + button1-click + button1-double-click + button1-triple-click + button1-down + button2-click + button2-double-click + button2-triple-click + button2-down) + :group 'mouse) + +(defcustom mouse-track-conservative-activate-strokes + '(button1-double-click button2-click) + "Mouse strokes causing \"conservative activation\" of text extent under mouse. +The exact meaning of \"activation\" is dependent on the text clicked on and +the mode of the buffer, but typically entails actions such as following a +hyperlink or selecting an entry in a completion buffer. + +\"Conservative activation\" differs from regular activation in that it is +not meant to be triggered by a button1 click, and thus is suitable for larger +regions of text where the user might want to position the cursor inside of +the region. + +See also `mouse-track-activate-strokes'. Possible list entries are @@ -573,15 +614,6 @@ 'mouse-track-scroll-undefined (copy-event event))))) -(defun mouse-track-do-activate (event) - "Execute the activate function under EVENT, if any. -Return true if the function was activated." - (let ((ex (extent-at-event event 'activate-function))) - (when ex - (funcall (extent-property ex 'activate-function) - event ex) - t))) - (defvar Mouse-track-gensym (gensym)) (defun mouse-track-run-hook (hook override event &rest args) @@ -1210,16 +1242,61 @@ (4 . button4) (5 . button5)))) (event-modifiers event))))) +;; return t if an activation function was called. This checks to see +;; if the appropriate stroke for the click count and the button that +;; was pressed is present in `mouse-track-activate-strokes'; if so, it +;; looks for an extent under the mouse with an `activate-function' +;; property, calls it and returns t. Else, it repeats the whole +;; process with `mouse-track-conservative-activate-strokes' and +;; `conservative-activate-function'. +(defun default-mouse-track-check-for-activation (event click-count + count-list button-list) + (flet ((do-activate (event property) + (let ((ex (extent-at-event event property))) + (when ex + (funcall (extent-property ex property) event ex) + t)))) + (or + (and (some #'(lambda (count button) + (and (= click-count count) + (memq button + mouse-track-activate-strokes))) + count-list button-list) + (do-activate event 'activate-function)) + (and (some #'(lambda (count button) + (and (= click-count count) + (memq button + mouse-track-conservative-activate-strokes))) + count-list button-list) + (do-activate event 'conservative-activate-function))))) + (defun default-mouse-track-down-hook (event click-count) (cond ((default-mouse-track-event-is-with-button event 1) - (if (and (memq 'button1-down mouse-track-activate-strokes) - (mouse-track-do-activate event)) + (if (default-mouse-track-check-for-activation + event 1 '(1) '(button1-down)) t (setq default-mouse-track-down-event (copy-event event)) nil)) ((default-mouse-track-event-is-with-button event 2) - (and (memq 'button2-down mouse-track-activate-strokes) - (mouse-track-do-activate event))))) + (default-mouse-track-check-for-activation + event 1 '(1) '(button2-down))))) + +(defun default-mouse-track-click-hook (event click-count) + (cond ((default-mouse-track-event-is-with-button event 1) + (if (default-mouse-track-check-for-activation + event click-count '(1 2 3) '(button1-click button1-double-click + button1-triple-click)) + t + (default-mouse-track-drag-hook event click-count nil) + (default-mouse-track-drag-up-hook event click-count) + t)) + ((default-mouse-track-event-is-with-button event 2) + (if (default-mouse-track-check-for-activation + event click-count '(1 2 3) '(button2-click button2-double-click + button2-triple-click)) + t + (mouse-yank event) + t)))) (defun default-mouse-track-cleanup-extents-hook () (remove-hook 'pre-command-hook 'default-mouse-track-cleanup-extents-hook) @@ -1329,44 +1406,10 @@ (default-mouse-track-maybe-own-selection result 'PRIMARY))) t)) -(defun default-mouse-track-click-hook (event click-count) - (cond ((default-mouse-track-event-is-with-button event 1) - (if (and - (or (and (= click-count 1) - (memq 'button1-click - mouse-track-activate-strokes)) - (and (= click-count 2) - (memq 'button1-double-click - mouse-track-activate-strokes)) - (and (= click-count 3) - (memq 'button1-triple-click - mouse-track-activate-strokes))) - (mouse-track-do-activate event)) - t - (default-mouse-track-drag-hook event click-count nil) - (default-mouse-track-drag-up-hook event click-count) - t)) - ((default-mouse-track-event-is-with-button event 2) - (if (and - (or (and (= click-count 1) - (memq 'button2-click - mouse-track-activate-strokes)) - (and (= click-count 2) - (memq 'button2-double-click - mouse-track-activate-strokes)) - (and (= click-count 3) - (memq 'button2-triple-click - mouse-track-activate-strokes))) - (mouse-track-do-activate event)) - t - (mouse-yank event) - t)))) - - (add-hook 'mouse-track-down-hook 'default-mouse-track-down-hook) +(add-hook 'mouse-track-click-hook 'default-mouse-track-click-hook) (add-hook 'mouse-track-drag-hook 'default-mouse-track-drag-hook) (add-hook 'mouse-track-drag-up-hook 'default-mouse-track-drag-up-hook) -(add-hook 'mouse-track-click-hook 'default-mouse-track-click-hook) (add-hook 'mouse-track-cleanup-hook 'default-mouse-track-cleanup-hook) diff --text -u 'xemacs-21.5.18/lisp/msw-faces.el' 'xemacs-21.5.19/lisp/msw-faces.el' Index: ./lisp/msw-faces.el --- ./lisp/msw-faces.el Sun Mar 9 11:27:33 2003 +++ ./lisp/msw-faces.el Fri Jan 28 11:58:40 2005 @@ -271,7 +271,7 @@ (and (string-match mswindows-font-regexp name) (string-to-int (substring name (match-beginning 3) (match-end 3))))) - (list-fonts font device))) + (font-list font device))) #'<)) (defun mswindows-frob-font-size (font up-p device) diff --text -u 'xemacs-21.5.18/lisp/msw-font-menu.el' 'xemacs-21.5.19/lisp/msw-font-menu.el' Index: ./lisp/msw-font-menu.el --- ./lisp/msw-font-menu.el Fri Jun 21 06:18:04 2002 +++ ./lisp/msw-font-menu.el Fri Jan 28 11:58:40 2005 @@ -74,7 +74,7 @@ family size weight entry dev-cache cache families sizes weights) (dolist (name (cond ((null debug) ; debugging kludge - (list-fonts "::::" device)) + (font-list "::::" device)) ((stringp debug) (split-string debug "\n")) (t debug))) (when (and (string-match mswindows-font-regexp-ascii name) diff --text -u 'xemacs-21.5.18/lisp/mule/devan-util.el' 'xemacs-21.5.19/lisp/mule/devan-util.el' Index: ./lisp/mule/devan-util.el --- ./lisp/mule/devan-util.el Thu Mar 21 16:30:21 2002 +++ ./lisp/mule/devan-util.el Tue Nov 16 05:15:22 2004 @@ -228,7 +228,7 @@ "\\)\\|\\(" devanagari-cons-vowel-syllable "\\)\\|\\(" devanagari-other-sign "\\)\\|\\(" devanagari-digit-viram-visarga "\\)") - "Regexp matching to Devanagari string to be composed form one glyph.") + "Regexp matching Devanagari string to be composed from one glyph.") ;;(put-charset-property charset-devanagari-1-column ;; 'char-to-glyph 'devanagari-compose-string) diff --text -u 'xemacs-21.5.18/lisp/mule/european.el' 'xemacs-21.5.19/lisp/mule/european.el' Index: ./lisp/mule/european.el --- ./lisp/mule/european.el Tue Jun 4 15:04:29 2002 +++ ./lisp/mule/european.el Thu Feb 10 03:06:40 2005 @@ -4,7 +4,7 @@ ;; Licensed to the Free Software Foundation. ;; Copyright (C) 1997 MORIOKA Tomohiko ;; Copyright (C) 2001 Ben Wing. -;; Copyright (C) 2002 Free Software Foundation +;; Copyright (C) 2002, 2005 Free Software Foundation ;; Keywords: multilingual, European @@ -27,8 +27,8 @@ ;;; Commentary: -;; For Europeans, six coded character sets ISO8859-1,2,3,4,9 are supported. -;; Note: ISO 8859/15 (Latin-9) is supported via the latin-unity package. +;; For Roman-alphabet-using Europeans, eight coded character sets, +;; ISO8859-1,2,3,4,9,14,15,16 are supported. ;; #### latin.el would be a better name for this file. @@ -131,6 +131,27 @@ long-name "RHP of Latin-8 (ISO 8859-14)" )) +(make-charset 'latin-iso8859-16 + "Right-Hand Part of Latin Alphabet 10 (ISO/IEC 8859-16)" + '(dimension + 1 + registry "ISO8859-16" + chars 96 + columns 1 + direction l2r + final ?f ; octet 06/06; cf ISO-IR 226 + graphic 1 + short-name "RHP of Latin-10" + long-name "RHP of Latin-10 (ISO 8859-16)" + )) + +(loop for c from 64 to 127 + do (modify-syntax-entry (make-char 'latin-iso8859-16 c) "w")) +(mapc (lambda (c) + (modify-syntax-entry (make-char 'latin-iso8859-16 c) "w")) + '(#xA1 #xA2 #xA3 #xA6 #xA8 #xAA #xAC #xAE #xAF + #xB3 #xB4 #xB5 #xB8 #xB9 #xBA #xBC #xBD #xBE #xBF)) + ;; For syntax of Latin-1 characters. (loop for c from 64 to 127 ; from ',A@(B' to ',A(B' @@ -351,6 +372,15 @@ mnemonic "MIME/Ltn-5" )) +;; Add a coding system for ISO 8859-16. +(make-coding-system + 'iso-8859-16 'iso2022 "MIME ISO-8859-16" + '(charset-g0 ascii + charset-g1 latin-iso8859-16 + charset-g2 t ; grrr + charset-g3 t ; grrr + mnemonic "MIME/Ltn-10")) + (loop for ((charset codesys default-input nice-charset-1 nice-charset-2 supported-langs ;; a list if the doc string is replaced ;; entirely diff --text -u 'xemacs-21.5.18/lisp/mule/mule-ccl.el' 'xemacs-21.5.19/lisp/mule/mule-ccl.el' Index: ./lisp/mule/mule-ccl.el --- ./lisp/mule/mule-ccl.el Wed Mar 13 17:52:16 2002 +++ ./lisp/mule/mule-ccl.el Fri Nov 5 08:06:01 2004 @@ -1267,18 +1267,18 @@ STATEMENT := SET | IF | BRANCH | LOOP | REPEAT | BREAK | READ | WRITE | CALL - | TRANSLATE | END + | TRANSLATE | MAP | END SET := (REG = EXPRESSION) | (REG ASSIGNMENT_OPERATOR EXPRESSION) - ;; The following form is the same as (r0 = integer). - | integer + ;; The following form is the same as (r0 = INT-OR-CHAR). + | INT-OR-CHAR EXPRESSION := ARG | (EXPRESSION OPERATOR ARG) ;; Evaluate EXPRESSION. If the result is nonzeor, execute ;; CCL_BLOCK_0. Otherwise, execute CCL_BLOCK_1. -IF := (if EXPRESSION CCL_BLOCK_0 CCL_BLOCK_1) +IF := (if EXPRESSION CCL_BLOCK_0 [CCL_BLOCK_1]) ;; Evaluate EXPRESSION. Provided that the result is N, execute ;; CCL_BLOCK_N. @@ -1293,24 +1293,24 @@ REPEAT := ;; Jump to the head of the most inner loop. (repeat) - ;; Same as: ((write [REG | integer | string]) + ;; Same as: ((write [REG | INT-OR-CHAR | string]) ;; (repeat)) - | (write-repeat [REG | integer | string]) + | (write-repeat [REG | INT-OR-CHAR | string]) ;; Same as: ((write REG [ARRAY]) ;; (read REG) ;; (repeat)) | (write-read-repeat REG [ARRAY]) - ;; Same as: ((write integer) + ;; Same as: ((write INT-OR-CHAR) ;; (read REG) ;; (repeat)) - | (write-read-repeat REG integer) + | (write-read-repeat REG INT-OR-CHAR) READ := ;; Set REG_0 to a byte read from the input text, set REG_1 ;; to the next byte read, and so on. (read REG_0 [REG_1 ...]) ;; Same as: ((read REG) ;; (if (REG OPERATOR ARG) CCL_BLOCK_0 CCL_BLOCK_1)) - | (read-if (REG OPERATOR ARG) CCL_BLOCK_0 CCL_BLOCK_1) + | (read-if (REG OPERATOR ARG) CCL_BLOCK_0 [CCL_BLOCK_1]) ;; Same as: ((read REG) ;; (branch REG CCL_BLOCK_0 [CCL_BLOCK_1 ...])) | (read-branch REG CCL_BLOCK_0 [CCL_BLOCK_1 ...]) @@ -1330,10 +1330,10 @@ ;; Same as: ((r7 = EXPRESSION) ;; (write r7)) | (write EXPRESSION) - ;; Write the value of `integer' to the output buffer. If it + ;; Write the value of `INT-OR-CHAR' to the output buffer. If it ;; is a multibyte character, write the corresponding multibyte ;; representation. - | (write integer) + | (write INT-OR-CHAR) ;; Write the byte sequence of `string' as is to the output ;; buffer. It is encoded by binary coding system, thus, ;; by this operation, you cannot write multibyte string @@ -1356,6 +1356,17 @@ ;; Call CCL program whose name is ccl-program-name. CALL := (call ccl-program-name) +TRANSLATE := + (translate-character REG(table) REG(charset) REG(codepoint)) + | (translate-character SYMBOL REG(charset) REG(codepoint)) +MAP := + (iterate-multiple-map REG REG MAP-IDs) + | (map-multiple REG REG (MAP-SET)) + | (map-single REG REG MAP-ID) +MAP-IDs := MAP-ID ... +MAP-SET := MAP-IDs | (MAP-IDs) MAP-SET +MAP-ID := INT-OR-CHAR + ;; Terminate the CCL program. END := (end) @@ -1363,7 +1374,7 @@ ;; used by CCL interpreter, its value is changed unexpectedly. REG := r0 | r1 | r2 | r3 | r4 | r5 | r6 | r7 -ARG := REG | integer +ARG := REG | INT-OR-CHAR OPERATOR := ;; Normal arithmethic operators (same meaning as C code). @@ -1429,19 +1440,9 @@ ;; (REG /= ARG)) | //= -ARRAY := `[' integer ... `]' +ARRAY := `[' INT-OR-CHAR ... `]' - -TRANSLATE := - (translate-character REG(table) REG(charset) REG(codepoint)) - | (translate-character SYMBOL REG(charset) REG(codepoint)) -MAP := - (iterate-multiple-map REG REG MAP-IDs) - | (map-multiple REG REG (MAP-SET)) - | (map-single REG REG MAP-ID) -MAP-IDs := MAP-ID ... -MAP-SET := MAP-IDs | (MAP-IDs) MAP-SET -MAP-ID := integer +INT-OR-CHAR := integer | character " `(let ((prog ,(ccl-compile (eval ccl-program)))) (defconst ,name prog ,doc) diff --text -u 'xemacs-21.5.18/lisp/mule/mule-cmds.el' 'xemacs-21.5.19/lisp/mule/mule-cmds.el' Index: ./lisp/mule/mule-cmds.el --- ./lisp/mule/mule-cmds.el Fri Feb 21 15:56:50 2003 +++ ./lisp/mule/mule-cmds.el Fri Nov 5 08:06:02 2004 @@ -1348,47 +1348,16 @@ (defun init-mule-at-startup () "Initialize MULE environment at startup. Don't call this." - ;; Fill up the Unicode translation tables for the standard charsets. - ;; Currently this needs to happen after data-directory gets - ;; initialized, which is not long in the startup process before we - ;; are called. However, in reality this is WAY TOO LATE for this to - ;; be happening. All manner of stuff involving paths happens - ;; beforehand, and eventually we want to be able to invoke XEmacs - ;; from a path with Japanese in it without problem. Everything else - ;; is carefully set up to get the coding systems ready before we - ;; have to consult any paths or similarly interact with the system - ;; (except possibly finding the dump file). We need to find a way - ;; of dumping the data that we use to build the tables along with - ;; the rest of the dump data, i.e. in the same file as it or ideally - ;; as a resource attached to the executable itself, so we have - ;; access to it extremely early; then, we call - ;; init-unicode-at-startup from init_intl(), which should (perhaps) - ;; be soon enough. - - ;; An alternative is to resurrect my attempts to actually dump the - ;; created tables, which would completely solve things, although - ;; they're somewhat big (HOW BIG? INVESTIGATE) and this would - ;; preclude demand-loading the data. Another possibility would be - ;; to load the tables into memory at dump time (after writing them - ;; out in some super-compressed binary form). Yet another is to - ;; spit out the table data out in C code, which is then compiled in. - - ;; We need to go through these, compile a list of what sorts of - ;; multilingual things we want to do early at startup (start XEmacs - ;; from a Japanese or other multilingual directory? Can we then - ;; find the dump file? If the dump file is elsewhere in a Japanese - ;; directory? etc.) and see what we get with the different - ;; possibilities, and what are their strengths and weaknesses. - - (init-unicode-at-startup) - - ;; This is called (currently; might be moved earlier) from startup.el, after - ;; the basic GUI systems have been initialized, and just before the - ;; init file gets read in. It needs to finish up initializing the current - ;; language environment. Very early in the startup procedure we determined - ;; the default language environment from the locale, and bootstrapped the - ;; native, file-name and process I/O coding systems. Now we need to do it - ;; over `the right away'. + (when (not load-unicode-tables-at-dump-time) + (load-unicode-tables)) + + ;; This is called (currently; might be moved earlier) from startup.el, + ;; after the basic GUI systems have been initialized, and just before the + ;; init file gets read in. It needs to finish up initializing the + ;; current language environment. Very early in the startup procedure we + ;; determined the default language environment from the locale, and + ;; bootstrapped the native, file-name and process I/O coding systems. + ;; Now we need to do it over `the right away'. (finish-set-language-environment current-language-environment) ;; Load a (localizable) locale-specific init file, if it exists. diff --text -u 'xemacs-21.5.18/lisp/mwheel.el' 'xemacs-21.5.19/lisp/mwheel.el' Index: ./lisp/mwheel.el --- ./lisp/mwheel.el Wed Aug 13 20:22:43 2003 +++ ./lisp/mwheel.el Thu Feb 3 14:26:41 2005 @@ -126,6 +126,18 @@ (setq keys (cdr keys))) (error nil)))) +;;;###autoload +(define-behavior 'mwheel + "This code enables the use of the infamous 'wheel' on the new +crop of mice. Under XFree86 and the XSuSE X Servers, the wheel +events are sent as button4/button5 events, which are automatically +set up to do scrolling in the expected way. The actual way that the +scrolling works can be controlled by `mwheel-scroll-amount' and +`mwheel-follow-mouse'." + :group 'mouse + :short-doc "Mouse wheel support for X Windows" + :enable 'mwheel-install) + (provide 'mwheel) ;;; mwheel.el ends here diff --text -u 'xemacs-21.5.18/lisp/newcomment.el' 'xemacs-21.5.19/lisp/newcomment.el' Index: ./lisp/newcomment.el Prereq: 1.2 --- ./lisp/newcomment.el Mon Jun 7 08:58:44 2004 +++ ./lisp/newcomment.el Wed Jan 26 18:57:14 2005 @@ -5,7 +5,6 @@ ;; Author: code extracted from Emacs-20's simple.el ;; Maintainer: Stefan Monnier <monnier@cs.yale.edu> ;; Keywords: comment uncomment -;; Revision: $Id: newcomment.el,v 1.2 2004/06/06 23:58:44 adrian Exp $ ;; This file is part of GNU Emacs. @@ -24,15 +23,19 @@ ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. +;;; Synched up with: FSF 21.3. + ;;; Commentary: ;; A replacement for simple.el's comment-related functions. ;;; Bugs: +;; - boxed comments in Perl are not properly uncommented because they are +;; uncommented one-line at a time. +;; - nested comments in sgml-mode are not properly quoted. ;; - single-char nestable comment-start can only do the "\\s<+" stuff ;; if the corresponding closing marker happens to be right. -;; - comment-box in TeXinfo generate bogus comments @ccccc@ ;; - uncomment-region with a numeric argument can render multichar ;; comment markers invalid. ;; - comment-indent or comment-region when called inside a comment @@ -43,15 +46,16 @@ ;;; Todo: -;; - quantized steps in comment-alignment -;; - try to align tail comments -;; - check what c-comment-line-break-function has to say -;; - spill auto-fill of comments onto the end of the next line +;; - rebox.el-style refill. +;; - quantized steps in comment-alignment. +;; - try to align tail comments. +;; - check what c-comment-line-break-function has to say. +;; - spill auto-fill of comments onto the end of the next line. ;; - uncomment-region with a consp (for blocks) or somehow make the -;; deletion of continuation markers less dangerous -;; - drop block-comment-<foo> unless it's really used -;; - uncomment-region on a subpart of a comment -;; - support gnu-style "multi-line with space in continue" +;; deletion of continuation markers less dangerous. +;; - drop block-comment-<foo> unless it's really used. +;; - uncomment-region on a subpart of a comment. +;; - support gnu-style "multi-line with space in continue". ;; - somehow allow comment-dwim to use the region even if transient-mark-mode ;; is not turned on. @@ -71,7 +75,6 @@ ;;;###autoload (defalias 'indent-new-comment-line 'comment-indent-new-line) -;;;###autoload (defgroup comment nil "Indenting and filling of comments." :prefix "comment-" @@ -85,14 +88,18 @@ to understand comments or not in the given buffer. Major modes should set this variable.") +(defcustom comment-fill-column nil + "Column to use for `comment-indent'. If nil, use `fill-column' instead." + :type '(choice (const nil) integer)) + ;;;###autoload (defcustom comment-column 32 "*Column to indent right-margin comments to. -Setting this variable automatically makes it local to the current buffer. Each mode establishes a different default value for this variable; you -can set the value for a particular mode using that mode's hook." - :type 'integer - :group 'comment) +can set the value for a particular mode using that mode's hook. +Comments might be indented to a value smaller than this in order +not to go beyond `comment-fill-column'." + :type 'integer) (make-variable-buffer-local 'comment-column) ;;;###autoload @@ -167,7 +174,6 @@ (defcustom comment-style 'plain "*Style to be used for `comment-region'. See `comment-styles' for a list of available styles." - :group 'comment :type (if (boundp 'comment-styles) `(choice ,@(mapcar (lambda (s) `(const ,(car s))) comment-styles)) 'symbol)) @@ -179,8 +185,7 @@ of the corresponding number of spaces. Extra spacing between the comment characters and the comment text -makes the comment easier to read. Default is \" \". nil means 0." - :group 'comment +makes the comment easier to read. Default is 1. nil means 0." :type '(choice string integer (const nil))) ;;;###autoload @@ -188,8 +193,7 @@ "*Non-nil means \\[indent-new-comment-line] should continue same comment on new line, with no new terminator or starter. This is obsolete because you might as well use \\[newline-and-indent]." - :type 'boolean - :group 'comment) + :type 'boolean) ;;;; ;;;; Helpers @@ -206,6 +210,7 @@ "Return the mirror image of string S, without any trailing space." (comment-string-strip (concat (nreverse (string-to-list s))) nil t)) +;;;###autoload (defun comment-normalize-vars (&optional noerror) (if (not comment-start) (or noerror (error "No comment syntax is defined")) ;; comment-use-syntax @@ -232,16 +237,24 @@ (unless (or comment-continue (string= comment-end "")) (set (make-local-variable 'comment-continue) (concat (if (string-match "\\S-\\S-" comment-start) " " "|") - (substring comment-start 1)))) + (substring comment-start 1))) + ;; Hasn't been necessary yet. + ;; (unless (string-match comment-start-skip comment-continue) + ;; (kill-local-variable 'comment-continue)) + ) ;; comment-skip regexps - (unless comment-start-skip + (unless (and comment-start-skip + ;; In case comment-start has changed since last time. + (string-match comment-start-skip comment-start)) (set (make-local-variable 'comment-start-skip) (concat "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(\\s<+\\|" (regexp-quote (comment-string-strip comment-start t t)) ;; Let's not allow any \s- but only [ \t] since \n ;; might be both a comment-end marker and \s-. "+\\)[ \t]*"))) - (unless comment-end-skip + (unless (and comment-end-skip + ;; In case comment-end has changed since last time. + (string-match comment-end-skip comment-end)) (let ((ce (if (string= "" comment-end) "\n" (comment-string-strip comment-end t t)))) (set (make-local-variable 'comment-end-skip) @@ -252,7 +265,7 @@ (if (and comment-quote-nested (<= (length ce) 1)) "" "+") (regexp-quote (substring ce 1)) "\\)")))))) - + (defun comment-quote-re (str unp) (concat (regexp-quote (substring str 0 1)) "\\\\" (if unp "+" "*") @@ -468,13 +481,25 @@ (begpos (comment-search-forward eolpos t)) cpos indent) ;; An existing comment? - (if begpos (setq cpos (point-marker)) + (if begpos + (progn + (if (and (not (looking-at "[\t\n ]")) + (looking-at comment-end-skip)) + ;; The comment is empty and we have skipped all its space + ;; and landed right before the comment-ender: + ;; Go back to the middle of the space. + (forward-char (/ (skip-chars-backward " \t") -2))) + (setq cpos (point-marker))) ;; If none, insert one. (save-excursion ;; Some comment-indent-function insist on not moving comments that ;; are in column 0, so we first go to the likely target column. (indent-to comment-column) (setq begpos (point)) + ;; Ensure there's a space before the comment for things + ;; like sh where it matters (as well as being neater). + (unless (eq ?\ (char-syntax (char-before))) + (insert ?\ )) (insert starter) (setq cpos (point-marker)) (insert ender))) @@ -482,22 +507,20 @@ ;; Compute desired indent. (setq indent (save-excursion (funcall comment-indent-function))) (if (not indent) - ;; comment-indent-function refuses delegates to indent. + ;; comment-indent-function refuses: delegate to indent. (indent-according-to-mode) ;; Avoid moving comments past the fill-column. (unless (save-excursion (skip-chars-backward " \t") (bolp)) (setq indent (min indent (+ (current-column) - (- fill-column + (- (or comment-fill-column fill-column) (save-excursion (end-of-line) (current-column))))))) ;; XEmacs change: Preserve indentation of comments starting in ;; column 0, as documented. - (if (or (= (current-column) 0) (= (current-column) indent)) - (goto-char begpos) + (unless (or (= (current-column) 0) (= (current-column) indent)) ;; If that's different from current, change it. - (skip-chars-backward " \t") - (delete-region (point) begpos) + (delete-region (point) (progn (skip-chars-backward " \t") (point))) (indent-to (if (bolp) indent (max indent (1+ (current-column))))))) (goto-char cpos) @@ -619,7 +642,7 @@ ;;;###autoload (defun uncomment-region (beg end &optional arg) - "Uncomment each line in the BEG..END region. + "Uncomment each line in the BEG .. END region. The numeric prefix ARG can specify a number of chars to remove from the comment markers." (interactive "*r\nP") @@ -649,31 +672,36 @@ (setq arg (list min-comments))) (goto-char beg))) - (let ((numarg (prefix-numeric-value arg)) - spt) + (let* ((numarg (prefix-numeric-value arg)) + (ccs comment-continue) + (srei (comment-padright ccs 're)) + (sre (and srei (concat "^\\s-*?\\(" srei "\\)"))) + spt) (while (and (< (point) end) (setq spt (comment-search-forward end t))) - (let* ((ipt (point)) - ;; Find the end of the comment. - (ept (progn - (goto-char spt) - (unless (comment-forward) - (error "Can't find the comment end")) - (point))) - (box nil) - (ccs comment-continue) - (srei (comment-padright ccs 're)) - (sre (and srei (concat "^\\s-*?\\(" srei "\\)")))) + (let ((ipt (point)) + ;; Find the end of the comment. + (ept (progn + (goto-char spt) + (unless (comment-forward) + (error "Can't find the comment end")) + (point))) + (box nil) + (box-equal nil)) ;Whether we might be using `=' for boxes. (save-restriction (narrow-to-region spt ept) + ;; Remove the comment-start. (goto-char ipt) (skip-syntax-backward " ") - ;; Check for special `=' used sometimes in comment-box. - (when (and (= (- (point) (point-min)) 1) (looking-at "=\\{7\\}")) - (skip-chars-forward "=")) ;; A box-comment starts with a looong comment-start marker. - (when (> (- (point) (point-min) (length comment-start)) 7) + (when (and (or (and (= (- (point) (point-min)) 1) + (setq box-equal t) + (looking-at "=\\{7\\}") + (not (eq (char-before (point-max)) ?\n)) + (skip-chars-forward "=")) + (> (- (point) (point-min) (length comment-start)) 7)) + (> (count-lines (point-min) (point-max)) 2)) (setq box t)) (when (looking-at (regexp-quote comment-padding)) (goto-char (match-end 0))) @@ -686,7 +714,7 @@ ;; Remove the end-comment (and leading padding and such). (goto-char (point-max)) (comment-enter-backward) ;; Check for special `=' used sometimes in comment-box. - (when (= (- (point-max) (point)) 1) + (when (and box-equal (not (eq (char-before (point-max)) ?\n))) (let ((pos (point))) ;; skip `=' but only if there are at least 7. (when (> (skip-chars-backward "=") -7) (goto-char pos)))) @@ -735,23 +763,32 @@ (s (concat cs "a=m" cce)) (e (concat ccs "a=m" ce)) (c (if (string-match ".*\\S-\\S-" cs) - (aref cs (1- (match-end 0))) ?=)) - ; Huh? (_ (string-match "\\s-*a=m\\s-*" s)) + (aref cs (1- (match-end 0))) + (if (and (equal comment-end "") (string-match ".*\\S-" cs)) + (aref cs (1- (match-end 0))) ?=))) + (re "\\s-*a=m\\s-*") + ; Huh? (_ (string-match re s)) + (lcs (length cs)) (fill (make-string (+ width (- (match-end 0) - (match-beginning 0) (length cs) 3)) c))) + (match-beginning 0) lcs 3)) c))) (setq cs (replace-match fill t t s)) - (string-match "\\s-*a=m\\s-*" e) + (when (and (not (string-match comment-start-skip cs)) + (string-match "a=m" s)) + ;; The whitespace around CS cannot be ignored: put it back. + (setq re "a=m") + (setq fill (make-string (- width lcs) c)) + (setq cs (replace-match fill t t s))) + (string-match re e) (setq ce (replace-match fill t t e)))) (cons (concat cs "\n" (make-string min-indent ? ) ccs) (concat cce "\n" (make-string (+ min-indent eindent) ? ) ce)))) -;(def-edebug-spec comment-with-narrowing t) -(put 'comment-with-narrowing 'lisp-indent-function 2) (defmacro comment-with-narrowing (beg end &rest body) "Execute BODY with BEG..END narrowing. Space is added (and then removed) at the beginning for the text's indentation to be kept as it was before narrowing." + (declare (debug t) (indent 2)) (let ((bindent (make-symbol "bindent"))) `(let ((,bindent (save-excursion (goto-char beg) (current-column)))) (save-restriction @@ -778,7 +815,7 @@ (defun comment-region-internal (beg end cs ce &optional ccs cce block lines indent) - "Comment region BEG..END. + "Comment region BEG .. END. CS and CE are the comment start resp end string. CCS and CCE are the comment continuation strings for the start resp end of lines (default to CS and CE). @@ -803,7 +840,7 @@ (unless block (setq cce nil)) ;; Continuation defaults to the same as CS and CE. (unless ccs (setq ccs cs cce ce)) - + (save-excursion (goto-char end) ;; If the end is not at the end of a line and the comment-end @@ -825,7 +862,7 @@ (end-of-line) (setq max-indent (max max-indent (current-column))) (not (or (eobp) (progn (forward-line) nil))))) - + ;; Inserting ccs can change max-indent by (1- tab-width). (setq max-indent (+ max-indent (max (length cs) (length ccs)) tab-width -1)) @@ -838,7 +875,7 @@ cs ce ccs cce min-indent max-indent block))) (setq cs (car csce)) (setq ce (cdr csce)))) - + (goto-char (point-min)) ;; Loop over all lines from BEG to END. (while @@ -857,7 +894,7 @@ ;;;###autoload (defun comment-region (beg end &optional arg) "Comment or uncomment each line in the region. -With just \\[universal-argument] prefix arg, uncomment each line in region BEG..END. +With just \\[universal-argument] prefix arg, uncomment each line in region BEG .. END. Numeric prefix arg ARG means use ARG comment characters. If ARG is negative, delete that many comment characters instead. By default, comments start at the left margin, are terminated on each line, @@ -894,8 +931,8 @@ (>= (point) beg)) (progn (goto-char end) (end-of-line) (skip-syntax-backward " ") (<= (point) end)) - (or (not (string= "" comment-end)) block) - (progn (goto-char beg) (search-forward "\n" end t))))) + (or block (not (string= "" comment-end))) + (or block (progn (goto-char beg) (search-forward "\n" end t)))))) ;; don't add end-markers just because the user asked for `block' (unless (or lines (string= "" comment-end)) (setq block nil)) @@ -921,7 +958,7 @@ (nth 3 style)))))) (defun comment-box (beg end &optional arg) - "Comment out the BEG..END region, putting it inside a box. + "Comment out the BEG .. END region, putting it inside a box. The numeric prefix ARG specifies how many characters to add to begin- and end- comment markers additionally to what `comment-add' already specifies." (interactive "*r\np") @@ -929,6 +966,20 @@ 'box-multi 'box))) (comment-region beg end (+ comment-add arg)))) + +;;;###autoload +(defun comment-or-uncomment-region (beg end &optional arg) + "Call `comment-region', unless the region only consists of comments, +in which case call `uncomment-region'. If a prefix arg is given, it +is passed on to the respective function." + (interactive "*r\nP") + (funcall (if (save-excursion ;; check for already commented region + (goto-char beg) + (comment-forward (point-max)) + (<= end (point))) + 'uncomment-region 'comment-region) + beg end arg)) + ;;;###autoload (defun comment-dwim (arg) "Call the comment command you want (Do What I Mean). @@ -941,14 +992,7 @@ (interactive "*P") (comment-normalize-vars) (if (region-active-p) ;mark-active transient-mark-mode) - (let ((beg (min (point) (mark))) - (end (max (point) (mark)))) - (if (save-excursion ;; check for already commented region - (goto-char beg) - (comment-forward (point-max)) - (<= end (point))) - (uncomment-region beg end arg) - (comment-region beg end arg))) + (comment-or-uncomment-region (region-beginning) (region-end) arg) (if (save-excursion (beginning-of-line) (not (looking-at "\\s-*$"))) ;; FIXME: If there's no comment to kill on this line and ARG is ;; specified, calling comment-kill is not very clever. @@ -967,8 +1011,15 @@ (defcustom comment-auto-fill-only-comments nil "Non-nil means to only auto-fill inside comments. This has no effect in modes that do not define a comment syntax." - :type 'boolean - :group 'comment) + :type 'boolean) + +(defun comment-valid-prefix (prefix compos) + (or + ;; Accept any prefix if the current comment is not EOL-terminated. + (save-excursion (goto-char compos) (comment-forward) (not (bolp))) + ;; Accept any prefix that starts with a comment-start marker. + (string-match (concat "\\`[ \t]*\\(?:" comment-start-skip "\\)") + fill-prefix))) ;;;###autoload (defun comment-indent-new-line (&optional soft) @@ -992,42 +1043,59 @@ ;; don't do anything (unless no comment syntax is defined). (unless (and comment-start comment-auto-fill-only-comments + (not (interactive-p)) (not (save-excursion (prog1 (setq compos (comment-beginning)) (setq comin (point)))))) - ;; Now we know we should auto-fill. ;; XEmacs: next 3 lines from old version. (skip-chars-backward " \t") (if (featurep 'mule) (declare-fboundp (kinsoku-process))) - (delete-horizontal-space) + + ;; Now we know we should auto-fill. + ;; Insert the newline before removing empty space so that markers + ;; get preserved better. (if soft (insert-and-inherit ?\n) (newline 1)) - (if fill-prefix + (save-excursion (forward-char -1) (delete-horizontal-space)) + (delete-horizontal-space) + + (if (and fill-prefix (not adaptive-fill-mode)) + ;; Blindly trust a non-adaptive fill-prefix. (progn (indent-to-left-margin) - (insert-and-inherit fill-prefix)) + (insert-before-markers-and-inherit fill-prefix)) ;;#### jhod: probably need to fix this for kinsoku processing ;; If necessary check whether we're inside a comment. - (unless (or comment-multi-line compos (null comment-start)) + (unless (or compos (null comment-start)) (save-excursion (backward-char) (setq compos (comment-beginning)) (setq comin (point)))) - ;; If we're not inside a comment, just try to indent. - ;; #### XEmacs: the line `(if comcol' was changed as follows. - ;; I'm leaving it out since who knows if it's applicable any more. - ;; --ben - ;; (if (and comcol (not fill-prefix)) ; XEmacs - (ENE) from fa-extras. - (if (not compos) (indent-according-to-mode) + (cond + ;; If there's an adaptive prefix, use it unless we're inside + ;; a comment and the prefix is not a comment starter. + ((and fill-prefix + (or (not compos) + (comment-valid-prefix fill-prefix compos))) + (indent-to-left-margin) + (insert-and-inherit fill-prefix)) + ;; If we're not inside a comment, just try to indent. + ;; #### XEmacs: the line `(if comcol' was changed as follows. + ;; I'm leaving it out since who knows if it's applicable any more. + ;; --ben + ;; (if (and comcol (not fill-prefix)) ; XEmacs - (ENE) from fa-extras. + ((not compos) (indent-according-to-mode)) + (t (let* ((comment-column ;; The continuation indentation should be somewhere between ;; the current line's indentation (plus 2 for good measure) ;; and the current comment's indentation, with a preference ;; for comment-column. (save-excursion + ;; FIXME: use prev line's info rather than first line's. (goto-char compos) (min (current-column) (max comment-column (+ 2 (current-indentation)))))) @@ -1049,22 +1117,25 @@ (point)) nil t))))) (comment-start comstart) + (continuep (or comment-multi-line + (cadr (assoc comment-style comment-styles)))) ;; Force comment-continue to be recreated from comment-start. ;; FIXME: wrong if comment-continue was set explicitly! + ;; FIXME: use prev line's continuation if available. (comment-continue nil)) - (insert-and-inherit ?\n) - (forward-char -1) - (comment-indent (cadr (assoc comment-style comment-styles))) - (save-excursion - (let ((pt (point))) - (end-of-line) - (let ((comend (buffer-substring pt (point)))) - ;; The 1+ is to make sure we delete the \n inserted above. - (delete-region pt (1+ (point))) - (beginning-of-line) - (backward-char) - (insert comend) - (forward-char)))))))))) + (if (and comment-multi-line (> (length comment-end) 0)) + (indent-according-to-mode) + (insert-and-inherit ?\n) + (forward-char -1) + (comment-indent continuep) + (save-excursion + (let ((pt (point))) + (end-of-line) + (let ((comend (buffer-substring pt (point)))) + ;; The 1+ is to make sure we delete the \n inserted above. + (delete-region pt (1+ (point))) + (end-of-line 0) + (insert comend)))))))))))) (provide 'newcomment) diff --text -u 'xemacs-21.5.18/lisp/obsolete.el' 'xemacs-21.5.19/lisp/obsolete.el' Index: ./lisp/obsolete.el --- ./lisp/obsolete.el Thu Mar 20 22:19:59 2003 +++ ./lisp/obsolete.el Fri Jan 28 11:58:41 2005 @@ -3,7 +3,7 @@ ;; Copyright (C) 1985-1994, 1997 Free Software Foundation, Inc. ;; Copyright (C) 1994, 1995 Amdahl Corporation. ;; Copyright (C) 1995 Sun Microsystems. -;; Copyright (C) 2002 Ben Wing. +;; Copyright (C) 2002, 2004 Ben Wing. ;; Maintainer: XEmacs Development Team ;; Keywords: internal, dumped @@ -372,6 +372,10 @@ (color-instance-rgb-components (make-color-instance color))) (make-compatible 'x-color-values 'color-instance-rgb-components) +(make-obsolete 'mswindows-color-list 'color-list) +(make-obsolete 'tty-color-list 'color-list) +(make-compatible 'list-fonts 'font-list) + ;; Two loser functions which shouldn't be used. (make-obsolete 'following-char 'char-after) (make-obsolete 'preceding-char 'char-before) diff --text -u 'xemacs-21.5.18/lisp/package-admin.el' 'xemacs-21.5.19/lisp/package-admin.el' Index: ./lisp/package-admin.el --- ./lisp/package-admin.el Sat Jul 5 17:40:37 2003 +++ ./lisp/package-admin.el Mon Dec 27 21:25:14 2004 @@ -197,9 +197,8 @@ (expand-file-name "mule-packages" user-init-directory)))))) ;; Finally check the normal places (if (not top-dir) - (let ((path-list (nth 1 (packages-find-packages - emacs-data-roots - (packages-compute-package-locations user-init-directory))))) + (let ((path-list (nth 1 (packages-find-all-package-hierarchies + emacs-data-roots)))) (cond ((eq type 'std) (while path-list (if (equal (substring (car path-list) -16) @@ -226,7 +225,7 @@ see if the PACKAGE is already installed and return that location, if it is writable. Finally, fall back to the `user-init-directory' if all else fails. As a side effect of installing packages under -`user-init-directory' these packages become part of `early-packages'." +`user-init-directory' these packages become part of `early-package-hierarchies'." ;; If pkg-dir specified, return that if writable. (if (and pkg-dir (file-writable-p (directory-file-name pkg-dir))) @@ -255,7 +254,7 @@ (car-safe (member-if (lambda (h) (string-match (concat "^" (regexp-quote h)) autoload-dir)) - (append (cdr early-packages) late-packages))))) + (append (cdr early-package-hierarchies) late-package-hierarchies))))) (if (and pkg-dir (file-writable-p (directory-file-name pkg-dir))) pkg-dir diff --text -u 'xemacs-21.5.18/lisp/package-ui.el' 'xemacs-21.5.19/lisp/package-ui.el' Index: ./lisp/package-ui.el --- ./lisp/package-ui.el Tue Jun 22 03:26:18 2004 +++ ./lisp/package-ui.el Fri Nov 5 08:05:55 2004 @@ -509,14 +509,15 @@ (defun pui-display-maintainer (&optional no-error event) "Display a package's maintainer in the minibuffer." (interactive) - (let (extent pkg-sym info maintainer) + (let (extent ;pkg-sym + info maintainer) (save-excursion (beginning-of-line) (if (setq extent (extent-at (point) (current-buffer) 'pui)) (progn - (setq pkg-sym (extent-property extent 'pui-package) - info (extent-property extent 'pui-info) - maintainer (package-get-info-prop info 'maintainer)) + (setq ;pkg-sym (extent-property extent 'pui-package) + info (extent-property extent 'pui-info) + maintainer (package-get-info-prop info 'maintainer)) (message (format "Maintainer: %s" maintainer))) (if no-error (clear-message nil) diff --text -u 'xemacs-21.5.18/lisp/packages.el' 'xemacs-21.5.19/lisp/packages.el' Index: ./lisp/packages.el --- ./lisp/packages.el Tue Sep 7 09:08:19 2004 +++ ./lisp/packages.el Fri Feb 4 08:56:53 2005 @@ -1,7 +1,7 @@ ;;; packages.el --- Low level support for XEmacs packages ;; Copyright (C) 1997 Free Software Foundation, Inc. -;; Copyright (C) 2002, 2003 Ben Wing. +;; Copyright (C) 2002, 2003, 2004 Ben Wing. ;; Author: Steven L Baur <steve@xemacs.org> ;; Maintainer: Steven L Baur <steve@xemacs.org> @@ -58,8 +58,25 @@ (defvar packages-package-list nil "Database of installed packages and version numbers") -(defvar packages-hierarchy-depth 1 - "Depth of package hierarchies.") +;;; Directories and paths + +;;; Terminology: + +;;; A *package hierarchy* is a directory that contains a collection of +;;; packages; it has lisp/, info/, etc/ etc. subdirectories that +;;; contain the files constituting the packages. + +;;; A *package directory* contains package hierarchies---the package +;;; hierarchies are typically in directories "xemacs-packages", +;;; "mule-packages", and so on. A package hierarchy might only be +;;; applicable for specific variants of XEmacs. + +;;; Package hierarchies come in "early", "late", and "last" variants, +;;; depending on their relative location in the various paths. +;;; "Early" hierarchies are typically in the user's home directory, +;;; "late" hierarchies are typically part of the XEmacs installation, +;;; and "last" package hierarchies are for special purposes, such as +;;; making the packages of some previous XEmacs version available. (defvar packages-load-path-depth 1 "Depth of load-path search in package hierarchies.") @@ -67,48 +84,33 @@ (defvar packages-data-path-depth 1 "Depth of data-path search in package hierarchies.") -(defvar early-packages nil - "Packages early in the load path.") +(defvar early-package-hierarchies nil + "Package hierarchies early in the load path.") (defvar early-package-load-path nil "Load path for packages early in the load path.") -(defvar late-packages nil - "Packages late in the load path.") +(defvar late-package-hierarchies nil + "Package hierarchies late in the load path.") (defvar late-package-load-path nil "Load path for packages late in the load path.") -(defvar last-packages nil - "Packages last in the load path.") +(defvar last-package-hierarchies nil + "Package hierarchies last in the load path.") (defvar last-package-load-path nil "Load path for packages last in the load path.") -(defun packages-compute-package-locations (user-init-directory) - "Compute locations of the various package directories. -This is a list each of whose elements describes one directory. -A directory description is a three-element list. -The first element is either an absolute path or a subdirectory -in the XEmacs hierarchy. -The second component is one of the symbols EARLY, LATE, LAST, -depending on the load-path segment the hierarchy is supposed to -show up in. -The third component is a thunk which, if it returns NIL, causes -the directory to be ignored." - (list - (list (paths-construct-path (list user-init-directory "site-packages")) - 'early #'(lambda () t)) - (list (paths-construct-path (list user-init-directory "infodock-packages")) - 'early #'(lambda () (featurep 'infodock))) - (list (paths-construct-path (list user-init-directory "mule-packages")) - 'early #'(lambda () (featurep 'mule))) - (list (paths-construct-path (list user-init-directory "xemacs-packages")) - 'early #'(lambda () t)) - (list "site-packages" 'late #'(lambda () t)) - (list "infodock-packages" 'late #'(lambda () (featurep 'infodock))) - (list "mule-packages" 'late #'(lambda () (featurep 'mule))) - (list "xemacs-packages" 'late #'(lambda () t)))) +(defun packages-package-hierarchy-directory-names () + "Returns a list package hierarchy directory names. +These are the valid immediate directory names of package +directories, directories with higher priority first" + (paths-filter #'(lambda (x) x) + `("site-packages" + ,(when (featurep 'infodock) "infodock-packages") + ,(when (featurep 'mule) "mule-packages") + "xemacs-packages"))) (defun package-get-key-1 (info key) "Locate keyword `key' in list." @@ -131,6 +133,14 @@ (setq packages-package-list (cons (cons name info) (remassq name packages-package-list))))) +(defun package-suppress (package file form) + "Set up a package-suppress condition FORM for FILE in PACKAGE. +When XEmacs searches for a file in the load path, it will ignore FILE +if FORM evaluates to non-nil." + (setq load-suppress-alist + (acons (expand-file-name file load-file-name) form + load-suppress-alist))) + (defun package-require (name version) (let ((pkg (assq name packages-package-list))) (cond ((null pkg) @@ -328,30 +338,15 @@ ;; Path setup -(defun packages-find-package-directories (roots base) - "Find a set of package directories." - ;; make sure paths-find-version-directory and paths-find-site-directory - ;; don't both pick up version-independent directories ... - (let ((version-directory (paths-find-version-directory roots base nil nil t)) - (site-directory (paths-find-site-directory roots base))) - (paths-uniq-append - (and version-directory (list version-directory)) - (and site-directory (list site-directory))))) - -(defvar packages-special-base-regexp "^\\(etc\\|info\\|man\\|lisp\\|lib-src\\|bin\\|pkginfo\\)$" - "Special subdirectories of packages.") - -(defvar packages-no-package-hierarchy-regexp - (concat "\\(" paths-version-control-filename-regexp "\\)" - "\\|" - "\\(" packages-special-base-regexp "\\)") - "Directories which can't be the roots of package hierarchies.") - -(defun packages-find-packages-in-directories (directories) - "Find all packages underneath directories in DIRECTORIES." - (paths-find-recursive-path directories - packages-hierarchy-depth - packages-no-package-hierarchy-regexp)) +(defun packages-find-package-hierarchies-named (package-directories base) + "Find a set of package hierarchies within an XEmacs installation. +PACKAGE-DIRECTORIES is a list of package directories. +BASE is a subdirectory name for the hierarchy. +Returns list of hierarchies." + (paths-directories-which-exist + (mapcar #'(lambda (package-directory) + (file-name-as-directory (concat package-directory base))) + package-directories))) (defun packages-split-path (path) "Split PATH at \"\", return pair with two components. @@ -368,7 +363,8 @@ (defun packages-split-package-path (package-path) "Split up PACKAGE-PATH into early, late and last components. The separation is by \"\" components. -This returns (LIST EARLY-PACKAGES LATE-PACKAGES LAST-PACKAGES)." +This returns +(LIST EARLY-PACKAGE-HIERARCHIES LATE-PACKAGE-HIERARCHIES LAST-PACKAGE-HIERARCHIES)." ;; When in doubt, it's late (let* ((stuff (packages-split-path package-path)) (early (and (cdr stuff) (car stuff))) @@ -376,99 +372,99 @@ (stuff (packages-split-path late+last)) (late (car stuff)) (last (cdr stuff))) - (list (packages-find-packages-in-directories early) - (packages-find-packages-in-directories late) - (packages-find-packages-in-directories last)))) + (list (mapcar #'file-name-as-directory early) + (mapcar #'file-name-as-directory late) + (mapcar #'file-name-as-directory last)))) (defun packages-deconstruct (list consumer) - "Deconstruct LIST and feed it to CONSUMER." + "Deconstruct LIST and feed it to CONSUMER. +CONSUMER is a function that accepts the elements of LISTS as separate arguments." (apply consumer list)) -(defun packages-find-packages-by-name (roots name) - "Find a package hierarchy by its name." - (packages-find-packages-in-directories - (if (and (file-name-absolute-p name) - (file-name-directory (expand-file-name name))) - (list (file-name-as-directory (expand-file-name name))) - (packages-find-package-directories roots name)))) - -(defun packages-find-packages-at-time - (roots package-locations time &optional default) - "Find packages at given time. -For the format of PACKAGE-LOCATIONS, see the global variable of the same name. -TIME is either 'EARLY, 'LATE, or 'LAST. -DEFAULT is a default list of packages." +(defun packages-find-installation-package-directories (roots) + "Find the package directories in the XEmacs installation. +ROOTS is a list of installation roots." + (paths-uniq-append (paths-find-version-directories roots "" nil nil t) + (paths-find-site-directories roots ""))) + +(defun packages-find-package-hierarchies (package-directories &optional default) + "Find package hierarchies in a list of package directories. +PACKAGE-DIRECTORIES is a list of package directories. +DEFAULT is a default list of package hierarchies." (or default - (let ((packages '())) - (while package-locations - (packages-deconstruct - (car package-locations) - #'(lambda (name a-time thunk) - (if (and (eq time a-time) - (funcall thunk)) - (setq packages - (nconc packages - (packages-find-packages-by-name roots name)))))) - (setq package-locations (cdr package-locations))) - packages))) - -(defun packages-find-packages (roots package-locations) - "Find the packages." + (let ((package-hierarchies '()) + (hierarchy-directories (packages-package-hierarchy-directory-names))) + (while hierarchy-directories + (setq package-hierarchies + (nconc package-hierarchies + (packages-find-package-hierarchies-named + package-directories + (car hierarchy-directories)))) + (setq hierarchy-directories (cdr hierarchy-directories))) + package-hierarchies))) + +(defun packages-find-all-package-hierarchies (roots) + "Find the package hierarchies. +ROOTS is a list of installation roots. +Returns a list of three directory lists, the first being the list of early +hierarchies, the second that of the late hierarchies, and the third the +list of the last hierarchies." (let ((envvar-value (getenv "EMACSPACKAGEPATH"))) (if envvar-value (packages-split-package-path (paths-decode-directory-path envvar-value)) (packages-deconstruct (packages-split-package-path configure-package-path) - #'(lambda (configure-early-packages - configure-late-packages - configure-last-packages) - (list (packages-find-packages-at-time roots package-locations 'early - configure-early-packages) - (packages-find-packages-at-time roots package-locations 'late - configure-late-packages) - (packages-find-packages-at-time roots package-locations 'last - configure-last-packages))))))) + #'(lambda (configure-early-package-hierarchies + configure-late-package-hierarchies + configure-last-package-hierarchies) + (list + (packages-find-package-hierarchies (list user-init-directory) + configure-early-package-hierarchies) + (packages-find-package-hierarchies (packages-find-installation-package-directories roots) + configure-late-package-hierarchies) + (packages-find-package-hierarchies '() + configure-last-package-hierarchies))))))) -(defun packages-find-package-library-path (packages suffixes) +(defun packages-find-package-library-path (package-hierarchies suffixes) "Construct a path into a component of the packages hierarchy. -PACKAGES is a list of package directories. -SUFFIXES is a list of names of package subdirectories to look for." +PACKAGE-HIERARCHIES is a list of package hierarchies. +SUFFIXES is a list of names of hierarchy subdirectories to look for." (let ((directories (apply #'nconc - (mapcar #'(lambda (package) + (mapcar #'(lambda (hierarchy) (mapcar #'(lambda (suffix) - (file-name-as-directory (concat package suffix))) + (file-name-as-directory (concat hierarchy suffix))) suffixes)) - packages)))) + package-hierarchies)))) (paths-directories-which-exist directories))) -(defun packages-find-package-load-path (packages) +(defun packages-find-package-load-path (package-hierarchies) "Construct the load-path component for packages. -PACKAGES is a list of package directories." +PACKAGE-HIERARCHIES is a list of package hierarchies." (paths-find-recursive-load-path - (packages-find-package-library-path packages + (packages-find-package-library-path package-hierarchies '("lisp")) packages-load-path-depth)) -(defun packages-find-package-exec-path (packages) +(defun packages-find-package-exec-path (package-hierarchies) "Construct the exec-path component for packages. -PACKAGES is a list of package directories." - (packages-find-package-library-path packages +PACKAGE-HIERARCHIES is a list of package hierarchies." + (packages-find-package-library-path package-hierarchies (list (paths-construct-path (list "bin" system-configuration)) "lib-src"))) -(defun packages-find-package-info-path (packages) +(defun packages-find-package-info-path (package-hierarchies) "Construct the info-path component for packages. -PACKAGES is a list of package directories." - (packages-find-package-library-path packages '("info"))) +PACKAGE-HIERARCHIES is a list of package directories." + (packages-find-package-library-path package-hierarchies '("info"))) -(defun packages-find-package-data-path (packages) +(defun packages-find-package-data-path (package-hierarchies) "Construct the data-path component for packages. -PACKAGES is a list of package directories." +PACKAGE-HIERARCHIES is a list of package hierachies." (paths-find-recursive-load-path - (packages-find-package-library-path packages + (packages-find-package-library-path package-hierarchies '("etc")) packages-data-path-depth)) diff --text -u 'xemacs-21.5.18/lisp/page.el' 'xemacs-21.5.19/lisp/page.el' Index: ./lisp/page.el --- ./lisp/page.el Fri Apr 13 03:21:34 2001 +++ ./lisp/page.el Wed Jan 26 18:56:06 2005 @@ -1,9 +1,10 @@ -;;; page.el --- page motion commands for emacs. +;;; page.el --- page motion commands for Emacs ;; Copyright (C) 1985, 1997 Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: extensions, dumped +;; Keywords: wp convenience ;; This file is part of XEmacs. @@ -22,7 +23,7 @@ ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ;; 02111-1307, USA. -;;; Synched up with: FSF 19.34. +;;; Synched up with: FSF 21.3. ;;; Commentary: @@ -94,15 +95,28 @@ (if (> arg 0) (forward-page arg) (if (< arg 0) - (forward-page (1- arg)))) + (let ((adjust 0) + (opoint (point))) + ;; If we are not now at the beginning of a page, + ;; move back one extra time, to get to the start of this page. + (save-excursion + (beginning-of-line) + (or (and (looking-at page-delimiter) + (eq (match-end 0) opoint)) + (setq adjust 1))) + (forward-page (- arg adjust))))) ;; Find the end of the page. + (set-match-data nil) (forward-page) ;; If we stopped due to end of buffer, stay there. ;; If we stopped after a page delimiter, put end of restriction ;; at the beginning of that line. - (if (save-excursion - (goto-char (match-beginning 0)) ; was (beginning-of-line) - (looking-at page-delimiter)) + ;; Before checking the match that was found, + ;; verify that forward-page actually set the match data. + (if (and (match-beginning 0) + (save-excursion + (goto-char (match-beginning 0)) ; was (beginning-of-line) + (looking-at page-delimiter))) (beginning-of-line)) (narrow-to-region (point) (progn diff --text -u 'xemacs-21.5.18/lisp/paragraphs.el' 'xemacs-21.5.19/lisp/paragraphs.el' Index: ./lisp/paragraphs.el --- ./lisp/paragraphs.el Wed Dec 5 13:09:25 2001 +++ ./lisp/paragraphs.el Thu Feb 10 12:16:59 2005 @@ -1,7 +1,7 @@ -;;; paragraphs.el --- paragraph and sentence parsing. +;;; paragraphs.el --- paragraph and sentence parsing -;; Copyright (C) 1985, 86, 87, 91, 94, 95, 97, 2001 -;; Free Software Foundation, Inc. +;; Copyright (C) 1985, 86, 87, 91, 94, 95, 96, 1997, 1999, 2000, 2001 +;; Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: wp, dumped @@ -23,7 +23,7 @@ ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ;; 02111-1307, USA. -;;; Synched up with: FSF 19.34. +;;; Synched up with: FSF 21.3. ;;; Commentary: @@ -37,19 +37,11 @@ ;;; Code: -(defvar use-hard-newlines nil - "Non-nil means to distinguish hard and soft newlines. -When this is non-nil, the functions `newline' and `open-line' add the -text-property `hard' to newlines that they insert. Also, a line is -only considered as a candidate to match `paragraph-start' or -`paragraph-separate' if it follows a hard newline. Newlines not -marked hard are called \"soft\", and are always internal to -paragraphs. The fill functions always insert soft newlines. - -Each buffer has its own value of this variable.") -(make-variable-buffer-local 'use-hard-newlines) +(defgroup paragraphs nil + "Paragraph and sentence parsing." + :group 'editing) -(defun use-hard-newlines (&optional arg insert) +(define-minor-mode use-hard-newlines "Minor mode to distinguish hard and soft newlines. When active, the functions `newline' and `open-line' add the text-property `hard' to newlines that they insert, and a line is @@ -58,25 +50,22 @@ Prefix argument says to turn mode on if positive, off if negative. When the mode is turned on, if there are newlines in the buffer but no hard -newlines, ask the user whether to mark as hard any newlines preceding a +newlines, ask the user whether to mark as hard any newlines preceeding a `paragraph-start' line. From a program, second arg INSERT specifies whether to do this; it can be `never' to change nothing, t or `always' to force -marking, `guess' to try to do the right thing with no questions, nil +marking, `guess' to try to do the right thing with no questions, nil or anything else to ask the user. Newlines not marked hard are called \"soft\", and are always internal to paragraphs. The fill functions insert and delete only soft newlines." - (interactive (list current-prefix-arg nil)) - (if (or (<= (prefix-numeric-value arg) 0) - (and use-hard-newlines (null arg))) - ;; Turn mode off - (setq use-hard-newlines nil) + :group 'paragraphs + :extra-args (insert) + (when use-hard-newlines ;; Turn mode on ;; Intuit hard newlines -- ;; mark as hard any newlines preceding a paragraph-start line. (if (or (eq insert t) (eq insert 'always) (and (not (eq 'never insert)) - (not use-hard-newlines) (not (text-property-any (point-min) (point-max) 'hard t)) (save-excursion (goto-char (point-min)) @@ -88,19 +77,16 @@ (while (search-forward "\n" nil t) (let ((pos (point))) (move-to-left-margin) - (if (looking-at paragraph-start) - (progn - (set-hard-newline-properties (1- pos) pos) - ;; If paragraph-separate, newline after it is hard too. - (if (looking-at paragraph-separate) - (progn - (end-of-line) - (if (not (eobp)) - (set-hard-newline-properties - (point) (1+ (point)))))))))))) - (setq use-hard-newlines t))) + (when (looking-at paragraph-start) + (set-hard-newline-properties (1- pos) pos)) + ;; If paragraph-separate, newline after it is hard too. + (when (looking-at paragraph-separate) + (set-hard-newline-properties (1- pos) pos) + (end-of-line) + (unless (eobp) + (set-hard-newline-properties (point) (1+ (point))))))))))) -(defconst paragraph-start "[ \t\n\f]" "\ +(defcustom paragraph-start "\f\\|[ \t]*$" "\ *Regexp for beginning of a line that starts OR separates paragraphs. This regexp should match lines that separate paragraphs and should also match lines that start a paragraph @@ -115,7 +101,9 @@ lines that start paragraphs from lines that separate them. If the variable `use-hard-newlines' is non-nil, then only lines following a -hard newline are considered to match.") +hard newline are considered to match." + :group 'paragraphs + :type 'regexp) ;; paragraph-start requires a hard newline, but paragraph-separate does not: ;; It is assumed that paragraph-separate is distinctive enough to be believed @@ -123,8 +111,8 @@ ;; something very minimal, even including "." (which makes every hard newline ;; start a new paragraph). -(defconst paragraph-separate "[ \t\f]*$" "\ -*Regexp for beginning of a line that separates paragraphs. +(defcustom paragraph-separate "[ \t\f]*$" + "*Regexp for beginning of a line that separates paragraphs. If you change this, you may have to change `paragraph-start' also. A line matching this is not part of any paragraph. @@ -132,34 +120,82 @@ This is matched against the text at the left margin, which is not necessarily the beginning of the line, so it should not use \"^\" as an anchor. This ensures that the paragraph functions will work equally within a region of -text indented by a margin setting.") - -(defconst sentence-end "[.?!][]\"')}]*\\($\\| $\\|\t\\| \\)[ \t\n]*" "\ -*Regexp describing the end of a sentence. +text indented by a margin setting." + :group 'paragraphs + :type 'regexp) + +(defcustom sentence-end-double-space t + "*Non-nil means a single space does not end a sentence. +This is relevant for filling. See also `sentence-end-without-period' +and `colon-double-space'. + +This variable applies only to filling, not motion commands. To +change the behavior of motion commands, see `sentence-end'. + +If you change this, you should also change `sentence-end'. See Info +node `Sentences'." + :type 'boolean + :group 'fill) + +(defcustom sentence-end-without-period nil + "*Non-nil means a sentence will end without a period. +For example, a sentence in Thai text ends with double space but +without a period." + :type 'boolean + :group 'fill) + +(defcustom sentence-end + (purecopy + ;; This is a bit stupid since it's not auto-updated when the + ;; other variables are changed, but it's still useful info. + (concat (if sentence-end-without-period "\\w \\|") + "[.?!" + (if (featurep 'mule) + (decode-coding-string "\033$B!#!%!)!*\033$A!##.#?#!\033$(0!$!%!)!*\033$(G!$!%!)!*\033(B" 'iso-2022-7bit) + "") + "][]\"')}]*" + (if sentence-end-double-space + "\\($\\| $\\|\t\\| \\)" "\\($\\|[\t ]\\)") + "[ \t\n]*")) + "*Regexp describing the end of a sentence. +The value includes the whitespace following the sentence. All paragraph boundaries also end sentences, regardless. -In order to be recognized as the end of a sentence, the ending period, -question mark, or exclamation point must be followed by two spaces, -unless it's inside some sort of quotes or parenthesis.") - -(defconst page-delimiter "^\014" "\ -*Regexp describing line-beginnings that separate pages.") - -(defvar paragraph-ignore-fill-prefix nil "\ -Non-nil means the paragraph commands are not affected by `fill-prefix'. -This is desirable in modes where blank lines are the paragraph delimiters.") +The default value specifies that in order to be recognized as the end +of a sentence, the ending period, question mark, or exclamation point +must be followed by two spaces, unless it's inside some sort of quotes +or parenthesis. + +See also the variable `sentence-end-double-space', the variable +`sentence-end-without-period' and Info node `Sentences'." + :group 'paragraphs + :type 'regexp) + +(defcustom page-delimiter "^\014" + "*Regexp describing line-beginnings that separate pages." + :group 'paragraphs + :type 'regexp) + +(defcustom paragraph-ignore-fill-prefix nil + "*Non-nil means the paragraph commands are not affected by `fill-prefix'. +This is desirable in modes where blank lines are the paragraph delimiters." + :group 'paragraphs + :type 'boolean) (defun forward-paragraph (&optional arg) "Move forward to end of paragraph. -With arg N, do it N times; negative arg -N means move backward N paragraphs. +With argument ARG, do it ARG times; +a negative argument ARG = -N means move backward N paragraphs. A line which `paragraph-start' matches either separates paragraphs \(if `paragraph-separate' matches it also) or is the first line of a paragraph. A paragraph end is the beginning of a line which is not part of the paragraph -to which the end of the previous line belongs, or the end of the buffer." +to which the end of the previous line belongs, or the end of the buffer. +Returns the count of paragraphs left to move." (interactive "_p") ; XEmacs (or arg (setq arg 1)) - (let* ((fill-prefix-regexp + (let* ((opoint (point)) + (fill-prefix-regexp (and fill-prefix (not (equal fill-prefix "")) (not paragraph-ignore-fill-prefix) (regexp-quote fill-prefix))) @@ -168,70 +204,74 @@ ;; starting at the left-margin. This allows paragraph commands to ;; work normally with indented text. ;; This hack will not find problem cases like "whatever\\|^something". - (paragraph-start (if (and (not (equal "" paragraph-start)) - (equal ?^ (aref paragraph-start 0))) - (substring paragraph-start 1) - paragraph-start)) - (paragraph-separate (if (and (not (equal "" paragraph-start)) - (equal ?^ (aref paragraph-separate 0))) - (substring paragraph-separate 1) - paragraph-separate)) - (paragraph-separate + (parstart (if (and (not (equal "" paragraph-start)) + (equal ?^ (aref paragraph-start 0))) + (substring paragraph-start 1) + paragraph-start)) + (parsep (if (and (not (equal "" paragraph-separate)) + (equal ?^ (aref paragraph-separate 0))) + (substring paragraph-separate 1) + paragraph-separate)) + (parsep (if fill-prefix-regexp - (concat paragraph-separate "\\|" + (concat parsep "\\|" fill-prefix-regexp "[ \t]*$") - paragraph-separate)) + parsep)) ;; This is used for searching. - (sp-paragraph-start (concat "^[ \t]*\\(" paragraph-start "\\)")) - start) + (sp-parstart (concat "^[ \t]*\\(?:" parstart "\\|" parsep "\\)")) + start found-start) (while (and (< arg 0) (not (bobp))) - (if (and (not (looking-at paragraph-separate)) + (if (and (not (looking-at parsep)) (re-search-backward "^\n" (max (1- (point)) (point-min)) t) - (looking-at paragraph-separate)) - nil + (looking-at parsep)) + (setq arg (1+ arg)) (setq start (point)) ;; Move back over paragraph-separating lines. (backward-char 1) (beginning-of-line) (while (and (not (bobp)) (progn (move-to-left-margin) - (looking-at paragraph-separate))) - (forward-line -1)) + (looking-at parsep))) + (forward-line -1)) (if (bobp) nil + (setq arg (1+ arg)) ;; Go to end of the previous (non-separating) line. (end-of-line) ;; Search back for line that starts or separates paragraphs. (if (if fill-prefix-regexp - ;; There is a fill prefix; it overrides paragraph-start. + ;; There is a fill prefix; it overrides parstart. (let (multiple-lines) (while (and (progn (beginning-of-line) (not (bobp))) (progn (move-to-left-margin) - (not (looking-at paragraph-separate))) + (not (looking-at parsep))) (looking-at fill-prefix-regexp)) - (if (not (= (point) start)) - (setq multiple-lines t)) + (unless (= (point) start) + (setq multiple-lines t)) (forward-line -1)) (move-to-left-margin) - ;; Don't move back over a line before the paragraph - ;; which doesn't start with fill-prefix - ;; unless that is the only line we've moved over. - (and (not (looking-at fill-prefix-regexp)) - multiple-lines - (forward-line 1)) + ;; This deleted code caused a long hanging-indent line + ;; not to be filled together with the following lines. + ;; ;; Don't move back over a line before the paragraph + ;; ;; which doesn't start with fill-prefix + ;; ;; unless that is the only line we've moved over. + ;; (and (not (looking-at fill-prefix-regexp)) + ;; multiple-lines + ;; (forward-line 1)) (not (bobp))) - (while (and (re-search-backward sp-paragraph-start nil 1) + (while (and (re-search-backward sp-parstart nil 1) + (setq found-start t) ;; Found a candidate, but need to check if it is a - ;; REAL paragraph-start. - (not (bobp)) + ;; REAL parstart. (progn (setq start (point)) (move-to-left-margin) - (not (looking-at paragraph-separate))) - (or (not (looking-at paragraph-start)) - (and use-hard-newlines - (not (get-text-property (1- start) - 'hard))))) + (not (looking-at parsep))) + (not (and (looking-at parstart) + (or (not use-hard-newlines) + (get-text-property (1- start) 'hard) + (bobp))))) + (setq found-start nil) (goto-char start)) - (> (point) (point-min))) + found-start) ;; Found one. (progn ;; Move forward over paragraph separators. @@ -239,7 +279,7 @@ ;; because we know we moved back over a non-separator. (while (and (not (eobp)) (progn (move-to-left-margin) - (looking-at paragraph-separate))) + (looking-at parsep))) (forward-line 1)) ;; If line before paragraph is just margin, back up to there. (end-of-line 0) @@ -249,38 +289,44 @@ (if (not (bolp)) (forward-line 1)))) ;; No starter or separator line => use buffer beg. - (goto-char (point-min))))) - (setq arg (1+ arg))) + (goto-char (point-min)))))) + (while (and (> arg 0) (not (eobp))) - ;; Move forward over separator lines, and one more line. - (while (prog1 (and (not (eobp)) - (progn (move-to-left-margin) (not (eobp))) - (looking-at paragraph-separate)) - (forward-line 1))) + ;; Move forward over separator lines... + (while (and (not (eobp)) + (progn (move-to-left-margin) (not (eobp))) + (looking-at parsep)) + (forward-line 1)) + (unless (eobp) (setq arg (1- arg))) + ;; ... and one more line. + (forward-line 1) (if fill-prefix-regexp - ;; There is a fill prefix; it overrides paragraph-start. + ;; There is a fill prefix; it overrides parstart. (while (and (not (eobp)) (progn (move-to-left-margin) (not (eobp))) - (not (looking-at paragraph-separate)) + (not (looking-at parsep)) (looking-at fill-prefix-regexp)) (forward-line 1)) - (while (and (re-search-forward sp-paragraph-start nil 1) + (while (and (re-search-forward sp-parstart nil 1) (progn (setq start (match-beginning 0)) (goto-char start) (not (eobp))) (progn (move-to-left-margin) - (not (looking-at paragraph-separate))) - (or (not (looking-at paragraph-start)) + (not (looking-at parsep))) + (or (not (looking-at parstart)) (and use-hard-newlines (not (get-text-property (1- start) 'hard))))) (forward-char 1)) (if (< (point) (point-max)) - (goto-char start))) - (setq arg (1- arg))))) + (goto-char start)))) + (constrain-to-field nil opoint t) + ;; Return the number of steps that could not be done. + arg)) (defun backward-paragraph (&optional arg) "Move backward to start of paragraph. -With arg N, do it N times; negative arg -N means move forward N paragraphs. +With argument ARG, do it ARG times; +a negative argument ARG = -N means move forward N paragraphs. A paragraph start is the beginning of a line which is a `first-line-of-paragraph' or which is ordinary text and follows a @@ -296,16 +342,29 @@ (defun mark-paragraph (&optional arg) "Put point at beginning of this paragraph, mark at end. The paragraph marked is the one that contains point or follows point. -With arg N, puts mark at end of following N paragraphs; -negative arg -N means point is put at end of this paragraph, mark is put -at beginning of this or a previous paragraph." + +With argument ARG, puts mark at end of a following paragraph, so that +the number of paragraphs marked equals ARG. + +If ARG is negative, point is put at end of this paragraph, mark is put +at beginning of this or a previous paragraph. + +If this command is repeated, it marks the next ARG paragraphs after (or +before, if arg is negative) the ones already marked." (interactive "p") (unless arg (setq arg 1)) (when (zerop arg) (error "Cannot mark zero paragraphs")) - (forward-paragraph arg) - (push-mark nil t t) - (backward-paragraph arg)) + (cond ((and (eq last-command this-command) (mark t)) + (set-mark + (save-excursion + (goto-char (mark)) + (forward-paragraph arg) + (point)))) + (t + (forward-paragraph arg) + (push-mark nil t t) + (backward-paragraph arg)))) (defun kill-paragraph (arg) "Kill forward to end of paragraph. @@ -359,18 +418,23 @@ sentences. A paragraph boundary also terminates a sentence." (interactive "_p") ; XEmacs (or arg (setq arg 1)) - (while (< arg 0) - (let ((par-beg (save-excursion (start-of-paragraph-text) (point)))) - (if (re-search-backward (concat sentence-end "[^ \t\n]") par-beg t) - (goto-char (1- (match-end 0))) - (goto-char par-beg))) - (setq arg (1+ arg))) - (while (> arg 0) - (let ((par-end (save-excursion (end-of-paragraph-text) (point)))) - (if (re-search-forward sentence-end par-end t) - (skip-chars-backward " \t\n") - (goto-char par-end))) - (setq arg (1- arg)))) + (let ((opoint (point))) + (while (< arg 0) + (let ((pos (point)) + (par-beg (save-excursion (start-of-paragraph-text) (point)))) + (if (and (re-search-backward sentence-end par-beg t) + (or (< (match-end 0) pos) + (re-search-backward sentence-end par-beg t))) + (goto-char (match-end 0)) + (goto-char par-beg))) + (setq arg (1+ arg))) + (while (> arg 0) + (let ((par-end (save-excursion (end-of-paragraph-text) (point)))) + (if (re-search-forward sentence-end par-end t) + (skip-chars-backward " \t\n") + (goto-char par-end))) + (setq arg (1- arg))) + (constrain-to-field nil opoint t))) (defun backward-sentence (&optional arg) "Move backward to start of sentence. With arg, do it arg times. @@ -392,14 +456,18 @@ (kill-region (point) (progn (backward-sentence arg) (point)))) (defun mark-end-of-sentence (arg) - "Put mark at end of sentence. Arg works as in `forward-sentence'." + "Put mark at end of sentence. Arg works as in `forward-sentence'. +If this command is repeated, it marks the next ARG sentences after the +ones already marked." (interactive "p") ;; FSF Version: -; (push-mark -; (save-excursion -; (forward-sentence arg) -; (point)) -; nil t)) +; (push-mark +; (save-excursion +; (if (and (eq last-command this-command) (mark t)) +; (goto-char (mark))) +; (forward-sentence arg) +; (point)) +; nil t)) (mark-something 'mark-end-of-sentence 'forward-sentence arg)) (defun mark-end-of-line (arg) @@ -407,10 +475,13 @@ (interactive "p") (mark-something 'mark-end-of-line 'end-of-line arg)) - (defun transpose-sentences (arg) "Interchange this (next) and previous sentence." (interactive "*p") (transpose-subr 'forward-sentence arg)) +;;; Local Variables: +;;; coding: iso-2022-7bit +;;; End: + ;;; paragraphs.el ends here diff --text -u 'xemacs-21.5.18/lisp/process.el' 'xemacs-21.5.19/lisp/process.el' Index: ./lisp/process.el --- ./lisp/process.el Mon Jan 6 03:38:37 2003 +++ ./lisp/process.el Sun Jan 9 18:44:44 2005 @@ -66,8 +66,9 @@ Process output goes at end of that buffer, unless you specify an output stream or filter function to handle the output. BUFFER may be also nil, meaning that this process is not associated - with any buffer -Third arg is command name, the name of a shell command. + with any buffer. +Variables `shell-file-name' and `shell-command-switch' are used to +start the process. Remaining arguments are the arguments for the command. Wildcards and redirection are handled as usual in the shell." ;; We used to use `exec' to replace the shell with the command, diff --text -u /dev/null 'xemacs-21.5.19/lisp/regexp-opt.el' Index: ./lisp/regexp-opt.el --- ./lisp/regexp-opt.el Thu Jan 1 09:00:00 1970 +++ ./lisp/regexp-opt.el Thu Feb 3 16:30:22 2005 @@ -0,0 +1,278 @@ +;;; regexp-opt.el --- generate efficient regexps to match strings + +;; Copyright (C) 1994,95,96,97,98,99,2000 Free Software Foundation, Inc. + +;; Author: Simon Marshall <simon@gnu.org> +;; Maintainer: FSF +;; Keywords: strings, regexps, extensions + +;; 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: GNU Emacs 21.3 + paren-in-char-set fix from CVS +;;; revision 1.25. Some implementation differences in +;;; regexp-opt-group and regexp-opt-charset but the APIs +;;; are compatible and should return compatible (if not +;;; exactly the same) regexps. + +;;; Commentary: + +;; The "opt" in "regexp-opt" stands for "optim\\(?:al\\|i\\(?:se\\|ze\\)\\)". +;; +;; This package generates a regexp from a given list of strings (which matches +;; one of those strings) so that the regexp generated by: +;; +;; (regexp-opt strings) +;; +;; is equivalent to, but more efficient than, the regexp generated by: +;; +;; (mapconcat 'regexp-quote strings "\\|") +;; +;; For example: +;; +;; (let ((strings '("cond" "if" "when" "unless" "while" +;; "let" "let*" "progn" "prog1" "prog2" +;; "save-restriction" "save-excursion" "save-window-excursion" +;; "save-current-buffer" "save-match-data" +;; "catch" "throw" "unwind-protect" "condition-case"))) +;; (concat "(" (regexp-opt strings t) "\\>")) +;; => "(\\(c\\(?:atch\\|ond\\(?:ition-case\\)?\\)\\|if\\|let\\*?\\|prog[12n]\\|save-\\(?:current-buffer\\|excursion\\|match-data\\|restriction\\|window-excursion\\)\\|throw\\|un\\(?:less\\|wind-protect\\)\\|wh\\(?:en\\|ile\\)\\)\\>" +;; +;; Searching using the above example `regexp-opt' regexp takes approximately +;; two-thirds of the time taken using the equivalent `mapconcat' regexp. + +;; Since this package was written to produce efficient regexps, not regexps +;; efficiently, it is probably not a good idea to in-line too many calls in +;; your code, unless you use the following trick with `eval-when-compile': +;; +;; (defvar definition-regexp +;; (eval-when-compile +;; (concat "^(" +;; (regexp-opt '("defun" "defsubst" "defmacro" "defalias" +;; "defvar" "defconst") t) +;; "\\>"))) +;; +;; The `byte-compile' code will be as if you had defined the variable thus: +;; +;; (defvar definition-regexp +;; "^(\\(def\\(alias\\|const\\|macro\\|subst\\|un\\|var\\)\\)\\>") +;; +;; Note that if you use this trick for all instances of `regexp-opt' and +;; `regexp-opt-depth' in your code, regexp-opt.el would only have to be loaded +;; at compile time. But note also that using this trick means that should +;; regexp-opt.el be changed, perhaps to fix a bug or to add a feature to +;; improve the efficiency of `regexp-opt' regexps, you would have to recompile +;; your code for such changes to have effect in your code. + +;; Originally written for font-lock.el, from an idea from Stig's hl319.el, with +;; thanks for ideas also to Michael Ernst, Bob Glickstein, Dan Nicolaescu and +;; Stefan Monnier. +;; No doubt `regexp-opt' doesn't always produce optimal regexps, so code, ideas +;; or any other information to improve things are welcome. +;; +;; One possible improvement would be to compile '("aa" "ab" "ba" "bb") +;; into "[ab][ab]" rather than "a[ab]\\|b[ab]". I'm not sure it's worth +;; it but if someone knows how to do it without going through too many +;; contortions, I'm all ears. + +;;; Code: + +;;;###autoload +(defun regexp-opt (strings &optional paren) + "Return a regexp to match a string in STRINGS. +Each string should be unique in STRINGS and should not contain any regexps, +quoted or not. If optional PAREN is non-nil, ensure that the returned regexp +is enclosed by at least one regexp grouping construct. +The returned regexp is typically more efficient than the equivalent regexp: + + (let ((open (if PAREN \"\\\\(\" \"\")) (close (if PAREN \"\\\\)\" \"\"))) + (concat open (mapconcat 'regexp-quote STRINGS \"\\\\|\") close)) + +If PAREN is `words', then the resulting regexp is additionally surrounded +by \\=\\< and \\>." + (save-match-data + ;; Recurse on the sorted list. + (let* ((max-lisp-eval-depth (* 1024 1024)) + (completion-ignore-case nil) + (words (eq paren 'words)) + (open (cond ((stringp paren) paren) (paren "\\("))) + (sorted-strings (sort (copy-sequence strings) 'string-lessp)) + (re (regexp-opt-group sorted-strings open))) + (if words (concat "\\<" re "\\>") re)))) + +(defconst regexp-opt-not-groupie*-re + (let* ((harmless-ch "[^\\\\[]") + (esc-pair-not-lp "\\\\[^(]") + (class-harmless-ch "[^][]") + (class-lb-harmless "[^]:]") + (class-lb-colon-maybe-charclass ":\\([a-z]+:]\\)?") + (class-lb (concat "\\[\\(" class-lb-harmless + "\\|" class-lb-colon-maybe-charclass "\\)")) + (class + (concat "\\[^?]?" + "\\(" class-harmless-ch + "\\|" class-lb "\\)*" + "\\[?]")) ; special handling for bare [ at end of re + (shy-lp "\\\\(\\?:")) + (concat "\\(" harmless-ch "\\|" esc-pair-not-lp + "\\|" class "\\|" shy-lp "\\)*")) + "Matches any part of a regular expression EXCEPT for non-shy \"\\\\(\"s") + +;;;###autoload +(defun regexp-opt-depth (regexp) + "Return the depth of REGEXP. +This means the number of regexp grouping constructs (parenthesised expressions) +in REGEXP." + (save-match-data + ;; Hack to signal an error if REGEXP does not have balanced parentheses. + (string-match regexp "") + ;; Count the number of open parentheses in REGEXP. + (let ((count 0) start) + (while + (progn + (string-match regexp-opt-not-groupie*-re regexp start) + (setq start ( + (match-end 0) 2)) ; +2 for "\\(" after match-end. + (<= start (length regexp))) + (setq count (1+ count))) + count))) + +;;; Workhorse functions. + +(eval-when-compile + (require 'cl)) + +(defun regexp-opt-group (strings &optional paren lax) + "Return a regexp to match a string in STRINGS. +If PAREN non-nil, output regexp parentheses around returned regexp. +If LAX non-nil, don't output parentheses if it doesn't require them. +Merges keywords to avoid backtracking in Emacs' regexp matcher. + +The basic idea is to find the shortest common prefix or suffix, remove it +and recurse. If there is no prefix, we divide the list into two so that +\(at least) one half will have at least a one-character common prefix. + +Also we delay the addition of grouping parenthesis as long as possible +until we're sure we need them, and try to remove one-character sequences +so we can use character sets rather than grouping parenthesis." + (let* ((open-group (cond ((stringp paren) paren) (paren "\\(?:") (t ""))) + (close-group (if paren "\\)" "")) + (open-charset (if lax "" open-group)) + (close-charset (if lax "" close-group))) + (cond + ;; + ;; If there are no strings, just return the empty string. + ((= (length strings) 0) + "") + ;; + ;; If there is only one string, just return it. + ((= (length strings) 1) + (if (= (length (car strings)) 1) + (concat open-charset (regexp-quote (car strings)) close-charset) + (concat open-group (regexp-quote (car strings)) close-group))) + ;; + ;; If there is an empty string, remove it and recurse on the rest. + ((= (length (car strings)) 0) + (concat open-charset + (regexp-opt-group (cdr strings) t t) "?" + close-charset)) + ;; + ;; If all are one-character strings, just return a character set. + ((= (length strings) (apply '+ (mapcar 'length strings))) + (concat open-charset + (regexp-opt-charset strings) + close-charset)) + ;; + ;; We have a list of different length strings. + (t + (let ((prefix (try-completion "" (mapcar 'list strings))) + (letters (let ((completion-regexp-list '("^.$"))) + (all-completions "" (mapcar 'list strings))))) + (cond + ;; + ;; If there is a common prefix, remove it and recurse on the suffixes. + ((> (length prefix) 0) + (let* ((length (length prefix)) + (suffixes (mapcar (lambda (s) (substring s length)) strings))) + (concat open-group + (regexp-quote prefix) (regexp-opt-group suffixes t t) + close-group))) + ;; + ;; If there are several one-character strings, remove them and recurse + ;; on the rest (first so the final regexp finds the longest match). + ((> (length letters) 1) + (let ((rest (let ((completion-regexp-list '("^..+$"))) + (all-completions "" (mapcar 'list strings))))) + (concat open-group + (regexp-opt-group rest) "\\|" (regexp-opt-charset letters) + close-group))) + ;; + ;; Otherwise, divide the list into those that start with a particular + ;; letter and those that do not, and recurse on them. + (t + (let* ((char (substring (car strings) 0 1)) + (half1 (all-completions char (mapcar 'list strings))) + (half2 (nthcdr (length half1) strings))) + (concat open-group + (regexp-opt-group half1) "\\|" (regexp-opt-group half2) + close-group))))))))) + +(defun regexp-opt-charset (chars) + ;; + ;; Return a regexp to match a character in CHARS. + ;; + ;; The basic idea is to find character ranges. Also we take care in the + ;; position of character set meta characters in the character set regexp. + ;; + (let* ((charwidth 256) ; Yeah, right. + ;; XEmacs: use bit-vectors instead of bool-vectors + (charmap (make-bit-vector charwidth 0)) + (charset "") + (bracket "") (dash "") (caret "")) + ;; + ;; Make a character map but extract character set meta characters. + (dolist (char (mapcar 'string-to-char chars)) + (case char + (?\] + (setq bracket "]")) + (?^ + (setq caret "^")) + (?- + (setq dash "-")) + (otherwise + ;; XEmacs: 1 + (aset charmap char 1)))) + ;; + ;; Make a character set from the map using ranges where applicable. + (dotimes (char charwidth) + (let ((start char)) + (while (and (< char charwidth) + ;; XEmacs: (not (zerop ...)) + (not (zerop (aref charmap char)))) + (incf char)) + (cond ((> char (+ start 3)) + (setq charset (format "%s%c-%c" charset start (1- char)))) + ((> char start) + (setq charset (format "%s%c" charset (setq char start))))))) + ;; + ;; Make sure a caret is not first and a dash is first or last. + (if (and (string-equal charset "") (string-equal bracket "")) + (concat "[" dash caret "]") + (concat "[" bracket charset caret dash "]")))) + +(provide 'regexp-opt) + +;;; regexp-opt.el ends here diff --text -u 'xemacs-21.5.18/lisp/register.el' 'xemacs-21.5.19/lisp/register.el' Index: ./lisp/register.el --- ./lisp/register.el Sun Jul 12 16:30:39 1998 +++ ./lisp/register.el Wed Jan 26 18:56:06 2005 @@ -1,4 +1,4 @@ -;;; register.el --- register commands for Emacs. +;;; register.el --- register commands for Emacs ;; Copyright (C) 1985, 1993, 1994, 1997 Free Software Foundation, Inc. @@ -22,7 +22,7 @@ ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ;; 02111-1307, USA. -;;; Synched up with: FSF 20.3 +;;; Synched up with: FSF 21.3 ;;; Commentary: @@ -57,8 +57,7 @@ (let ((aelt (assq register register-alist))) (if aelt (setcdr aelt value) - (setq aelt (cons register value)) - (setq register-alist (cons aelt register-alist))) + (push (cons register value) register-alist)) value)) (defun point-to-register (register &optional arg) @@ -67,6 +66,8 @@ Use \\[jump-to-register] to go to that location or restore that configuration. Argument is a character, naming the register." (interactive "cPoint to register: \nP") + ;; Turn the marker into a file-ref if the buffer is killed. + (add-hook 'kill-buffer-hook 'register-swap-out nil t) (set-register register (if arg (list (current-frame-configuration) (point-marker)) (point-marker)))) @@ -125,20 +126,16 @@ (t (error "Register doesn't contain a buffer position or configuration"))))) -;; Turn markers into file-query references when a buffer is killed. (defun register-swap-out () + "Turn markers into file-query references when a buffer is killed." (and buffer-file-name - (let ((tail register-alist)) - (while tail - (and (markerp (cdr (car tail))) - (eq (marker-buffer (cdr (car tail))) (current-buffer)) - (setcdr (car tail) - (list 'file-query - buffer-file-name - (marker-position (cdr (car tail)))))) - (setq tail (cdr tail)))))) - -(add-hook 'kill-buffer-hook 'register-swap-out) + (dolist (elem register-alist) + (and (markerp (cdr elem)) + (eq (marker-buffer (cdr elem)) (current-buffer)) + (setcdr elem + (list 'file-query + buffer-file-name + (marker-position (cdr elem)))))))) (defun number-to-register (number register) "Store a number in a register. @@ -147,7 +144,7 @@ at point, and point moves to the end of that number. Interactively, NUMBER is the prefix arg (none means nil)." (interactive "P\ncNumber to register: ") - (set-register register + (set-register register (if number (prefix-numeric-value number) (if (looking-at "\\s-*-?[0-9]+") @@ -172,54 +169,89 @@ (if (null val) (message "Register %s is empty" (single-key-description register)) (with-output-to-temp-buffer "*Output*" - (princ "Register ") - (princ (single-key-description register)) - (princ " contains ") - (cond - ((numberp val) - (princ val)) + (describe-register-1 register t))))) - ((markerp val) - (let ((buf (marker-buffer val))) - (if (null buf) - (princ "a marker in no buffer") - (princ "a buffer position:\nbuffer ") - (princ (buffer-name buf)) - (princ ", position ") - (princ (marker-position val))))) - - ((and (consp val) (window-configuration-p (car val))) - (princ "a window configuration.")) - - ((and (consp val) (frame-configuration-p (car val))) - (princ "a frame configuration.")) - - ((and (consp val) (eq (car val) 'file)) - (princ "the file ") - (prin1 (cdr val)) - (princ ".")) - - ((and (consp val) (eq (car val) 'file-query)) - (princ "a file-query reference:\nfile ") - (prin1 (car (cdr val))) - (princ ",\nposition ") - (princ (car (cdr (cdr val)))) - (princ ".")) - - ((consp val) - (princ "the rectangle:\n") - (while val - (princ (car val)) - (terpri) - (setq val (cdr val)))) - - ((stringp val) - (princ "the text:\n") - (princ val)) +(defun list-registers () + "Display a list of nonempty registers saying briefly what they contain." + (interactive) + (let ((list (copy-sequence register-alist))) + (setq list (sort list (lambda (a b) (< (car a) (car b))))) + (with-output-to-temp-buffer "*Output*" + (dolist (elt list) + (when (get-register (car elt)) + (describe-register-1 (car elt)) + (terpri)))))) + +(defun describe-register-1 (register &optional verbose) + (princ "Register ") + (princ (single-key-description register)) + (princ " contains ") + (let ((val (get-register register))) + (cond + ((numberp val) + (princ val)) + ((markerp val) + (let ((buf (marker-buffer val))) + (if (null buf) + (princ "a marker in no buffer") + (princ "a buffer position:\n buffer ") + (princ (buffer-name buf)) + (princ ", position ") + (princ (marker-position val))))) + + ((and (consp val) (window-configuration-p (car val))) + (princ "a window configuration.")) + + ((and (consp val) (frame-configuration-p (car val))) + (princ "a frame configuration.")) + + ((and (consp val) (eq (car val) 'file)) + (princ "the file ") + (prin1 (cdr val)) + (princ ".")) + + ((and (consp val) (eq (car val) 'file-query)) + (princ "a file-query reference:\n file ") + (prin1 (car (cdr val))) + (princ ",\n position ") + (princ (car (cdr (cdr val)))) + (princ ".")) + + ((consp val) + (if verbose + (progn + (princ "the rectangle:\n") + (while val + (princ " ") + (princ (car val)) + (terpri) + (setq val (cdr val)))) + (princ "a rectangle starting with ") + (princ (car val)))) + + ((stringp val) + (remove-list-of-text-properties 0 (length val) + yank-excluded-properties val) + (if verbose + (progn + (princ "the text:\n") + (princ val)) + (cond + ;; Extract first N characters starting with first non-whitespace. + ((string-match (format "[^ \t\n].\\{,%d\\}" + ;; Deduct 6 for the spaces inserted below. + (min 20 (max 0 (- (window-width) 6)))) + val) + (princ "text starting with\n ") + (princ (match-string 0 val))) + ((string-match "^[ \t\n]+$" val) + (princ "whitespace")) (t - (princ "Garbage:\n") - (prin1 val))))))) + (princ "the empty string"))))) + (t + (princ "Garbage:\n") + (if verbose (prin1 val)))))) (defun insert-register (register &optional arg) "Insert contents of register REGISTER. (REGISTER is a character.) @@ -233,7 +265,7 @@ ((consp val) (insert-rectangle val)) ((stringp val) - (insert val)) + (insert-for-yank val)) ((numberp val) (princ val (current-buffer))) ((and (markerp val) (marker-position val)) diff --text -u 'xemacs-21.5.18/lisp/setup-paths.el' 'xemacs-21.5.19/lisp/setup-paths.el' Index: ./lisp/setup-paths.el --- ./lisp/setup-paths.el Fri Jun 13 09:11:16 2003 +++ ./lisp/setup-paths.el Mon Dec 27 21:25:15 2004 @@ -5,7 +5,7 @@ ;; Copyright (C) 1995 Board of Trustees, University of Illinois ;; Copyright (C) 2003 Ben Wing. -;; Author: Mike Sperber <sperber@informatik.uni-tuebingen.de> +;; Author: Mike Sperber <mike@xemacs.orgx> ;; Maintainer: XEmacs Development Team ;; Keywords: internal, dumped @@ -34,7 +34,10 @@ ;; This file contains functions and variables that describe and construct ;; the various paths into the XEmacs hierarchy from a global viewpoint. -;; This file doesn't actually do anything. + +;; This file doesn't actually set any global variable, and doesn't +;; contain any state---it just contains the functionality for +;; searching directories and constructing paths. ;; It requires find-paths.el and packages.el. @@ -43,51 +46,6 @@ ;(setq debug-paths t) -;;; Path-related variables. -;;; NOTE: Many of them (`lisp-directory', `data-directory', etc.) are -;;; built-in. - -(defvar emacs-roots nil - "List of plausible roots of the XEmacs hierarchy. -This is a list of plausible directories in which to search for the important -directories used by XEmacs at run-time, for example `exec-directory', -`data-directory' and `lisp-directory'. - -Normally set at startup by calling `paths-find-emacs-roots'.") - -(defvar emacs-data-roots nil - "List of plausible data roots of the XEmacs hierarchy.") - -(defvar user-init-directory-base ".xemacs" - "Base of directory where user-installed init files may go.") - -(defvar user-init-directory - (file-name-as-directory - (paths-construct-path (list "~" user-init-directory-base))) - "Directory where user-installed init files may go.") - -(defvar user-init-file-base "init.el" - "Default name of the user init file if uncompiled. -This should be used for migration purposes only.") - -(defvar user-init-file-base-list '("init.el") - "List of allowed init files in the user's init directory. -The first one found takes precedence. .elc files do not need to be listed.") - -(defvar user-home-init-file-base-list - (append '(".emacs.el" ".emacs") - (and (eq system-type 'windows-nt) - '("_emacs.el" "_emacs"))) - "List of allowed init files in the user's home directory. -The first one found takes precedence. .elc files do not need to be listed.") - -(defvar load-home-init-file nil - "Non-nil if XEmacs should load the init file from the home directory. -Otherwise, XEmacs will offer migration to the init directory.") - -(defvar load-user-init-file-p t - "Non-nil if XEmacs should load the user's init file.") - (defvar paths-core-load-path-depth 0 "Depth of load-path searches in core Lisp paths.") @@ -130,7 +88,9 @@ (defun paths-emacs-data-root-p (directory) "Check if DIRECTORY is a plausible data installation root. A data installation root is one containing data files that may be shared -among multiple different versions of XEmacs, the packages in particular." +among multiple different versions of XEmacs, the packages in particular. +This serves as an additional filter to narrow down the list of plausible +installation roots." (or ;; installed (paths-file-readable-directory-p (paths-construct-path (list directory @@ -145,7 +105,9 @@ (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." + "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))) @@ -159,7 +121,9 @@ (and (paths-emacs-root-p maybe-root-2) maybe-root-2)))) -(defun paths-find-emacs-roots (root-p) +(defun paths-find-emacs-roots (invocation-directory + invocation-name + root-p) "Find all plausible installation roots for XEmacs. This is a list of plausible directories in which to search for the important directories used by XEmacs at run-time, for example `exec-directory', @@ -184,25 +148,29 @@ installation-roots))) (defun paths-find-site-lisp-directory (roots) - "Find the site Lisp directory of the XEmacs hierarchy." + "Find the site Lisp directory of the XEmacs hierarchy. +ROOTS is a list of installation roots." (paths-find-site-directory roots "site-lisp" nil configure-site-directory)) (defun paths-find-site-module-directory (roots) - "Find the site modules directory of the XEmacs hierarchy." + "Find the site modules directory of the XEmacs hierarchy. +ROOTS is a list of installation roots." (paths-find-site-directory roots "site-modules" nil configure-site-module-directory)) (defun paths-find-lisp-directory (roots) - "Find the main Lisp directory of the XEmacs hierarchy." + "Find the main Lisp directory of the XEmacs hierarchy. +ROOTS is a list of installation roots." (paths-find-version-directory roots "lisp" nil configure-lisp-directory)) (defun paths-find-mule-lisp-directory (roots &optional lisp-directory) - "Find the Mule Lisp directory of the XEmacs hierarchy." + "Find the Mule Lisp directory of the XEmacs hierarchy. +ROOTS is a list of installation roots." ;; #### kludge (if lisp-directory (let ((guess @@ -215,7 +183,8 @@ configure-mule-lisp-directory))))) (defun paths-find-module-directory (roots) - "Find the main modules directory of the XEmacs hierarchy." + "Find the main modules directory of the XEmacs hierarchy. +ROOTS is a list of installation roots." (paths-find-architecture-directory roots "modules" nil configure-module-directory)) @@ -223,7 +192,14 @@ (roots early-package-load-path late-package-load-path last-package-load-path lisp-directory &optional site-lisp-directory mule-lisp-directory) - "Construct the load path." + "Construct the complete load path. +ROOTS is the list of installation roots. +EARLY-PACKAGE-LOAD-PATH, LATE-PACKAGE-LOAD-PATH, and LAST-PACKAGE-LOAD-PATH +are the load paths for the package hierarchies. +SITE-LISP-DIRECTORY and MULE-LISP-DIRECTORY are optional directories to be +included in the load path---SITE-LISP-DIRECTORY for the obsolete site-specific +Lisp files, and MULE-LISP-DIRECTORY for the Mule Lisp files, which exist +only in Mule installations." (let* ((envvar-value (getenv "EMACSLOADPATH")) (env-load-path (and envvar-value @@ -263,12 +239,19 @@ (and module-directory (paths-find-recursive-load-path (list module-directory) paths-core-load-path-depth)))) - (append env-module-path + (append env-module-path site-module-load-path module-load-path))) -(defun paths-construct-info-path (roots early-packages late-packages last-packages) - "Construct the info path." +(defun paths-construct-info-path (roots + early-package-hierarchies + late-package-hierarchies + last-package-hierarchies) + "Construct the info path. +ROOTS is the list of installation roots. +EARLY-PACKAGE-HIERARCHIES, LATE-PACKAGE-HIERARCHIES, and +LAST-PACKAGE-HIERARCHIES are lists of package hierarchy roots, +respectively." (let ((info-path-envval (getenv "INFOPATH"))) (paths-uniq-append (append @@ -278,9 +261,9 @@ configure-info-directory))) (and info-directory (list info-directory))) - (packages-find-package-info-path early-packages) - (packages-find-package-info-path late-packages) - (packages-find-package-info-path last-packages) + (packages-find-package-info-path early-package-hierarchies) + (packages-find-package-info-path late-package-hierarchies) + (packages-find-package-info-path last-package-hierarchies) (and info-path-envval (paths-decode-directory-path info-path-envval 'drop-empties))) (and (null info-path-envval) @@ -289,259 +272,60 @@ (paths-directories-which-exist paths-default-info-directories)))))) (defun paths-find-doc-directory (roots) - "Find the documentation directory." + "Find the documentation directory. +ROOTS is the list of installation roots." (paths-find-architecture-directory roots "lib-src" nil configure-doc-directory)) (defun paths-find-exec-directory (roots) - "Find the binary directory." + "Find the binary directory. +ROOTS is the list of installation roots." (paths-find-architecture-directory roots "lib-src" nil configure-exec-directory)) (defun paths-construct-exec-path (roots exec-directory - early-packages late-packages last-packages) - "Find the binary path." + early-package-hierarchies + late-package-hierarchies + last-package-hierarchies) + "Find the binary path. +ROOTS is the list of installation roots. +EARLY-PACKAGE-HIERARCHIES, LATE-PACKAGE-HIERARCHIES, and +LAST-PACKAGE-HIERARCHIES are lists of package hierarchy roots, +respectively. +EXEC-DIRECTORY is the directory of architecture-dependent files that +come with XEmacs. +EARLY-PACKAGES, LATE-PACKAGES, and LAST-PACKAGES are lists of +package hierarchy roots, respectively." (append (let ((path-envval (getenv "PATH"))) (if path-envval (paths-decode-directory-path path-envval 'drop-empties))) - (packages-find-package-exec-path early-packages) - (packages-find-package-exec-path late-packages) + (packages-find-package-exec-path early-package-hierarchies) + (packages-find-package-exec-path late-package-hierarchies) (let ((emacspath-envval (getenv "EMACSPATH"))) (and emacspath-envval (split-path emacspath-envval))) (and exec-directory (list exec-directory)) - (packages-find-package-exec-path last-packages))) + (packages-find-package-exec-path last-package-hierarchies))) (defun paths-find-data-directory (roots) - "Find the data directory." + "Find the data directory. +ROOTS is the list of installation roots." (paths-find-version-directory roots "etc" "EMACSDATA" configure-data-directory)) (defun paths-construct-data-directory-list (data-directory - early-packages late-packages last-packages) - "Find the data path." + early-package-hierarchies + late-package-hierarchies + last-package-hierarchies) + "Construct the data path. +DATA-DIRECTORY is the data directory of the XEmacs installation. +EARLY-PACKAGE-HIERARCHIES, LATE-PACKAGE-HIERARCHIES, and +LAST-PACKAGE-HIERARCHIES are lists of package hierarchy roots, +respectively." (append - (packages-find-package-data-path early-packages) - (packages-find-package-data-path late-packages) + (packages-find-package-data-path early-package-hierarchies) + (packages-find-package-data-path late-package-hierarchies) (list data-directory) - (packages-find-package-data-path last-packages))) - - -;;; High-level functions to set up the paths. - -(defun startup-find-load-path (&optional inhibit-packages - set-global-package-paths) - "Determine the value for `load-path'. -INHIBIT-PACKAGES says which types of packages, if any, to omit from the -returned value. It can be `t' (omit all), one of the symbols `early', -`late', or `last', or a list of one or more of the symbols. - -If SET-GLOBAL-PACKAGE-PATHS is non-nil, initialize the global package path -variables referring to the particular types of packages (`early-packages', -`early-package-load-path', `late-packages', `late-package-load-path', -`last-packages', `last-package-load-path')." - (let (earlyp latep lastp earlyp-lp latep-lp lastp-lp) - (apply #'(lambda (early late last) - (setq earlyp (and (not (memq 'early inhibit-packages)) early)) - (setq latep (and (not (memq 'late inhibit-packages)) late)) - (setq lastp (and (not (memq 'last inhibit-packages)) last))) - (packages-find-packages - emacs-data-roots - (packages-compute-package-locations user-init-directory))) - - (setq earlyp-lp (packages-find-package-load-path earlyp)) - (setq latep-lp (packages-find-package-load-path latep)) - (setq lastp-lp (packages-find-package-load-path lastp)) - - (when set-global-package-paths - (setq early-packages earlyp - late-packages latep - last-packages lastp - early-package-load-path earlyp-lp - late-package-load-path latep-lp - last-package-load-path lastp-lp)) - - (paths-construct-load-path emacs-roots earlyp-lp latep-lp lastp-lp - lisp-directory site-directory - mule-lisp-directory))) - -(defun startup-setup-paths (&optional inhibit-packages called-early) - "Setup all the various paths. -INHIBIT-PACKAGES says which types of packages, if any, to omit from the -returned value. It can be `t' (omit all), one of the symbols `early', -`late', or `last', or a list of one or more of the symbols. - -This function is idempotent, so call this as often as you like!" - - (setq debug-paths (or debug-paths - (and (getenv "EMACSDEBUGPATHS") - t))) - - (setq emacs-roots (paths-find-emacs-roots #'paths-emacs-data-root-p)) - - (setq emacs-data-roots (paths-find-emacs-roots #'paths-emacs-data-root-p)) - - (if (null emacs-roots) - (save-excursion - (set-buffer (get-buffer-create " *warning-tmp*")) - (erase-buffer) - (buffer-disable-undo (current-buffer)) - - (insert "Couldn't find an obvious default for the root of the\n" - "XEmacs hierarchy.") - - (princ "\nWARNING:\n" 'external-debugging-output) - (princ (buffer-string) 'external-debugging-output))) - - (if (eq inhibit-packages t) - (setq inhibit-packages '(early late last))) - (if (not (listp inhibit-packages)) - (setq inhibit-packages (list inhibit-packages))) - - (when debug-paths - (princ (format -"startup-setup-paths arguments: - inhibit-packages: %S - inhibit-site-lisp: %S - called-early: %S -" inhibit-packages inhibit-site-lisp called-early) - 'external-debugging-output) - (princ (format -"emacs-roots: -%S -emacs-data-roots: -%S -user-init-directory: %S -configure-package-path: %S -" emacs-roots emacs-data-roots user-init-directory configure-package-path) - 'external-debugging-output) - ) - - (setq lisp-directory (paths-find-lisp-directory emacs-roots)) - - (if debug-paths - (princ (format "lisp-directory:\n%S\n" lisp-directory) - 'external-debugging-output)) - - (if (featurep 'mule) - (progn - (setq mule-lisp-directory - (paths-find-mule-lisp-directory emacs-roots - lisp-directory)) - (if debug-paths - (princ (format "mule-lisp-directory:\n%S\n" - mule-lisp-directory) - 'external-debugging-output))) - (setq mule-lisp-directory '())) - - (setq site-directory (and (null inhibit-site-lisp) - (paths-find-site-lisp-directory emacs-roots))) - - (if (and debug-paths (null inhibit-site-lisp)) - (princ (format "site-directory:\n%S\n" site-directory) - 'external-debugging-output)) - - (setq load-path (startup-find-load-path inhibit-packages t)) - - (when debug-paths - (princ (format "early-packages and early-package-load-path:\n%S\n%S\n" - early-packages early-package-load-path) - 'external-debugging-output) - (princ (format "late-packages and late-package-load-path:\n%S\n%S\n" - late-packages late-package-load-path) - 'external-debugging-output) - (princ (format "last-packages and last-package-load-path:\n%S\n%S\n" - last-packages last-package-load-path) - 'external-debugging-output)) - - (if debug-paths - (princ (format "load-path:\n%S\n" load-path) - 'external-debugging-output)) - (setq module-directory (paths-find-module-directory emacs-roots)) - (if debug-paths - (princ (format "module-directory:\n%S\n" module-directory) - 'external-debugging-output)) - (setq site-module-directory (and (null inhibit-site-modules) - (paths-find-site-module-directory - emacs-roots))) - (if (and debug-paths (null inhibit-site-modules)) - (princ (format "site-module-directory:\n%S\n" - site-module-directory) - 'external-debugging-output)) - - (setq module-load-path (paths-construct-module-load-path - emacs-roots - module-directory - site-module-directory)) - - (unless called-early - (setq Info-directory-list - (paths-construct-info-path - emacs-roots early-packages late-packages last-packages)) - - (if debug-paths - (princ (format "Info-directory-list:\n%S\n" Info-directory-list) - 'external-debugging-output)) - - (setq exec-directory (paths-find-exec-directory emacs-roots)) - - (if debug-paths - (princ (format "exec-directory:\n%s\n" exec-directory) - 'external-debugging-output)) - - (setq exec-path - (paths-construct-exec-path emacs-roots exec-directory - early-packages late-packages - last-packages)) - - (if debug-paths - (princ (format "exec-path:\n%S\n" exec-path) - 'external-debugging-output)) - - (setq doc-directory (paths-find-doc-directory emacs-roots)) - - (if debug-paths - (princ (format "doc-directory:\n%S\n" doc-directory) - 'external-debugging-output)) - - (setq data-directory (paths-find-data-directory emacs-roots)) - - (if debug-paths - (princ (format "data-directory:\n%S\n" data-directory) - 'external-debugging-output)) - - (setq data-directory-list (paths-construct-data-directory-list - data-directory early-packages - late-packages last-packages)) - (if debug-paths - (princ (format "data-directory-list:\n%S\n" data-directory-list) - 'external-debugging-output)))) - -(defun startup-find-load-path-for-packages (packages) - "Return a suitable load-path for PACKAGES. -PACKAGES is a list of package names (strings). This looks for package -directories in the load path whose last component is one of the members of -PACKAGES." - (mapcan - #'(lambda (package) - (and (member (file-name-nondirectory (directory-file-name package)) - packages) - (list package))) - (startup-find-load-path))) - -; (defun startup-set-basic-packages-load-path () -; "#### This is a hack. When recompiling .el files, we use -no-packages -; to avoid problems with packages shadowing standard Lisp files -; (e.g. unicode.el), but we really still need the stuff in xemacs-base and -; xemacs-devel, which SHOULD NOT be in the packages." -; (setq load-path (startup-find-load-path-for-packages -; '("xemacs-base" "xemacs-devel")))) - - -;;; Now actually set the paths up, for bootstrapping purposes. This is run -;;; at early dump time and in certain cases where we use a minimal temacs -;;; to do useful things, like rebuild DOC. - -(startup-setup-paths (if inhibit-all-packages t '(early last)) t) + (packages-find-package-data-path last-package-hierarchies))) ;;; setup-paths.el ends here diff --text -u 'xemacs-21.5.18/lisp/shadow.el' 'xemacs-21.5.19/lisp/shadow.el' Index: ./lisp/shadow.el --- ./lisp/shadow.el Sun Jun 10 19:42:23 2001 +++ ./lisp/shadow.el Fri Feb 4 11:59:27 2005 @@ -114,6 +114,7 @@ '("subdirs" "auto-autoloads" "custom-load" + "custom-defines" "dumped-lisp" "_pkg" "lpath"))) diff --text -u 'xemacs-21.5.18/lisp/simple.el' 'xemacs-21.5.19/lisp/simple.el' Index: ./lisp/simple.el --- ./lisp/simple.el Sat Sep 20 10:46:54 2003 +++ ./lisp/simple.el Mon Jan 17 20:23:01 2005 @@ -1979,7 +1979,7 @@ When the region has been enabled or augmented as a result of a shifted motion key, an unshifted motion key will normally deselect the region. -However, if `unshifted-motion-keys-deselect-region' is t, the region +However, if `unshifted-motion-keys-deselect-region' is nil, the region will remain active, augmented by the characters moved over by this motion key. @@ -2238,7 +2238,9 @@ If there is no line in the buffer after this one, behavior depends on the value of `next-line-add-newlines'. If non-nil, it inserts a newline character to create a line, and moves the cursor to that line. Otherwise it moves the -cursor to the end of the buffer. +cursor to the end of the buffer. If `signal-error-on-buffer-boundary' is +non-nil and you attempt to move past a buffer boundary, XEmacs will ring the +bell using `ding'. The command \\[set-goal-column] can be used to create a semipermanent goal column to which this command always moves. @@ -2286,6 +2288,9 @@ to invoke this command, and `shifted-motion-keys-select-region' is t; see the documentation for this variable for more details. +If `signal-error-on-buffer-boundary' is non-nil and you attempt to move past +a buffer boundary, XEmacs will ring the bell using `ding'. + If you are thinking of using this in a Lisp program, consider using `forward-line' with a negative argument instead. It is usually easier to use and more reliable (no dependence on goal column, etc.)." diff --text -u 'xemacs-21.5.18/lisp/startup.el' 'xemacs-21.5.19/lisp/startup.el' Index: ./lisp/startup.el --- ./lisp/startup.el Thu Sep 23 14:44:37 2004 +++ ./lisp/startup.el Wed Jan 26 13:56:18 2005 @@ -3,7 +3,7 @@ ;; Copyright (C) 1985-1986, 1990, 1992-1997 Free Software Foundation, Inc. ;; Copyright (c) 1993, 1994 Sun Microsystems, Inc. ;; Copyright (C) 1995 Board of Trustees, University of Illinois -;; Copyright (C) 2001, 2002, 2003 Ben Wing. +;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Ben Wing. ;; Maintainer: XEmacs Development Team ;; Keywords: internal, dumped @@ -72,7 +72,6 @@ (defvar command-line-processed nil "t once command line has been processed") (defconst startup-message-timeout 12000) ; More or less disable the timeout -(defconst splash-frame-timeout 7) ; interval between splash frame elements (defconst inhibit-startup-message nil "*Non-nil inhibits the initial startup message. @@ -129,7 +128,52 @@ (defconst initial-major-mode 'lisp-interaction-mode "Major mode command symbol to use for the initial *scratch* buffer.") + +;;; Path-related variables. +;;; NOTE: Many of them (`lisp-directory', `data-directory', etc.) are +;;; built-in. + +(defvar emacs-roots nil + "List of plausible roots of the XEmacs hierarchy. +This is a list of plausible directories in which to search for the important +directories used by XEmacs at run-time, for example `exec-directory', +`data-directory' and `lisp-directory'. + +Normally set at startup by calling `paths-find-emacs-roots'.") + +(defvar emacs-data-roots nil + "List of plausible data roots of the XEmacs hierarchy.") + +(defvar user-init-directory-base ".xemacs" + "Base of directory where user-installed init files may go.") + +(defvar user-init-directory + (file-name-as-directory + (paths-construct-path (list "~" user-init-directory-base))) + "Directory where user-installed init files may go.") + +(defvar user-init-file-base "init.el" + "Default name of the user init file if uncompiled. +This should be used for migration purposes only.") + +(defvar user-init-file-base-list '("init.el") + "List of allowed init files in the user's init directory. +The first one found takes precedence. .elc files do not need to be listed.") + +(defvar user-home-init-file-base-list + (append '(".emacs.el" ".emacs") + (and (eq system-type 'windows-nt) + '("_emacs.el" "_emacs"))) + "List of allowed init files in the user's home directory. +The first one found takes precedence. .elc files do not need to be listed.") + +(defvar load-home-init-file nil + "Non-nil if XEmacs should load the init file from the home directory. +Otherwise, XEmacs will offer migration to the init directory.") +(defvar load-user-init-file-p t + "Non-nil if XEmacs should load the user's init file.") + ;; #### called `site-run-file' in FSFmacs (defvar site-start-file "site-start" @@ -1014,7 +1058,7 @@ (when (string= (buffer-name) "*scratch*") (unless (or inhibit-startup-message (input-pending-p)) - (let (tmout circ-tmout) + (let (tmout) (unwind-protect ;; Guts of with-timeout (catch 'tmout @@ -1024,13 +1068,12 @@ (throw 'tmout t) (error nil))) nil)) - (setq circ-tmout (display-splash-frame)) + (display-splash-screen) (or nil;; (pos-visible-in-window-p (point-min)) (goto-char (point-min))) (sit-for 0) (setq unread-command-event (next-command-event))) - (when tmout (disable-timeout tmout)) - (when circ-tmout (disable-timeout circ-tmout))))) + (when tmout (disable-timeout tmout))))) (with-current-buffer (get-buffer "*scratch*") ;; In case the XEmacs server has already selected ;; another buffer, erase the one our message is in. @@ -1080,55 +1123,20 @@ (goto-line line) (setq line nil)))))))) -(defvar startup-presentation-hack-keymap - (let ((map (make-sparse-keymap))) - (set-keymap-name map 'startup-presentation-hack-keymap) - (define-key map '[button1] 'startup-presentation-hack) - (define-key map '[button2] 'startup-presentation-hack) - map) - "Putting yesterday in the future tomorrow.") - -(defun startup-presentation-hack () - (interactive) - (let ((e last-command-event)) - (and (button-press-event-p e) - (setq e (extent-at (event-point e) - (event-buffer e) - 'startup-presentation-hack)) - (setq e (extent-property e 'startup-presentation-hack)) - (if (consp e) - (apply (car e) (cdr e)) - (while (keymapp (indirect-function e)) - (let ((map e) - (overriding-local-map (indirect-function e))) - (setq e (read-key-sequence - (let ((p (keymap-prompt map t))) - (cond ((symbolp map) - (if p - (format "%s %s " map p) - (format "%s " map))) - (p) - (t - (prin1-to-string map)))))) - (if (and (button-release-event-p (elt e 0)) - (null (key-binding e))) - (setq e map) ; try again - (setq e (key-binding e))))) - (call-interactively e))))) - + (defun startup-presentation-hack-help (e) (setq e (extent-property e 'startup-presentation-hack)) - (if (consp e) - (format "Evaluate %S" e) - (symbol-name e))) - -(defun splash-frame-present-hack (e v) - ;; (set-extent-property e 'mouse-face 'highlight) - ;; (set-extent-property e 'keymap - ;; startup-presentation-hack-keymap) - ;; (set-extent-property e 'startup-presentation-hack v) - ;; (set-extent-property e 'help-echo - ;; 'startup-presentation-hack-help) + (symbol-name e)) + +(defun startup-presentation-activate (ev ex) + (call-interactively (extent-property ex 'startup-presentation-hack))) + +(defun splash-screen-present-hack (e v) +; (set-extent-property e 'mouse-face 'highlight) +; (set-extent-property e 'startup-presentation-hack v) +; (set-extent-property e 'help-echo +; 'startup-presentation-hack-help) +; (set-extent-property e 'activate-function 'startup-presentation-activate) ) (defun splash-hack-version-string () @@ -1148,35 +1156,34 @@ (when (search-forward "." nil t) (delete-region (1- (point)) (point-max)))))) -(defun splash-frame-present (l) +;; parse one page description (see `splash-screen-body') and display +;; at point. +(defun splash-screen-present (l) (cond ((stringp l) (insert l)) ((eq (car-safe l) 'face) ;; (face name string) (let ((p (point))) - (splash-frame-present (elt l 2)) - (if (fboundp 'set-extent-face) - (set-extent-face (make-extent p (point)) - (elt l 1))))) + (splash-screen-present (elt l 2)) + (set-extent-face (make-extent p (point)) + (elt l 1)))) ((eq (car-safe l) 'key) (let* ((c (elt l 1)) (p (point)) (k (where-is-internal c nil t))) (insert (if k (key-description k) (format "M-x %s" c))) - (if (fboundp 'set-extent-face) - (let ((e (make-extent p (point)))) - (set-extent-face e 'bold) - (splash-frame-present-hack e c))))) + (let ((e (make-extent p (point)))) + (set-extent-face e 'bold) + (splash-screen-present-hack e c)))) ((eq (car-safe l) 'funcall) ;; (funcall (fun . args) string) (let ((p (point))) - (splash-frame-present (elt l 2)) - (if (fboundp 'set-extent-face) - (splash-frame-present-hack (make-extent p (point)) - (elt l 1))))) + (splash-screen-present (elt l 2)) + (splash-screen-present-hack (make-extent p (point)) + (elt l 1)))) ((consp l) - (mapcar 'splash-frame-present l)) + (mapcar 'splash-screen-present l)) (t (error "WTF!?")))) @@ -1196,9 +1203,6 @@ (fill-area-width (* avg-pixwidth (- fill-column left-margin))) (glyph-pixwidth (cond ((stringp glyph) (* avg-pixwidth (length glyph))) - ;; #### the pixmap option should be removed - ;;((pixmapp glyph) - ;; (pixmap-width glyph)) ((glyphp glyph) (glyph-width glyph)) (t @@ -1206,10 +1210,49 @@ (+ left-margin (round (/ (/ (- fill-area-width glyph-pixwidth) 2) avg-pixwidth))))) -(defun splash-frame-body () - `[((face (blue bold underline) - "\nDistribution, copying license, warranty:\n\n") - "Please visit the XEmacs website at http://www.xemacs.org/ !\n\n" +;; the splash screen originated in 19.10 as splash-screen-*. When +;; Chuck made the global screen->frame change for 19.12, he +;; accidentally changed these too. This randomness is getting on my +;; nerves, so let's fix it and provide minimal aliases for the +;; `locale' mule package. --ben + +;; returns either of vector of page descriptions, each describing one +;; screenful of information, or just one such page descriptions Each +;; page description is a list of textual elements describing how to +;; display a section of text. The elements are processed in turn and +;; the results inserted one after the previous in a buffer. Each +;; textual element is either: + +;; -- a string, inserted as-is with no decoration. +;; -- a list of (face FACES "text"), where FACES is the name of a face +;; or a list of such names, and specifies the face(s) used when +;; displaying the text. +;; -- a list of (key COMMAND-NAME); the key sequence corresponding to +;; the command will be inserted, in boldface. +;; -- a list of textual elements. + +(defun splash-screen-window-body () + `( + (face (blue bold underline) + "Useful Help-menu entries:\n\n") + ,@(if (string-match "beta" emacs-version) + `((face bold "Beta Info:") + (face (red bold) + " This is an Experimental version of XEmacs.\n")) + `( "")) + (face bold "XEmacs FAQ:") + " Read the XEmacs FAQ.\n" + (face bold "Info (Online Docs):") + " Read the on-line documentation.\n" + (face bold "Tutorial:") + " XEmacs tutorial.\n" + (face bold "Samples->View Sample init.el:") + " A useful initialization file.\n" + (face bold "About XEmacs:") + " See who's developing XEmacs.\n" + "\n" + (face (bold blue) "XEmacs website:") + " http://www.xemacs.org/\n\n" ,@(if (featurep 'sparcworks) `( "\ Sun provides support for the WorkShop/XEmacs integration package only. @@ -1218,8 +1261,6 @@ (getenv "LANG")))) (if (and (not (featurep 'mule)) ;; Already got mule? - ;; No Mule support on tty's yet - (not (eq 'tty (console-type))) lang ;; Non-English locale? (not (string= lang "C")) (not (string-match "^en" lang)) @@ -1231,46 +1272,47 @@ XEmacs, by either running the command `xemacs-mule', or by using the X resource `ESERVE*defaultXEmacsPath: xemacs-mule' when starting XEmacs from Sun WorkShop. \n"))))) - ((key describe-no-warranty) - ": "(face (red bold) "XEmacs comes with ABSOLUTELY NO WARRANTY\n")) - ((key describe-copying) - ": conditions to give out copies of XEmacs\n") - ((key describe-distribution) - ": how to get the latest version\n") - "\n--\n" (face italic "\ Copyright (C) 1985-1999 Free Software Foundation, Inc. Copyright (C) 1990-1994 Lucid, Inc. Copyright (C) 1993-1997 Sun Microsystems, Inc. All Rights Reserved. -Copyright (C) 1994-1996 Board of Trustees, University of Illinois -Copyright (C) 1995-1996 Ben Wing\n")) - - ((face (blue bold underline) "\nInformation, on-line help:\n\n") - "XEmacs comes with plenty of documentation...\n\n" +Copyright (C) 1994-1996 Board of Trustees, University of Illinois. +Copyright (C) 1995-2005 Ben Wing.\n") + )) + +(defun splash-screen-tty-body () + `( + (face italic "[`C-' means the control key, `M-' means the meta key]\n\n") ,@(if (string-match "beta" emacs-version) `((key describe-beta) ": " (face (red bold) "This is an Experimental version of XEmacs.\n")) `( "\n")) ((key xemacs-local-faq) - ": read the XEmacs FAQ (a " (face underline "capital") " F!)\n") - ((key help-with-tutorial) - ": read the XEmacs tutorial (also available through the " - (face bold "Help") " menu)\n") + ": Read the XEmacs FAQ. (A " (face underline "capital") " F!)\n") + ((key info) ": Read the on-line documentation.\n") ((key help-command) - ": get help on using XEmacs (also available through the " - (face bold "Help") " menu)\n") - ((key info) ": read the on-line documentation\n\n") - ((key describe-project) ": read about the GNU project\n") - ((key about-xemacs) ": see who's developing XEmacs\n")) - - ((face (blue bold underline) "\nUseful stuff:\n\n") - "Things that you should learn rather quickly...\n\n" - ((key find-file) ": visit a file\n") - ((key save-buffer) ": save changes\n") - ((key undo) ": undo changes\n") - ((key save-buffers-kill-emacs) ": exit XEmacs\n")) - ]) + ": Get help on using XEmacs.\n") + ((key help-with-tutorial) + ": Read the XEmacs tutorial.\n") + ((key view-sample-init-el) + ": View the sample init.el file.\n") + ((key about-xemacs) ": See who's developing XEmacs.\n") + ((key save-buffers-kill-emacs) + ": exit XEmacs\n") + "\n" + (face (bold blue) "XEmacs website: ") + "http://www.xemacs.org/\n\n" + (face italic "\ +Copyright (C) 1985-1999 Free Software Foundation, Inc. +Copyright (C) 1990-1994 Lucid, Inc. +Copyright (C) 1993-1997 Sun Microsystems, Inc. All Rights Reserved. +Copyright (C) 1994-1996 Board of Trustees, University of Illinois. +Copyright (C) 1995-2004 Ben Wing.") +; ((key find-file) ": visit a file; ") +; ((key save-buffer) ": save changes; ") +; ((key undo) ": undo changes; ") + )) ;; I really hate global variables, oh well. ;(defvar xemacs-startup-logo-function nil @@ -1278,67 +1320,58 @@ ;This function should return an initialized glyph if it is used.") ;; This will hopefully go away when gettext is functional. -(defconst splash-frame-static-body - `(,(emacs-version) "\n\n" - (face italic "`C-' means the control key,`M-' means the meta key\n\n"))) - - -(defun circulate-splash-frame-elements (client-data) - (with-current-buffer (aref client-data 2) - (let ((buffer-read-only nil) - (elements (aref client-data 3)) - (indice (aref client-data 0))) - (goto-char (aref client-data 1)) - (delete-region (point) (point-max)) - (splash-frame-present (aref elements indice)) - (set-buffer-modified-p nil) - (aset client-data 0 - (if (= indice (- (length elements) 1)) - 0 - (1+ indice ))) - ))) - -;; #### This function now returns the (possibly nil) timeout circulating the -;; splash-frame elements -(defun display-splash-frame () +(defconst splash-screen-static-body + `(,(emacs-version) "\n\n")) +;; temporary support for old locale files. +(define-obsolete-variable-alias 'splash-frame-static-body + 'splash-screen-static-body) + +(defun display-splash-screen () + ;; display the splash screen in the current buffer and put it in the + ;; current window. (let ((logo xemacs-logo) (buffer-read-only nil) - (cramped-p (eq 'tty (console-type)))) - (unless cramped-p (insert "\n")) - (indent-to (startup-center-spaces logo)) - (set-extent-begin-glyph (make-extent (point) (point)) logo) - ;;(splash-frame-present-hack (make-extent p (point)) 'about-xemacs)) - (insert "\n\n") - (splash-frame-present splash-frame-static-body) + (tty (eq 'tty (console-type)))) + (unless tty + (insert "\n") + (indent-to (startup-center-spaces logo)) + (set-extent-begin-glyph (make-extent (point) (point)) logo) + ;;(splash-screen-present-hack (make-extent p (point)) 'about-xemacs)) + (insert "\n\n")) + (splash-screen-present splash-screen-static-body) (splash-hack-version-string) (goto-char (point-max)) (let* ((after-change-functions nil) ; no font-lock, thank you - (elements (splash-frame-body)) - (client-data `[ 1 ,(point) ,(current-buffer) ,elements ]) - tmout) - (if (listp elements) ;; A single element to display - (splash-frame-present (splash-frame-body)) - ;; several elements to rotate - (splash-frame-present (aref elements 0)) - (setq tmout (add-timeout splash-frame-timeout - 'circulate-splash-frame-elements - client-data splash-frame-timeout))) - (set-buffer-modified-p nil) - tmout))) + (elements (cond (tty (splash-screen-tty-body)) + (t (splash-screen-window-body))))) + (pop-to-buffer (current-buffer)) + (delete-other-windows) + (splash-screen-present elements) + (set-buffer-modified-p nil)))) + +(defun xemacs-splash-buffer () + "Display XEmacs splash screen in a buffer." + (interactive) + (let ((buffer (get-buffer-create "*Splash*"))) + (set-buffer buffer) + (setq buffer-read-only nil) + (erase-buffer buffer) + (display-splash-screen))) ;; (let ((present-file ;; #'(lambda (f) -;; (splash-frame-present +;; (splash-screen-present ;; (list 'funcall ;; (list 'find-file-other-window ;; (expand-file-name f data-directory)) ;; f))))) ;; (insert "For customization examples, see the files ") -;; (funcall present-file "sample.emacs") +;; (funcall present-file "sample.init.el") ;; (insert " and ") ;; (funcall present-file "sample.Xresources") ;; (insert (format "\nin the directory %s." data-directory))) + (defun startup-set-invocation-environment () ;; XEmacs -- Steven Baur says invocation directory is nil if you ;; try to use XEmacs as a login shell. @@ -1347,6 +1380,219 @@ ;; don't let /tmp_mnt/... get into the load-path or exec-path. (abbreviate-file-name invocation-directory))) +;;; High-level functions to set up the paths. + +(defun startup-find-load-path (&optional inhibit-packages + set-global-package-paths) + "Determine the value for `load-path'. +INHIBIT-PACKAGES says which types of packages, if any, to omit from the +returned value. It can be `t' (omit all), one of the symbols `early', +`late', or `last', or a list of one or more of the symbols. + +If SET-GLOBAL-PACKAGE-PATHS is non-nil, initialize the global package path +variables referring to the particular types of packages +(`early-package-hierarchies', `early-package-load-path', +`late-package-hierarchies', `late-package-load-path', +`last-package-hierarchies', `last-package-load-path')." + (let (earlyp latep lastp earlyp-lp latep-lp lastp-lp) + (apply #'(lambda (early late last) + (setq earlyp (and (not (memq 'early inhibit-packages)) early)) + (setq latep (and (not (memq 'late inhibit-packages)) late)) + (setq lastp (and (not (memq 'last inhibit-packages)) last))) + (packages-find-all-package-hierarchies + emacs-data-roots)) + + (setq earlyp-lp (packages-find-package-load-path earlyp)) + (setq latep-lp (packages-find-package-load-path latep)) + (setq lastp-lp (packages-find-package-load-path lastp)) + + (when set-global-package-paths + (setq early-package-hierarchies earlyp + late-package-hierarchies latep + last-package-hierarchies lastp + early-package-load-path earlyp-lp + late-package-load-path latep-lp + last-package-load-path lastp-lp)) + + (paths-construct-load-path emacs-roots earlyp-lp latep-lp lastp-lp + lisp-directory site-directory + mule-lisp-directory))) + +(defun startup-setup-paths (&optional inhibit-packages called-early) + "Setup all the various paths. +INHIBIT-PACKAGES says which types of packages, if any, to omit from the +returned value. It can be `t' (omit all), one of the symbols `early', +`late', or `last', or a list of one or more of the symbols. + +This function is idempotent, so call this as often as you like!" + + (setq debug-paths (or debug-paths + (and (getenv "EMACSDEBUGPATHS") + t))) + + (setq emacs-roots (paths-find-emacs-roots invocation-directory invocation-name + #'paths-emacs-data-root-p)) + + (setq emacs-data-roots (paths-find-emacs-roots invocation-directory invocation-name + #'paths-emacs-data-root-p)) + + (if (null emacs-roots) + (save-excursion + (set-buffer (get-buffer-create " *warning-tmp*")) + (erase-buffer) + (buffer-disable-undo (current-buffer)) + + (insert "Couldn't find an obvious default for the root of the\n" + "XEmacs hierarchy.") + + (princ "\nWARNING:\n" 'external-debugging-output) + (princ (buffer-string) 'external-debugging-output))) + + (if (eq inhibit-packages t) + (setq inhibit-packages '(early late last))) + (if (not (listp inhibit-packages)) + (setq inhibit-packages (list inhibit-packages))) + + (when debug-paths + (princ (format +"startup-setup-paths arguments: + inhibit-packages: %S + inhibit-site-lisp: %S + called-early: %S +" inhibit-packages inhibit-site-lisp called-early) + 'external-debugging-output) + (princ (format +"emacs-roots: +%S +emacs-data-roots: +%S +user-init-directory: %S +configure-package-path: %S +" emacs-roots emacs-data-roots user-init-directory configure-package-path) + 'external-debugging-output) + ) + + (setq lisp-directory (paths-find-lisp-directory emacs-roots)) + + (if debug-paths + (princ (format "lisp-directory:\n%S\n" lisp-directory) + 'external-debugging-output)) + + (if (featurep 'mule) + (progn + (setq mule-lisp-directory + (paths-find-mule-lisp-directory emacs-roots + lisp-directory)) + (if debug-paths + (princ (format "mule-lisp-directory:\n%S\n" + mule-lisp-directory) + 'external-debugging-output))) + (setq mule-lisp-directory '())) + + (setq site-directory (and (null inhibit-site-lisp) + (paths-find-site-lisp-directory emacs-roots))) + + (if (and debug-paths (null inhibit-site-lisp)) + (princ (format "site-directory:\n%S\n" site-directory) + 'external-debugging-output)) + + (setq load-path (startup-find-load-path inhibit-packages t)) + + (when debug-paths + (princ (format "early-package-hierarchies and early-package-load-path:\n%S\n%S\n" + early-package-hierarchies early-package-load-path) + 'external-debugging-output) + (princ (format "late-package-hierarchies and late-package-load-path:\n%S\n%S\n" + late-package-hierarchies late-package-load-path) + 'external-debugging-output) + (princ (format "last-package-hierarchies and last-package-load-path:\n%S\n%S\n" + last-package-hierarchies last-package-load-path) + 'external-debugging-output)) + + (if debug-paths + (princ (format "load-path:\n%S\n" load-path) + 'external-debugging-output)) + (setq module-directory (paths-find-module-directory emacs-roots)) + (if debug-paths + (princ (format "module-directory:\n%S\n" module-directory) + 'external-debugging-output)) + (setq site-module-directory (and (null inhibit-site-modules) + (paths-find-site-module-directory + emacs-roots))) + (if (and debug-paths (null inhibit-site-modules)) + (princ (format "site-module-directory:\n%S\n" + site-module-directory) + 'external-debugging-output)) + + (setq module-load-path (paths-construct-module-load-path + emacs-roots + module-directory + site-module-directory)) + + (unless called-early + (setq Info-directory-list + (paths-construct-info-path + emacs-roots + early-package-hierarchies late-package-hierarchies last-package-hierarchies)) + + (if debug-paths + (princ (format "Info-directory-list:\n%S\n" Info-directory-list) + 'external-debugging-output)) + + (setq exec-directory (paths-find-exec-directory emacs-roots)) + + (if debug-paths + (princ (format "exec-directory:\n%s\n" exec-directory) + 'external-debugging-output)) + + (setq exec-path + (paths-construct-exec-path emacs-roots exec-directory + early-package-hierarchies late-package-hierarchies + last-package-hierarchies)) + + (if debug-paths + (princ (format "exec-path:\n%S\n" exec-path) + 'external-debugging-output)) + + (setq doc-directory (paths-find-doc-directory emacs-roots)) + + (if debug-paths + (princ (format "doc-directory:\n%S\n" doc-directory) + 'external-debugging-output)) + + (setq data-directory (paths-find-data-directory emacs-roots)) + + (if debug-paths + (princ (format "data-directory:\n%S\n" data-directory) + 'external-debugging-output)) + + (setq data-directory-list (paths-construct-data-directory-list + data-directory early-package-hierarchies + late-package-hierarchies last-package-hierarchies)) + (if debug-paths + (princ (format "data-directory-list:\n%S\n" data-directory-list) + 'external-debugging-output)))) + +(defun startup-find-load-path-for-packages (packages) + "Return a suitable load-path for PACKAGES. +PACKAGES is a list of package names (strings). This looks for package +directories in the load path whose last component is one of the members of +PACKAGES." + (mapcan + #'(lambda (package) + (and (member (file-name-nondirectory (directory-file-name package)) + packages) + (list package))) + (startup-find-load-path))) + +; (defun startup-set-basic-packages-load-path () +; "#### This is a hack. When recompiling .el files, we use -no-packages +; to avoid problems with packages shadowing standard Lisp files +; (e.g. unicode.el), but we really still need the stuff in xemacs-base and +; xemacs-devel." +; (setq load-path (startup-find-load-path-for-packages +; '("xemacs-base" "xemacs-devel")))) + (defun startup-setup-paths-warning () (let ((warnings '())) (cond @@ -1379,6 +1625,14 @@ (erase-buffer) t))))) + +;;; Now actually set the paths up, for bootstrapping purposes. This is run +;;; at early dump time and in certain cases where we use a minimal temacs +;;; to do useful things, like rebuild DOC. + +(startup-setup-paths (if inhibit-all-packages t '(early last)) t) + + (defun startup-load-autoloads () (when (and (not inhibit-autoloads) lisp-directory) (load (expand-file-name (file-name-sans-extension autoload-file-name) diff --text -u 'xemacs-21.5.18/lisp/subr.el' 'xemacs-21.5.19/lisp/subr.el' Index: ./lisp/subr.el --- ./lisp/subr.el Thu Jun 17 20:29:39 2004 +++ ./lisp/subr.el Fri Jan 28 11:05:05 2005 @@ -1,12 +1,13 @@ ;;; subr.el --- basic lisp subroutines for XEmacs -;; Copyright (C) 1985, 1986, 1992, 1994-5, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1985, 86, 92, 94, 95, 99, 2000, 2001, 2002, 2003 +;; Free Software Foundation, Inc. ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. ;; Copyright (C) 1995 Sun Microsystems. ;; Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. ;; Maintainer: XEmacs Development Team -;; Keywords: extensions, dumped +;; Keywords: extensions, dumped, internal ;; This file is part of XEmacs. @@ -48,6 +49,24 @@ (defun custom-declare-variable-early (&rest arguments) (setq custom-declare-variable-list (cons arguments custom-declare-variable-list))) + + +(defun macro-declaration-function (macro decl) + "Process a declaration found in a macro definition. +This is set as the value of the variable `macro-declaration-function'. +MACRO is the name of the macro being defined. +DECL is a list `(declare ...)' containing the declarations. +The return value of this function is not used." + (dolist (d (cdr decl)) + (cond ((and (consp d) (eq (car d) 'indent)) + (put macro 'lisp-indent-function (cadr d))) + ((and (consp d) (eq (car d) 'debug)) + (put macro 'edebug-form-spec (cadr d))) + (t + (message "Unknown declaration %s" d))))) + +(setq macro-declaration-function 'macro-declaration-function) + ;;;; Lisp language features. @@ -1601,4 +1620,32 @@ ;; END SYNC WITH FSF 21.2 +;; (defun shell-quote-argument (argument) in process.el. + +;; (defun make-syntax-table (&optional oldtable) in syntax.el. + +;; (defun syntax-after (pos) #### doesn't exist. + +;; global-set-key, local-set-key, global-unset-key, local-unset-key in +;; keymap.el. + +;; frame-configuration-p is in frame.el. + +;; functionp is built-in. + +;; interactive-form in obsolete.el. + +;; assq-del-all in obsolete.el. + +;; (defun make-temp-file (prefix &optional dir-flag suffix) #### doesn't exist. + +;; add-minor-mode in modeline.el. + +;; text-clone stuff #### doesn't exist; should go in text-props.el and +;; requires changes to extents.c (modification hooks). + +;; play-sound is built-in. + +;; define-mail-user-agent is in simple.el. + ;;; subr.el ends here diff --text -u 'xemacs-21.5.18/lisp/unicode.el' 'xemacs-21.5.19/lisp/unicode.el' Index: ./lisp/unicode.el --- ./lisp/unicode.el Wed Sep 22 11:05:51 2004 +++ ./lisp/unicode.el Thu Feb 10 00:29:07 2005 @@ -77,6 +77,11 @@ ; )) +;; accessed in loadup.el, mule-cmds.el; see discussion in unicode.c +(defvar load-unicode-tables-at-dump-time (eq system-type 'windows-nt) + "[INTERNAL] Whether to load the Unicode tables at dump time. +Setting this at run-time does nothing.") + ;; NOTE: This takes only a fraction of a second on my Pentium III ;; 700Mhz even with a totally optimization-disabled XEmacs. (defun load-unicode-tables () @@ -96,6 +101,7 @@ ;; "8859-13.TXT" ("8859-14.TXT" latin-iso8859-14 #xA0 #xFF #x-80) ("8859-15.TXT" latin-iso8859-15 #xA0 #xFF #x-80) + ("8859-16.TXT" latin-iso8859-16 #xA0 #xFF #x-80) ("8859-2.TXT" latin-iso8859-2 #xA0 #xFF #x-80) ("8859-3.TXT" latin-iso8859-3 #xA0 #xFF #x-80) ("8859-4.TXT" latin-iso8859-4 #xA0 #xFF #x-80) @@ -173,9 +179,6 @@ (cdr tables)))) parse-args))) -(defun init-unicode-at-startup () - (load-unicode-tables)) - (make-coding-system 'utf-16 'unicode "UTF-16" @@ -190,6 +193,8 @@ for private, corporate or internal use." type utf-16)) +(define-coding-system-alias 'utf-16-be 'utf-16) + (make-coding-system 'utf-16-bom 'unicode "UTF-16 w/BOM" @@ -227,6 +232,8 @@ type utf-16 little-endian t)) +(define-coding-system-alias 'utf-16-le 'utf-16-little-endian) + (make-coding-system 'utf-16-little-endian-bom 'unicode "UTF-16 Little Endian w/BOM" diff --text -u 'xemacs-21.5.18/lisp/update-elc-2.el' 'xemacs-21.5.19/lisp/update-elc-2.el' Index: ./lisp/update-elc-2.el --- ./lisp/update-elc-2.el Sat Mar 1 16:25:27 2003 +++ ./lisp/update-elc-2.el Thu Feb 3 16:11:20 2005 @@ -149,32 +149,25 @@ ;; way is slow, so we avoid it when possible. (when (file-exists-p (expand-file-name "REBUILD_AUTOLOADS" invocation-directory)) - (let ((generated-autoload-file (expand-file-name "auto-autoloads.el" dir)) - (autoload-package-name "auto")) ; feature prefix - ;; if we were instructed to rebuild the autoloads, force the file - ;; to be touched even w/o changes; otherwise, we won't ever stop - ;; being told to rebuild them. - (update-autoload-files (list dir) nil t) - (byte-recompile-file generated-autoload-file 0)) + ;; if we were instructed to rebuild the autoloads, force the file + ;; to be touched even w/o changes; otherwise, we won't ever stop + ;; being told to rebuild them. + (update-autoload-files dir "auto" nil t) + (byte-recompile-file (expand-file-name "auto-autoloads.el" dir) 0) (when (featurep 'mule) - (let* ((muledir (expand-file-name "../lisp/mule" (file-truename dir))) - (generated-autoload-file - (expand-file-name "auto-autoloads.el" muledir)) - (autoload-package-name "mule")) ; feature prefix + (let ((muledir (expand-file-name "../lisp/mule" (file-truename dir)))) ;; force here just like above. - (update-autoload-files (list muledir) nil t) - (byte-recompile-file generated-autoload-file 0)))) + (update-autoload-files muledir "mule" nil t) + (byte-recompile-file (expand-file-name "auto-autoloads.el" dir) 0)))) (when (featurep 'modules) (let* ((moddir (expand-file-name "../modules" (file-truename dir))) - (generated-autoload-file - (expand-file-name "auto-autoloads.el" moddir)) - (autoload-package-name "modules")) ; feature prefix - (update-autoload-files + (autofile (expand-file-name "auto-autoloads.el" moddir))) + (update-autoload-files (delete (concat (file-name-as-directory moddir) ".") (delete (concat (file-name-as-directory moddir) "..") (directory-files moddir t nil nil 0))) - t) - (byte-recompile-file generated-autoload-file 0))) + "modules" autofile) + (byte-recompile-file autofile 0))) ;; now load the (perhaps newly rebuilt) autoloads; we were called with ;; -no-autoloads so they're not already loaded. (load (expand-file-name "auto-autoloads" lisp-directory)) diff --text -u 'xemacs-21.5.18/lisp/update-elc.el' 'xemacs-21.5.19/lisp/update-elc.el' Index: ./lisp/update-elc.el --- ./lisp/update-elc.el Sat Mar 1 16:25:27 2003 +++ ./lisp/update-elc.el Thu Feb 3 16:11:20 2005 @@ -106,7 +106,7 @@ ;; early byte compilation. These are files loaded by update-elc.el in ;; order to do the compilation of all the rest of the files. (defvar lisp-files-needing-early-byte-compilation - '(;"easy-mmode" + '("easy-mmode" "autoload" "shadow" "cl-macs")) @@ -117,7 +117,15 @@ "dumped-pkg-lisp.el" "raw-process.el" "version.el") - "Lisp files that should not be byte compiled.") + "Lisp files that should not be byte compiled. +Files in `additional-dump-dependencies' do not need to be listed here.") + +(defvar additional-dump-dependencies + '("loadup.el" + "loadup-el.el" + "update-elc.el") + "Lisp files that are not dumped but which the dump depends on. +If any of these files are changed, we need to redump.") (defvar lisp-files-ignored-when-checking-for-autoload-updating '("custom-load.el" @@ -187,10 +195,13 @@ ;; in the lisp-files-need* variables. (setq files-to-process (append lisp-files-needed-for-byte-compilation lisp-files-needing-early-byte-compilation + additional-dump-dependencies preloaded-file-list)) (while files-to-process (let* ((arg (car files-to-process)) - (arg-is-preloaded (member arg preloaded-file-list)) + (arg-is-dump-dependency + (or (member arg preloaded-file-list) + (member arg additional-dump-dependencies))) (arg-sans-extension (update-elc-chop-extension arg)) (full-arg (locate-library arg-sans-extension)) (full-arg-sans-extension @@ -199,7 +210,7 @@ (print (format "Error: Library file %s not found" arg)) (backtrace) ;; Uncomment in case of trouble - ;;(print (format "late-packages: %S" late-packages)) + ;;(print (format "late-package-hierarchies: %S" late-package-hierarchies)) ;;(print (format "guessed-roots: %S" ;; (paths-find-emacs-roots ;; invocation-directory invocation-name))) @@ -209,11 +220,11 @@ (full-arg-elc (concat full-arg-sans-extension ".elc")) (full-arg-dir (file-name-directory full-arg-el))) - ;; (print full-arg-el) + ; (print full-arg-el) ;; now check if .el or .elc is newer than the dumped exe. ;; if so, need to redump. - (when (and dump-target arg-is-preloaded + (when (and dump-target arg-is-dump-dependency ;; no need to check for existence of either of the files ;; because of the definition of file-newer-than-file-p. (or (file-newer-than-file-p full-arg-el dump-target) @@ -222,6 +233,8 @@ (if (and (not (member (file-name-nondirectory arg) unbytecompiled-lisp-files)) + (not (member (file-name-nondirectory arg) + additional-dump-dependencies)) (not (member full-arg-el processed)) ;; no need to check for existence of either of the files ;; because of the definition of file-newer-than-file-p. @@ -299,10 +312,10 @@ need-to-rebuild-mule-autoloads) (list "-l" "autoload")) (if need-to-rebuild-autoloads - (list "-f" "autoload-update-directory-autoloads" + (list "-f" "batch-update-directory-autoloads" "auto" source-lisp)) (if need-to-rebuild-mule-autoloads - (list "-f" "autoload-update-directory-autoloads" + (list "-f" "batch-update-directory-autoloads" "mule" source-lisp-mule)) (if need-to-recompile-autoloads (list "-f" "batch-byte-compile-one-file" diff --text -u 'xemacs-21.5.18/lisp/wid-edit.el' 'xemacs-21.5.19/lisp/wid-edit.el' Index: ./lisp/wid-edit.el --- ./lisp/wid-edit.el Thu Jan 22 11:50:26 2004 +++ ./lisp/wid-edit.el Fri Nov 5 08:05:56 2004 @@ -2131,7 +2131,7 @@ (defun widget-url-link-action (widget &optional event) "Open the url specified by WIDGET." - (if (fboundp 'browse-url) + (if-fboundp 'browse-url (browse-url (widget-value widget)) (error 'missing-package "Cannot browse URLs in this XEmacs" 'browse-url))) diff --text -u 'xemacs-21.5.18/lisp/widgets-gtk.el' 'xemacs-21.5.19/lisp/widgets-gtk.el' Index: ./lisp/widgets-gtk.el --- ./lisp/widgets-gtk.el Wed Jul 7 21:00:59 2004 +++ ./lisp/widgets-gtk.el Fri Nov 5 08:05:56 2004 @@ -89,7 +89,8 @@ (defun gtk-widget-instantiate-notebook-internal (plist instance) (let ((widget (gtk-notebook-new)) - (items (plist-get plist :items))) + ;(items (plist-get plist :items)) + ) ; (while items ; (gtk-notebook-append-page widget ; (gtk-vbox-new nil 3) diff --text -u 'xemacs-21.5.18/lisp/win32-native.el' 'xemacs-21.5.19/lisp/win32-native.el' Index: ./lisp/win32-native.el --- ./lisp/win32-native.el Fri Sep 19 18:50:08 2003 +++ ./lisp/win32-native.el Fri Nov 5 08:05:56 2004 @@ -1,7 +1,7 @@ ;;; win32-native.el --- Lisp routines when running on native MS Windows. ;; Copyright (C) 1994 Free Software Foundation, Inc. -;; Copyright (C) 2000 Ben Wing. +;; Copyright (C) 2000, 2004 Ben Wing. ;; Maintainer: XEmacs Development Team ;; Keywords: mouse, dumped @@ -81,9 +81,125 @@ (if (mswindows-system-shell-p shell-file-name) (setq shell-command-switch "/c"))) -;;---------------------------------------------------------------------- -;; Quoting process args -;;-------------------- +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Quoting process args ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Converting a bunch of args into a single command line or vice-versa is +;; extremely hairy due to the quoting conventions needed. There is in fact +;; code that does this in the CRT, and perhaps we should look at it and +;; follow the logic. + +;; Here is some further info from MSDN, discovered *AFTER* the actual code +;; below was written, and hence the code may not follow what it should. +;; !!#### But this is definitely something to be fixed up. The article is +;; called "Parsing C++ Command-Line Arguments", Visual Tools and Langs -> +;; Visual Studio -> Visual C++ -> Reference -> C/C++ Lang and ... -> C++ +;; Lang Ref -> Basic Concepts -> Startup and Termination -> Program +;; Startup: the main Function. + +;; Microsoft Specific +;; +;; Microsoft C/C++ startup code uses the following rules when interpreting +;; arguments given on the operating system command line: +;; +;; Arguments are delimited by white space, which is either a space or a tab. +;; +;; The caret character (^) is not recognized as an escape character or +;; delimiter. The character is handled completely by the command-line parser +;; in the operating system before being passed to the argv array in the +;; program. +;; +;; A string surrounded by double quotation marks ("string") is interpreted as +;; a single argument, regardless of white space contained within. A quoted +;; string can be embedded in an argument. +;; +;; A double quotation mark preceded by a backslash ( \") is interpreted as a +;; literal double quotation mark character ("). +;; +;; Backslashes are interpreted literally, unless they immediately precede a +;; double quotation mark. +;; +;; If an even number of backslashes is followed by a double quotation mark, +;; one backslash is placed in the argv array for every pair of backslashes, +;; and the double quotation mark is interpreted as a string delimiter. +;; +;; If an odd number of backslashes is followed by a double quotation mark, one +;; backslash is placed in the argv array for every pair of backslashes, and +;; the double quotation mark is "escaped" by the remaining backslash, +;; causing a literal double quotation mark (") to be placed in argv. +;; +;; The following program demonstrates how command-line arguments are passed: +;; +;; include <iostream.h> +;; +;; void main( int argc, // Number of strings in array argv +;; char *argv[], // Array of command-line argument strings +;; char *envp[] ) // Array of environment variable strings +;; { +;; int count; +;; +;; // Display each command-line argument. +;; cout << "\nCommand-line arguments:\n"; +;; for( count = 0; count < argc; count++ ) +;; cout << " argv[" << count << "] " +;; << argv[count] << "\n"; +;; } +;; +;; Table 2.2 shows example input and expected output, demonstrating the rules +;; in the preceding list. +;; +;; Table 2.2 +;; +;; Command-Line Input argv[1] argv[2] argv[3] +;; ------------------------------------------ +;; "abc" d e abc d e +;; +;; a\\\b d"e f"g h a\\\b de fg h +;; +;; a\\\"b c d a\"b c d +;; +;; a\\\\"b c" d e a\\b c d e +;; +;; END Microsoft Specific +;; +;; note: for pulling apart an arg: +;; each arg consists of either + +;; something surrounded by single quotes + +;; or + +;; one or more of + +;; 1. a non-ws, non-" char +;; 2. a section of double-quoted text +;; 3. a section of double-quoted text with end-of-string instead of the final +;; quote. + +;; 2 and 3 get handled together. + +;; quoted text is one of +;; +;; 1. quote + even number of backslashes + quote, or +;; 2. quote + non-greedy anything + non-backslash + even number of +;; backslashes + quote. + +;; we need to separate the two because we unfortunately have no non-greedy +;; ? operator. (urk! we actually do, but it wasn't documented.) --ben + +;; if you want to mess around, keep this test case in mind: + +;; this string + +;; " as'f 'FOO BAR' '' \"\" \"asdf \\ \\\" \\\\\\\" asdfasdf\\\\\" foo\" " + +;; should tokenize into this: + +;; (" " "as'f" " " "'FOO BAR' " "'' " "\"\"" " " "\"asdf \\ \\\" \\\\\\\" asdfasdf\\\\\"" " " "foo" "\" ") + (defvar debug-mswindows-process-command-lines nil "If non-nil, output debug information about the command lines constructed. @@ -131,41 +247,6 @@ (defun mswindows-construct-vc-runtime-command-line (program args) (mapconcat #'mswindows-quote-one-vc-runtime-arg args " ")) -;; note: for pulling apart an arg: -;; each arg consists of either - -;; something surrounded by single quotes - -;; or - -;; one or more of - -;; 1. a non-ws, non-" char -;; 2. a section of double-quoted text -;; 3. a section of double-quoted text with end-of-string instead of the final -;; quote. - -;; 2 and 3 get handled together. - -;; quoted text is one of -;; -;; 1. quote + even number of backslashes + quote, or -;; 2. quote + non-greedy anything + non-backslash + even number of -;; backslashes + quote. - -;; we need to separate the two because we unfortunately have no non-greedy -;; ? operator. (urk! we actually do, but it wasn't documented.) --ben - -;; if you want to mess around, keep this test case in mind: - -;; this string - -;; " as'f 'FOO BAR' '' \"\" \"asdf \\ \\\" \\\\\\\" asdfasdf\\\\\" foo\" " - -;; should tokenize into this: - -;; (" " "as'f" " " "'FOO BAR' " "'' " "\"\"" " " "\"asdf \\ \\\" \\\\\\\" asdfasdf\\\\\"" " " "foo" "\" ") - ;; this regexp actually separates the arg into individual args, like a ;; shell (such as sh) does, but using vc-runtime rules. it's easy to ;; derive the tokenizing regexp from it, and that's exactly what i did. diff --text -u 'xemacs-21.5.18/lisp/window-xemacs.el' 'xemacs-21.5.19/lisp/window-xemacs.el' Index: ./lisp/window-xemacs.el --- ./lisp/window-xemacs.el Sun Aug 22 02:05:51 2004 +++ ./lisp/window-xemacs.el Wed Feb 16 20:07:30 2005 @@ -701,6 +701,10 @@ If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER. +If the buffer name is a member of the `same-window-buffer-names' list, +or matches one of the `same-window-regexps' expressions, display the +buffer in the currently selected window. + Returns the window displaying BUFFER." (interactive "BDisplay buffer:\nP") diff --text -u 'xemacs-21.5.18/lisp/x-faces.el' 'xemacs-21.5.19/lisp/x-faces.el' Index: ./lisp/x-faces.el --- ./lisp/x-faces.el Fri Jun 21 06:18:04 2002 +++ ./lisp/x-faces.el Fri Jan 28 11:58:41 2005 @@ -1,7 +1,7 @@ ;;; x-faces.el --- X-specific face frobnication, aka black magic. ;; Copyright (C) 1992-4, 1997 Free Software Foundation, Inc. -;; Copyright (C) 1995, 1996, 2002 Ben Wing. +;; Copyright (C) 1995, 1996, 2002, 2004 Ben Wing. ;; Author: Jamie Zawinski <jwz@jwz.org> ;; Maintainer: XEmacs Development Team @@ -284,7 +284,7 @@ (string-to-int (substring name (match-beginning 6) (match-end 6))) name)))) - (list-fonts font device))) + (font-list font device))) (function (lambda (x y) (if (= (nth 1 x) (nth 1 y)) (< (nth 0 x) (nth 0 y)) (< (nth 1 x) (nth 1 y))))))) @@ -376,6 +376,71 @@ (make-obsolete 'x-make-face-unitalic 'make-face-unitalic) + +;; #### - wrong place for this variable? Exactly. We probably want +;; `color-list' to be a console method, so `tty-color-list' becomes +;; obsolete, and `read-color-completion-table' conses (mapcar #'list +;; (color-list)), optionally caching the results. + +;; Ben wanted all of the possibilities from the `configure' script used +;; here, but I think this is way too many. I already trimmed the R4 variants +;; and a few obvious losers from the list. --Stig +(defvar x-library-search-path '("/usr/X11R6/lib/X11/" + "/usr/X11R5/lib/X11/" + "/usr/lib/X11R6/X11/" + "/usr/lib/X11R5/X11/" + "/usr/local/X11R6/lib/X11/" + "/usr/local/X11R5/lib/X11/" + "/usr/local/lib/X11R6/X11/" + "/usr/local/lib/X11R5/X11/" + "/usr/X11/lib/X11/" + "/usr/lib/X11/" + "/usr/local/lib/X11/" + "/usr/X386/lib/X11/" + "/usr/x386/lib/X11/" + "/usr/XFree86/lib/X11/" + "/usr/unsupported/lib/X11/" + "/usr/athena/lib/X11/" + "/usr/local/x11r5/lib/X11/" + "/usr/lpp/Xamples/lib/X11/" + "/usr/openwin/lib/X11/" + "/usr/openwin/share/lib/X11/") + "Search path used by `x-color-list-internal' to find rgb.txt.") + +(defvar x-color-list-internal-cache) + +(defun x-color-list-internal () + (if (boundp 'x-color-list-internal-cache) + x-color-list-internal-cache + (let ((rgb-file (locate-file "rgb.txt" x-library-search-path)) + clist color p) + (if (not rgb-file) + ;; prevents multiple searches for rgb.txt if we can't find it + (setq x-color-list-internal-cache nil) + (with-current-buffer (get-buffer-create " *colors*") + (reset-buffer (current-buffer)) + (insert-file-contents rgb-file) + (while (not (eobp)) + ;; skip over comments + (while (looking-at "^!") + (end-of-line) + (forward-char 1)) + (skip-chars-forward "0-9 \t") + (setq p (point)) + (end-of-line) + (setq color (buffer-substring p (point)) + clist (cons (list color) clist)) + ;; Ugh. If we want to be able to complete the lowercase form + ;; of the color name, we need to add it twice! Yuck. + (let ((dcase (downcase color))) + (or (string= dcase color) + (push (list dcase) clist))) + (forward-char 1)) + (kill-buffer (current-buffer)))) + (setq x-color-list-internal-cache clist) + x-color-list-internal-cache))) + + ;;; internal routines ;;; x-init-face-from-resources is responsible for initializing a diff --text -u 'xemacs-21.5.18/lisp/x-font-menu.el' 'xemacs-21.5.19/lisp/x-font-menu.el' Index: ./lisp/x-font-menu.el --- ./lisp/x-font-menu.el Wed Sep 22 11:05:51 2004 +++ ./lisp/x-font-menu.el Fri Jan 28 11:58:41 2005 @@ -90,7 +90,7 @@ or if you change your font path, you can call this to re-initialize the menus." ;; by Stig@hackvan.com ;; #### - this should implement a `menus-only' option, which would - ;; recalculate the menus from the cache w/o having to do list-fonts again. + ;; recalculate the menus from the cache w/o having to do font-list again. (unless x-font-regexp-ascii (setq x-font-regexp-ascii (if (featurep 'mule) (charset-registry 'ascii) @@ -101,7 +101,7 @@ family size weight entry monospaced-p dev-cache cache families sizes weights) (dolist (name (cond ((null debug) ; debugging kludge - (list-fonts "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device + (font-list "*-*-*-*-*-*-*-*-*-*-*-*-*-*" device font-menu-max-number)) ((stringp debug) (split-string debug "\n")) (t debug))) diff --text -u 'xemacs-21.5.18/lwlib/ChangeLog' 'xemacs-21.5.19/lwlib/ChangeLog' Index: ./lwlib/ChangeLog --- ./lwlib/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./lwlib/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,7 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/man/ChangeLog' 'xemacs-21.5.19/man/ChangeLog' Index: ./man/ChangeLog --- ./man/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./man/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,1461 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * xemacs-faq.texi: + * xemacs-faq.texi (Top): + * xemacs-faq.texi (Introduction): + * xemacs-faq.texi (Q1.2.2): + * xemacs-faq.texi (Q1.2.5): + * xemacs-faq.texi (Q1.2.9): + * xemacs-faq.texi (Q1.2.10): + * xemacs-faq.texi (Q1.2.11): + * xemacs-faq.texi (Q1.2.12): + * xemacs-faq.texi (Q1.4.2): + * xemacs-faq.texi (Q1.5.2): + * xemacs-faq.texi (Q1.5.3): + * xemacs-faq.texi (Q1.5.4): + * xemacs-faq.texi (Q1.5.5): + * xemacs-faq.texi (Q1.6.6): + * xemacs-faq.texi (Q1.7.1): + * xemacs-faq.texi (Q1.7.2): + * xemacs-faq.texi (Q1.7.3): + * xemacs-faq.texi (Q1.7.4): + * xemacs-faq.texi (Installation): + * xemacs-faq.texi (Q2.0.1): + * xemacs-faq.texi (Q2.0.2): + * xemacs-faq.texi (Q2.0.3): + * xemacs-faq.texi (Q2.0.4): + * xemacs-faq.texi (Q2.0.5): + * xemacs-faq.texi (Q2.1.1): + * xemacs-faq.texi (Q2.1.2): + * xemacs-faq.texi (Q2.1.3): + * xemacs-faq.texi (Q2.1.4): + * xemacs-faq.texi (Q2.1.5): + * xemacs-faq.texi (Q2.1.6): + * xemacs-faq.texi (Q2.1.7): + * xemacs-faq.texi (Q2.2.1): + * xemacs-faq.texi (Q2.2.2): + * xemacs-faq.texi (Q2.3.1): + * xemacs-faq.texi (Q2.3.2): + * xemacs-faq.texi (Q2.3.3): + * xemacs-faq.texi (Q2.3.4): + * xemacs-faq.texi (Q2.3.5): + * xemacs-faq.texi (Q2.3.6): + * xemacs-faq.texi (Q2.3.7): + * xemacs-faq.texi (Q2.3.8): + * xemacs-faq.texi (Q2.4.1): + * xemacs-faq.texi (Q2.4.2): + * xemacs-faq.texi (Q2.4.3): + * xemacs-faq.texi (Q2.4.4): + * xemacs-faq.texi (Q2.4.5): + * xemacs-faq.texi (Q2.4.6): + * xemacs-faq.texi (Q2.4.7): + * xemacs-faq.texi (Q2.4.8): + * xemacs-faq.texi (Q2.4.9): + * xemacs-faq.texi (Q2.4.10): + * xemacs-faq.texi (Q2.4.11): + * xemacs-faq.texi (Q2.4.12): + * xemacs-faq.texi (Q2.5.1): + * xemacs-faq.texi (Q2.5.2): + * xemacs-faq.texi (Q2.5.3): + * xemacs-faq.texi (Q2.5.4): + * xemacs-faq.texi (Q2.5.5): + * xemacs-faq.texi (Legacy Versions): + * xemacs-faq.texi (Q10.0.1): + * xemacs-faq.texi (Q10.0.2): + Flesh out intro section on packages and section on installing + packages. Incorporate README, README.packages, BUGS, etc/PACKAGES. + Various other changes. + +2005-02-03 Stephen J. Turnbull <stephen@xemacs.org> + + * beta.texi: Update Copyright. Add pointer comment. + + (New packages): Remove personal names, point at jobs.html + instead. + + (Syncing with GNU Emacs): Change "don't assume Mule" to + "conditionalize Mule dependencies correctly". RMS stroking: use + "GNU", not "FSF", in sync notices. + +2005-02-02 Robert Delius Royar <xemacs@frinabulax.org> + + * beta.texi (Top): + Add reference to Index in catalog to prevent + errors compiling with GNU makeinfo 4.5. + + * beta.texi (Syncing with GNU Emacs): + Add forward reference to Index in next node to prevent + errors compiling with GNU makeinfo 4.5. + + * beta.texi (Index): + Add backward reference to Syncing with GNU Emacs to + replace obsolete reference to Defining Variables to + prevent errors compiling with GNU makeinfo 4.5. + +2005-01-31 Ben Wing <ben@xemacs.org> + + * xemacs/help.texi (Misc Help): + Delete references to DISTRIB. Point to FAQ. + + * xemacs/new.texi: + Update sample code for version checking. + + * xemacs/xemacs.texi (Distrib): + * xemacs/xemacs.texi (Intro): + Delete references to DISTRIB. Point directly to web site. + Update stuff referring to GNU Emacs. Delete references to Win-Emacs. + +2005-01-31 Ben Wing <ben@xemacs.org> + + * Makefile: + * Makefile (info_files): + * Makefile (html_files): + * Makefile (dvi_files): + * Makefile (pdf_files): + * Makefile ($(INFODIR)/beta.info): + Add beta.texi and built files. + + * xemacs-faq.texi (Top): + * xemacs-faq.texi (Introduction): + * xemacs-faq.texi (Q1.0.3): + * xemacs-faq.texi (Q1.0.4): + * xemacs-faq.texi (Q1.0.5): + * xemacs-faq.texi (Q1.0.6): + * xemacs-faq.texi (Q1.1.1): + * xemacs-faq.texi (Q1.1.2): + * xemacs-faq.texi (Q1.1.3): + * xemacs-faq.texi (Q1.1.4): + * xemacs-faq.texi (Q1.2.1): + * xemacs-faq.texi (Q1.2.2): + * xemacs-faq.texi (Q1.2.3): + * xemacs-faq.texi (Q1.2.4): + * xemacs-faq.texi (Q1.2.5): + * xemacs-faq.texi (Q1.2.6): + * xemacs-faq.texi (Q1.2.7): + * xemacs-faq.texi (Q1.2.8): + * xemacs-faq.texi (Q1.2.9): + * xemacs-faq.texi (Q1.2.10): + * xemacs-faq.texi (Q1.2.11): + * xemacs-faq.texi (Q1.2.12): + * xemacs-faq.texi (Q1.2.13): + * xemacs-faq.texi (Q1.3.1): + * xemacs-faq.texi (Q1.3.2): + * xemacs-faq.texi (Q1.3.3): + * xemacs-faq.texi (Q1.3.4): + * xemacs-faq.texi (Q1.3.5): + * xemacs-faq.texi (Q1.3.6): + * xemacs-faq.texi (Q1.3.7): + * xemacs-faq.texi (Q1.3.8): + * xemacs-faq.texi (Q1.4.1): + * xemacs-faq.texi (Q1.4.2): + * xemacs-faq.texi (double-word): New. + * xemacs-faq.texi (Q1.4.3): + * xemacs-faq.texi (Q1.4.4): + * xemacs-faq.texi (Q1.4.5): + * xemacs-faq.texi (Q1.5.1): + * xemacs-faq.texi (Q1.5.2): + * xemacs-faq.texi (Q1.5.3): + * xemacs-faq.texi (Q1.6.1): + * xemacs-faq.texi (Q1.6.2): + * xemacs-faq.texi (Q1.6.3): + * xemacs-faq.texi (Q1.6.4): + * xemacs-faq.texi (Q1.6.5): + * xemacs-faq.texi (Q1.6.6): + * xemacs-faq.texi (Q1.7.1): + * xemacs-faq.texi (Q1.8.1): + * xemacs-faq.texi (Q1.8.2): + * xemacs-faq.texi (Q1.8.3): + * xemacs-faq.texi (Q1.8.4): + * xemacs-faq.texi (Q1.8.5): + * xemacs-faq.texi (Q1.8.6): + * xemacs-faq.texi (Q1.8.7): + * xemacs-faq.texi (Q1.8.8): + * xemacs-faq.texi (Q1.8.9): + * xemacs-faq.texi (Q2.2.1): + * xemacs-faq.texi (Q2.2.2): + * xemacs-faq.texi (Q2.4.2): + * xemacs-faq.texi (Advanced): + * xemacs-faq.texi (Q7.0.1): + * xemacs-faq.texi (Q7.0.2): + * xemacs-faq.texi (Q7.0.3): + * xemacs-faq.texi (Q7.0.4): + * xemacs-faq.texi (Q7.0.5): + * xemacs-faq.texi (Q7.0.6): + * xemacs-faq.texi (Q7.1.1): + * xemacs-faq.texi (Q7.1.2): + * xemacs-faq.texi (Q7.1.3): + * xemacs-faq.texi (Q7.1.4): + * xemacs-faq.texi (Q7.1.5): + * xemacs-faq.texi (Q7.1.6): + * xemacs-faq.texi (Q7.1.7): + * xemacs-faq.texi (Q7.1.8): + * xemacs-faq.texi (Q7.1.9): + * xemacs-faq.texi (Q7.1.10): + * xemacs-faq.texi (Q7.1.11): + * xemacs-faq.texi (Q7.2.1): + * xemacs-faq.texi (Q7.2.2): + * xemacs-faq.texi (Q7.2.3): + * xemacs-faq.texi (Other Packages): + * xemacs-faq.texi (Current Events): + * xemacs-faq.texi (Legacy Versions): + Major overhaul of section 1. Add mailing list info, update + downloading info, add info on CVS, etc. + +2004-10-17 Shyamal Prasad <shyamal@member.fsf.org> + + * xemacs/programs.texi (Program Modes): Updated it to reflect + current status of programming modes. + * xemacs/programs.texi (CC Mode): New section introduces CC + Mode. Introduces customization with reference to CC Mode + manual. Also introduce C/AWK modes in prog-modes package + * xemacs/programs.texi (C Ident): Removed - it was + obsolete. prog-modes package documentation now contains + indentation description for old C mode + * xemacs/major.texi (Mode Hooks): Add description of major mode + hooks. Cleaned up and updated programming mode descriptions. + * xemacs/xemacs.texi (Top): Updated Detailed Node listing for new + CC Mode section in programs.texi + + +2005-01-26 Ben Wing <ben@xemacs.org> + + * internals/internals.texi: + * internals/internals.texi (Through Version 18): + * internals/internals.texi (GNU Emacs 19): + * internals/internals.texi (GNU Emacs 20): + Update History. + + * internals/internals.texi (Unicode support under Windows): + Redo section on Windows 95 support for Unicode. + +2005-01-19 Aidan Kehoe <kehoea@parhasard.net> + + * man/lispref/functions.texi (Functions): Rename to "Functions and + Commands" + * man/lispref/functions.texi (What Is a Function): Move the definition + of a command further up the list, give information on a trivial + (interactive) declaration, and cross-reference to the key binding + detail. Cf. 87vf9wgd08.fsf@tleepslib.sk.tsukuba.ac.jp + (comp.emacs.xemacs, 2005-01-18). + * man/lispref/eval.texi man/lispref/lispref.texi + man/lispref/macros.texi man/lispref/symbols.texi + man/lispref/variables.texi: Fix cross references. + +2004-12-28 Ben Wing <ben@xemacs.org> + + * xemacs-faq.texi (Top): + * xemacs-faq.texi (Introduction): + * xemacs-faq.texi (Q1.0.3): + * xemacs-faq.texi (Q1.0.5): + * xemacs-faq.texi (Q1.0.10): + * xemacs-faq.texi (Q1.1.4): + * xemacs-faq.texi (Q1.1.5): + * xemacs-faq.texi (Q1.4.1): + * xemacs-faq.texi (Q1.4.3): + * xemacs-faq.texi (Q1.5.8): + * xemacs-faq.texi (Installation): + * xemacs-faq.texi (Q2.0.3): + * xemacs-faq.texi (Q2.0.5): + * xemacs-faq.texi (Q2.1.1): + * xemacs-faq.texi (Q2.1.2): + * xemacs-faq.texi (Q2.2.7): + * xemacs-faq.texi (Q2.4.6): + * xemacs-faq.texi (Editing): + * xemacs-faq.texi (Q3.0.1): + * xemacs-faq.texi (Q3.0.2): + * xemacs-faq.texi (Q3.0.3): + * xemacs-faq.texi (Q3.0.4): + * xemacs-faq.texi (Q3.0.5): + * xemacs-faq.texi (Q3.0.6): + * xemacs-faq.texi (Q3.0.7): + * xemacs-faq.texi (Q3.0.8): + * xemacs-faq.texi (Q3.0.9): + * xemacs-faq.texi (Q3.0.10): + * xemacs-faq.texi (Q3.0.11): + * xemacs-faq.texi (Q3.1.1): + * xemacs-faq.texi (Q3.1.2): + * xemacs-faq.texi (Q3.1.3): + * xemacs-faq.texi (Q3.1.4): + * xemacs-faq.texi (Q3.1.5): + * xemacs-faq.texi (Q3.2.1): + * xemacs-faq.texi (Q3.2.2): + * xemacs-faq.texi (Q3.2.3): + * xemacs-faq.texi (Q3.2.4): + * xemacs-faq.texi (Q3.2.5): + * xemacs-faq.texi (Q3.3.1): + * xemacs-faq.texi (Q3.3.2): + * xemacs-faq.texi (Q3.3.3): + * xemacs-faq.texi (Q3.3.4): + * xemacs-faq.texi (Q3.3.5): + * xemacs-faq.texi (Q3.3.6): + * xemacs-faq.texi (Q3.4.1): + * xemacs-faq.texi (Q3.4.2): + * xemacs-faq.texi (Display): + * xemacs-faq.texi (Q4.0.1): + * xemacs-faq.texi (Q4.0.2): + * xemacs-faq.texi (Q4.0.3): + * xemacs-faq.texi (Q4.0.4): + * xemacs-faq.texi (my-toggle-toolbar): Removed. + * xemacs-faq.texi (Q4.0.5): + * xemacs-faq.texi (Q4.0.6): + * xemacs-faq.texi (Q4.0.7): + * xemacs-faq.texi (Q4.0.8): + * xemacs-faq.texi (Q4.0.9): + * xemacs-faq.texi (Q4.1.1): + * xemacs-faq.texi (Q4.1.2): + * xemacs-faq.texi (Q4.2.1): + * xemacs-faq.texi (Q4.2.2): + * xemacs-faq.texi (Q4.2.3): + * xemacs-faq.texi (Q4.2.4): + * xemacs-faq.texi (Q4.3.1): + * xemacs-faq.texi (Q4.3.2): + * xemacs-faq.texi (Q4.3.3): + * xemacs-faq.texi (Q4.4.1): + * xemacs-faq.texi (Q4.4.2): + * xemacs-faq.texi (Q4.4.3): + * xemacs-faq.texi (Q4.4.4): + * xemacs-faq.texi (Q4.4.5): + * xemacs-faq.texi (Q4.5.1): + * xemacs-faq.texi (Q4.5.2): + * xemacs-faq.texi (Q4.5.3): + * xemacs-faq.texi (Q4.5.4): + * xemacs-faq.texi (Q4.6.1): + * xemacs-faq.texi (Q4.6.2): + * xemacs-faq.texi (Q4.6.3): + * xemacs-faq.texi (Q4.6.4): + * xemacs-faq.texi (scroll-up): Removed. + * xemacs-faq.texi (Q4.6.5): + * xemacs-faq.texi (scroll-down): Removed. + * xemacs-faq.texi (Q4.6.6): + * xemacs-faq.texi (Q4.6.7): + * xemacs-faq.texi (Q4.7.1): + * xemacs-faq.texi (Q4.7.2): + * xemacs-faq.texi (Q4.7.3): + * xemacs-faq.texi (Q4.7.4): + * xemacs-faq.texi (External Subsystems): + * xemacs-faq.texi (Q5.0.1): + * xemacs-faq.texi (Q5.0.2): + * xemacs-faq.texi (Q5.0.3): + * xemacs-faq.texi (Q5.0.4): + * xemacs-faq.texi (Q5.0.5): + * xemacs-faq.texi (Q5.0.6): + * xemacs-faq.texi (Q5.1.1): + * xemacs-faq.texi (Q5.1.2): + * xemacs-faq.texi (Q5.2.1): + * xemacs-faq.texi (Q5.2.2): + * xemacs-faq.texi (Q5.2.3): + * xemacs-faq.texi (Q5.2.4): + * xemacs-faq.texi (Q5.3.1): + * xemacs-faq.texi (Q5.3.2): + * xemacs-faq.texi (Q5.3.3): + * xemacs-faq.texi (Q5.3.4): + * xemacs-faq.texi (Q5.4.1): + * xemacs-faq.texi (Q5.4.2): + * xemacs-faq.texi (Q5.4.3): + * xemacs-faq.texi (Q5.4.4): + * xemacs-faq.texi (Q5.4.5): + * xemacs-faq.texi (Q5.5.1): + * xemacs-faq.texi (Q5.5.2): + * xemacs-faq.texi (Q5.5.3): + * xemacs-faq.texi (Q5.5.4): + * xemacs-faq.texi (Q5.5.5): + * xemacs-faq.texi (Internet): + * xemacs-faq.texi (Q6.0.1): + * xemacs-faq.texi (Q6.0.2): + * xemacs-faq.texi (Q6.0.3): + * xemacs-faq.texi (Q6.0.4): + * xemacs-faq.texi (Q6.0.5): + * xemacs-faq.texi (Q6.0.6): + * xemacs-faq.texi (Q6.0.7): + * xemacs-faq.texi (Q6.0.8): + * xemacs-faq.texi (Q6.0.9): + * xemacs-faq.texi (Q6.0.10): + * xemacs-faq.texi (Q6.0.11): + * xemacs-faq.texi (Q6.1.1): + * xemacs-faq.texi (Q6.1.2): + * xemacs-faq.texi (Q6.1.3): + * xemacs-faq.texi (Q6.1.4): + * xemacs-faq.texi (Q6.1.5): + * xemacs-faq.texi (Q6.1.6): + * xemacs-faq.texi (Q6.2.1): + * xemacs-faq.texi (Q6.2.2): + * xemacs-faq.texi (Q6.3.1): + * xemacs-faq.texi (Q6.3.2): + * xemacs-faq.texi (Q6.4.1): + * xemacs-faq.texi (Q6.4.2): + * xemacs-faq.texi (Q6.4.3): + * xemacs-faq.texi (Advanced): + * xemacs-faq.texi (Q7.0.1): + * xemacs-faq.texi (Q7.0.2): + * xemacs-faq.texi (Q7.1.1): + * xemacs-faq.texi (Q7.1.2): + * xemacs-faq.texi (Q7.1.3): + * xemacs-faq.texi (Q7.1.4): + * xemacs-faq.texi (Q7.1.5): + * xemacs-faq.texi (Q7.1.6): + * xemacs-faq.texi (Q7.2.1): + * xemacs-faq.texi (Q7.2.2): + * xemacs-faq.texi (Q7.2.3): + * xemacs-faq.texi (Q7.2.4): + * xemacs-faq.texi (Q7.2.5): + * xemacs-faq.texi (Q7.2.6): + * xemacs-faq.texi (Q7.2.7): + * xemacs-faq.texi (Q7.2.8): + * xemacs-faq.texi (Q7.2.9): + * xemacs-faq.texi (Q7.2.10): + * xemacs-faq.texi (Q7.2.11): + * xemacs-faq.texi (Q7.3.1): + * xemacs-faq.texi (Q7.3.2): + * xemacs-faq.texi (Q7.3.3): + * xemacs-faq.texi (Q7.3.4): + * xemacs-faq.texi (Other Packages): + * xemacs-faq.texi (Q8.0.1): + * xemacs-faq.texi (Q8.0.2): + * xemacs-faq.texi (Q8.0.3): + * xemacs-faq.texi (Q8.0.4): + * xemacs-faq.texi (Q8.1.1): + * xemacs-faq.texi (Q8.1.2): + * xemacs-faq.texi (Q8.1.3): + * xemacs-faq.texi (Q8.2.1): + * xemacs-faq.texi (Q8.2.2): + * xemacs-faq.texi (Q8.2.3): + * xemacs-faq.texi (Q8.2.4): + * xemacs-faq.texi (Current Events): + * xemacs-faq.texi (Q9.0.1): + * xemacs-faq.texi (my-function): Removed. + * xemacs-faq.texi (Q9.0.2): + * xemacs-faq.texi (Q9.0.3): + * xemacs-faq.texi (Q9.0.4): + * xemacs-faq.texi (Q9.0.5): + * xemacs-faq.texi (Legacy Versions): + Major rearrangement. Expand to 10 sections. Add various questions, + mostly stubs currently. Remove some obsolete stuff. Update a bunch + of the links. + +2004-12-15 Ville Skyttä <scop@xemacs.org> + + * lispref/help.texi: Document 3rd arg to `make-obsolete'. + +2004-12-15 Robert Delius Royar <xemacs@frinabulax.org> + + * internals/internals.texi (Modules for the Basic Displayable Lisp + Objects): Remove Mote in Make's eye, fix build. + +2004-12-12 Stephen J. Turnbull <stephen@xemacs.org> + + * internals/internals.texi (Modules for the Basic Displayable Lisp + Objects): Comment on problems, and extensions needed to handle + native widgets properly. + +2004-12-10 Stephen J. Turnbull <stephen@xemacs.org> + + * internals/internals.texi (Better Rendering Support -- + Implementation): Document reasons for Label Widget crash. + +2004-12-07 Malcolm Purvis <malcolmp@xemacs.org> + + * Makefile (RECURSIVE_MAKE): Removed. + * Makefile (RECURSIVE_MAKE_ARGS): New. The new method for + handling parallel builds. + +2004-12-05 Ben Wing <ben@xemacs.org> + + * xemacs/packages.texi (Packages): + * xemacs/packages.texi (Manually): + * xemacs/packages.texi (Building Packages): + * xemacs/packages.texi (Local.rules File): + * xemacs/packages.texi (Available Packages): + Add long form of Lisp Reference Manual to links. + Add links pointing to Lisp Reference Manual for more detailed + package discussion. + + * xemacs/xemacs-faq.texi: + As per Adrian's suggestion, mention that Pitts Jarvis is deceased. + +2004-12-05 Ben Wing <ben@xemacs.org> + + * lispref/range-tables.texi (Range Tables): + * lispref/range-tables.texi (Introduction to Range Tables): + * lispref/range-tables.texi (Working With Range Tables): + Document range-table changes. + +2004-12-05 Ben Wing <ben@xemacs.org> + + * internals/internals.texi (A History of Emacs): + Update history section. + +2004-12-05 Ben Wing <ben@xemacs.org> + + * xemacs-faq.texi: + * xemacs-faq.texi (fix-main-menu): New. + * xemacs-faq.texi (fix-omitted-menu-lines): New. + * xemacs-faq.texi (Top): + * xemacs-faq.texi (Introduction): + * xemacs-faq.texi (Q1.0.1): + * xemacs-faq.texi (Q1.0.2): + * xemacs-faq.texi (Q1.0.4): + * xemacs-faq.texi (Q1.0.5): + * xemacs-faq.texi (Q1.0.6): + * xemacs-faq.texi (Q1.0.7): + * xemacs-faq.texi (Q1.0.8): + * xemacs-faq.texi (Q1.0.9): + * xemacs-faq.texi (Q1.0.10): + * xemacs-faq.texi (Q1.0.11): + * xemacs-faq.texi (Q1.0.12): + * xemacs-faq.texi (Q1.0.13): + * xemacs-faq.texi (Q1.0.14): + * xemacs-faq.texi (Q1.1.1): + * xemacs-faq.texi (Q1.1.2): + * xemacs-faq.texi (Q1.1.3): + * xemacs-faq.texi (Q1.1.4): + * xemacs-faq.texi (Q1.1.5): + * xemacs-faq.texi (Q1.1.6): + * xemacs-faq.texi (Q1.1.7): + * xemacs-faq.texi (Q1.1.8): + * xemacs-faq.texi (Q1.1.9): + * xemacs-faq.texi (Q1.2.1): + * xemacs-faq.texi (Q1.2.2): + * xemacs-faq.texi (Q1.2.3): + * xemacs-faq.texi (Q1.3.1): + * xemacs-faq.texi (Q1.3.2): + * xemacs-faq.texi (Q1.3.3): + * xemacs-faq.texi (Q1.4.1): + * xemacs-faq.texi (Q1.4.2): + * xemacs-faq.texi (Q1.4.3): + * xemacs-faq.texi (Q1.4.4): + * xemacs-faq.texi (Q1.4.5): + * xemacs-faq.texi (Q1.4.6): + * xemacs-faq.texi (Q1.4.7): + * xemacs-faq.texi (Q1.4.8): + * xemacs-faq.texi (Q1.4.9): + * xemacs-faq.texi (Q1.5.1): + * xemacs-faq.texi (Q1.5.2): + * xemacs-faq.texi (Q1.5.3): + * xemacs-faq.texi (Q1.5.4): + * xemacs-faq.texi (Q1.5.5): + * xemacs-faq.texi (Q1.5.6): + * xemacs-faq.texi (Q1.5.7): + * xemacs-faq.texi (Q1.5.8): + * xemacs-faq.texi (Installation): + * xemacs-faq.texi (Q2.0.1): + * xemacs-faq.texi (Q2.0.2): + * xemacs-faq.texi (Q2.0.3): + * xemacs-faq.texi (Q2.0.4): + * xemacs-faq.texi (Q2.0.5): + * xemacs-faq.texi (Q2.0.6): + * xemacs-faq.texi (Q2.0.7): + * xemacs-faq.texi (Q2.1.1): + * xemacs-faq.texi (Q2.1.2): + * xemacs-faq.texi (Q2.1.3): + * xemacs-faq.texi (Q2.1.4): + * xemacs-faq.texi (Q2.2.1): + * xemacs-faq.texi (Q2.2.2): + * xemacs-faq.texi (Q2.2.3): + * xemacs-faq.texi (Q2.2.4): + * xemacs-faq.texi (Q2.2.5): + * xemacs-faq.texi (Q2.2.6): + * xemacs-faq.texi (Q2.2.7): + * xemacs-faq.texi (Q2.2.8): + * xemacs-faq.texi (Q2.3.1): + * xemacs-faq.texi (Q2.3.2): + * xemacs-faq.texi (Q2.3.3): + * xemacs-faq.texi (Q2.3.4): + * xemacs-faq.texi (Q2.3.5): + * xemacs-faq.texi (Q2.3.6): + * xemacs-faq.texi (Q2.3.7): + * xemacs-faq.texi (Q2.3.8): + * xemacs-faq.texi (Q2.3.9): + * xemacs-faq.texi (Q2.3.10): + * xemacs-faq.texi (Q2.3.11): + * xemacs-faq.texi (Q2.4.1): + * xemacs-faq.texi (Q2.4.2): + * xemacs-faq.texi (Q2.4.3): + * xemacs-faq.texi (Q2.4.4): + * xemacs-faq.texi (Q2.4.5): + * xemacs-faq.texi (Q2.4.6): + * xemacs-faq.texi (Display Subsystems): + * xemacs-faq.texi (running-xemacs): Removed. + * xemacs-faq.texi (Q3.0.1): + * xemacs-faq.texi (Q3.0.2): + * xemacs-faq.texi (Q3.0.3): + * xemacs-faq.texi (Q3.0.4): + * xemacs-faq.texi (Q3.0.5): + * xemacs-faq.texi (Q3.0.6): + * xemacs-faq.texi (foo-old-losing-code-p): Removed. + * xemacs-faq.texi (Q3.0.7): + * xemacs-faq.texi (Q3.0.8): + * xemacs-faq.texi (Q3.0.9): + * xemacs-faq.texi (Q3.0.10): + * xemacs-faq.texi (Q3.1.1): + * xemacs-faq.texi (Q3.1.2): + * xemacs-faq.texi (Q3.1.3): + * xemacs-faq.texi (Q3.1.4): + * xemacs-faq.texi (Q3.1.5): + * xemacs-faq.texi (Q3.2.1): + * xemacs-faq.texi (Q3.2.2): + * xemacs-faq.texi (Q3.2.3): + * xemacs-faq.texi (Q3.2.4): + * xemacs-faq.texi (Q3.2.5): + * xemacs-faq.texi (Q3.2.6): + * xemacs-faq.texi (Q3.2.7): + * xemacs-faq.texi (Q3.2.8): + * xemacs-faq.texi (Q3.2.9): + * xemacs-faq.texi (Q3.3.1): + * xemacs-faq.texi (Q3.3.2): + * xemacs-faq.texi (Q3.3.3): + * xemacs-faq.texi (Q3.3.4): + * xemacs-faq.texi (Q3.3.5): + * xemacs-faq.texi (Q3.3.6): + * xemacs-faq.texi (Q3.4.1): + * xemacs-faq.texi (Q3.4.2): + * xemacs-faq.texi (Q3.4.3): + * xemacs-faq.texi (Q3.4.4): + * xemacs-faq.texi (Q3.4.5): + * xemacs-faq.texi (Q3.4.6): + * xemacs-faq.texi (Q3.5.1): + * xemacs-faq.texi (Q3.5.2): + * xemacs-faq.texi (Q3.5.3): + * xemacs-faq.texi (Q3.5.4): + * xemacs-faq.texi (Q3.6.1): + * xemacs-faq.texi (Q3.6.2): + * xemacs-faq.texi (Q3.6.3): + * xemacs-faq.texi (Q3.7.1): + * xemacs-faq.texi (Q3.7.2): + * xemacs-faq.texi (Q3.7.3): + * xemacs-faq.texi (Q3.7.4): + * xemacs-faq.texi (Q3.7.5): + * xemacs-faq.texi (Q3.7.6): + * xemacs-faq.texi (Q3.7.7): + * xemacs-faq.texi (Q3.7.8): + * xemacs-faq.texi (Q3.8.1): + * xemacs-faq.texi (Q3.8.2): + * xemacs-faq.texi (Q3.8.3): + * xemacs-faq.texi (my-toggle-toolbar): New. + * xemacs-faq.texi (Q3.8.4): + * xemacs-faq.texi (scroll-one-line-up): Removed. + * xemacs-faq.texi (scroll-one-line-down): Removed. + * xemacs-faq.texi (Q3.8.5): + * xemacs-faq.texi (Q3.9.1): + * xemacs-faq.texi (Q3.9.2): + * xemacs-faq.texi (Q3.9.3): + * xemacs-faq.texi (Q3.9.4): + * xemacs-faq.texi (Q3.9.5): + * xemacs-faq.texi (External Subsystems): + * xemacs-faq.texi (Q4.0.1): + * xemacs-faq.texi (Q4.0.2): + * xemacs-faq.texi (Q4.0.3): + * xemacs-faq.texi (Q4.0.4): + * xemacs-faq.texi (Q4.0.5): + * xemacs-faq.texi (Q4.0.6): + * xemacs-faq.texi (global-map): Removed. + * xemacs-faq.texi (Q4.1.1): + * xemacs-faq.texi (Q4.1.2): + * xemacs-faq.texi (Q4.2.1): + * xemacs-faq.texi (Q4.2.2): + * xemacs-faq.texi (Q4.2.3): + * xemacs-faq.texi (Q4.2.4): + * xemacs-faq.texi (Q4.3.1): + * xemacs-faq.texi (Q4.3.2): + * xemacs-faq.texi (Q4.3.3): + * xemacs-faq.texi (Q4.3.4): + * xemacs-faq.texi (Q4.4.1): + * xemacs-faq.texi (Q4.4.2): + * xemacs-faq.texi (Q4.4.3): + * xemacs-faq.texi (Q4.4.4): + * xemacs-faq.texi (Q4.4.5): + * xemacs-faq.texi (Q4.5.1): + * xemacs-faq.texi (Q4.5.2): + * xemacs-faq.texi (Q4.5.3): + * xemacs-faq.texi (Q4.5.4): + * xemacs-faq.texi (Q4.5.5): + * xemacs-faq.texi (Q4.6.1): + * xemacs-faq.texi (Q4.6.2): + * xemacs-faq.texi (Q4.6.3): + * xemacs-faq.texi (Q4.6.4): + * xemacs-faq.texi (Q4.7.1): + * xemacs-faq.texi (Q4.7.2): + * xemacs-faq.texi (Q4.7.3): + * xemacs-faq.texi (Q4.8.1): + * xemacs-faq.texi (Q4.8.2): + * xemacs-faq.texi (Q4.8.3): + * xemacs-faq.texi (Q4.8.4): + * xemacs-faq.texi (Internet): + * xemacs-faq.texi (Q5.0.1): + * xemacs-faq.texi (Q5.0.2): + * xemacs-faq.texi (Q5.0.3): + * xemacs-faq.texi (Q5.0.4): + * xemacs-faq.texi (Q5.0.5): + * xemacs-faq.texi (Q5.0.6): + * xemacs-faq.texi (Q5.0.7): + * xemacs-faq.texi (Q5.0.8): + * xemacs-faq.texi (Q5.0.9): + * xemacs-faq.texi (Q5.0.10): + * xemacs-faq.texi (Q5.0.11): + * xemacs-faq.texi (Q5.1.1): + * xemacs-faq.texi (Q5.1.2): + * xemacs-faq.texi (Q5.1.3): + * xemacs-faq.texi (Q5.1.4): + * xemacs-faq.texi (Q5.1.5): + * xemacs-faq.texi (Q5.1.6): + * xemacs-faq.texi (Q5.2.1): + * xemacs-faq.texi (Q5.2.2): + * xemacs-faq.texi (Q5.3.1): + * xemacs-faq.texi (Q5.3.2): + * xemacs-faq.texi (Q5.4.1): + * xemacs-faq.texi (Q5.4.2): + * xemacs-faq.texi (Q5.4.3): + * xemacs-faq.texi (Advanced): + * xemacs-faq.texi (Q6.0.1): + * xemacs-faq.texi (Q6.0.2): + * xemacs-faq.texi (Q6.1.1): + * xemacs-faq.texi (Q6.1.2): + * xemacs-faq.texi (Q6.1.3): + * xemacs-faq.texi (Q6.1.4): + * xemacs-faq.texi (Q6.1.5): + * xemacs-faq.texi (Q6.1.6): + * xemacs-faq.texi (Q6.2.1): + * xemacs-faq.texi (Q6.2.2): + * xemacs-faq.texi (Q6.2.3): + * xemacs-faq.texi (Q6.2.4): + * xemacs-faq.texi (Q6.2.5): + * xemacs-faq.texi (Q6.2.6): + * xemacs-faq.texi (Q6.2.7): + * xemacs-faq.texi (Q6.2.8): + * xemacs-faq.texi (Q6.2.9): + * xemacs-faq.texi (Q6.2.10): + * xemacs-faq.texi (Q6.2.11): + * xemacs-faq.texi (Q6.3.1): + * xemacs-faq.texi (Q6.3.2): + * xemacs-faq.texi (Q6.3.3): + * xemacs-faq.texi (Q6.3.4): + * xemacs-faq.texi (Current Events): + * xemacs-faq.texi (Q7.0.1): + * xemacs-faq.texi (Q7.0.2): + * xemacs-faq.texi (Q7.0.3): + * xemacs-faq.texi (Q7.0.5): + * xemacs-faq.texi (Q7.0.6): + * xemacs-faq.texi (Legacy Versions): + * xemacs-faq.texi (my-function): Removed. + * xemacs-faq.texi (Q8.0.1): + + The section on Troubleshooting (now 2.3) has been completely + written and includes a lot of stuff that is not properly + documented anywhere else. A fair amount of obsolete info has been + deleted and I've incorporated the comments that people (mostly + Stephen T) made. Former chapter 3 has been split up in two, one + pertaining to basic I/O and the other to external I/O. What were + formerly chapters 5 and 6 no longer exist as such; the info in + them has been distributed across various other chapters. Old + chapter 4 got split up, part going to the new chapter 4 on + external I/O and part going to the new chapter 5 on the Internet. + In this new chapter, stuff not pertaining to a specific package + (e.g. VM or GNUS) was taken out of package-specific sections and a + general mail section was constituted. Part of old chapter 5 + remains in a new chapter 6 devoted to Emacs Lisp and other + advanced stuff, and a section from old chapter 3 on basic + init-file Lisp and some stuff from old chapter 5 on Info. The + rest of chapter 5 was just "misc" and has gotten scattered to the + winds (mostly in chapters 3 and 4). Old chapter 6 has also gotten + quite scattered; there is no longer any section specifically + devoted to Windows except one of the Installation sections (along + with a section specfically devoted to Unix), and the rest has + moved to join the appropriate non-Windows-specific section + elsewhere. A lot of chapters had their sections rearranged and + likewise for sections having entries rearranged, with the + intention that the new arrangement should be more natural. In + general I hope that stuff should be much easier to locate. I also + rewrote the entries on the relation between XEmacs and GNU Emacs + on the authors of XEmacs, including lots of info on who wrote + specific subsections. + +2004-12-05 Adrian Aichner <adrian@xemacs.org> + + * Makefile (TEXI2HTML): Changed to produce unsplit output. + * Makefile (TEXI2HTML_SPLIT): New. + * Makefile (CP): New. + * Makefile (PHOTODIR): New. + * Makefile ($(HTMLDIR)/cl.html): Use TEXI2HTML_SPLIT. + * Makefile ($(HTMLDIR)/custom.html): Ditto. + * Makefile ($(HTMLDIR)/emodules.html): Ditto. + * Makefile ($(HTMLDIR)/external-widget.html): Ditto. + * Makefile ($(HTMLDIR)/info.html): Ditto. + * Makefile ($(HTMLDIR)/standards.html): Ditto. + * Makefile ($(HTMLDIR)/term.html): Ditto. + * Makefile ($(HTMLDIR)/termcap.html): Ditto. + * Makefile ($(HTMLDIR)/texinfo.html): Ditto. + * Makefile ($(HTMLDIR)/widget.html): Ditto. + * Makefile ($(HTMLDIR)/xemacs-faq.html): Ditto. + Produce unsplit output for website also, copy photos to HTMLDIR. + * Makefile ($(HTMLDIR)/xemacs.html): Ditto. + * Makefile ($(HTMLDIR)/lispref.html): Ditto. + * Makefile ($(HTMLDIR)/internals.html): Ditto. + * Makefile ($(HTMLDIR)/new-users-guide.html): Ditto. + * xemacs-faq.texi (Q1.3.1): Fix broken image links in HTML output. + +2004-11-26 Stephen J. Turnbull <stephen@xemacs.org> + + * internals/internals.texi (Better Rendering Support -- + Configuration with the Interim Patches): + Add documentation of X resources, especially for GUI elements. + (Better Rendering Support -- Implementation): + More comments about specification and design issues. + (Better Rendering Support -- Current Status): + New subsubsection "Bugs Reported in sjt-xft". + +2004-11-26 Stephen J. Turnbull <stephen@xemacs.org> + + * internals/internals.texi (Future Work -- Better Rendering Support): + New node. + (Top): + (Future Work): + (Future Work -- Lisp Engine Replacement): + Add pointers to new node. + +2004-11-16 Ben Wing <ben@xemacs.org> + + * internals/internals.texi (Top): + * internals/internals.texi (Introduction): + * internals/internals.texi (Authorship of XEmacs): + * internals/internals.texi (A History of Emacs): + * internals/internals.texi (Through Version 18): + * internals/internals.texi (Epoch): + * internals/internals.texi (Lucid Emacs): + * internals/internals.texi (GNU Emacs 19): + * internals/internals.texi (GNU Emacs 20): + * internals/internals.texi (XEmacs): + * internals/internals.texi (The XEmacs Split): + * internals/internals.texi (Build-Time Dependencies): + * internals/internals.texi (Low-Level Modules): + * internals/internals.texi (Modules for Interfacing with the Operating System): + * internals/internals.texi (Rules When Writing New C Code): + * internals/internals.texi (Introduction to Writing C Code): + * internals/internals.texi (Writing New Modules): + * internals/internals.texi (Working with Lisp Objects): + * internals/internals.texi (Writing Lisp Primitives): + * internals/internals.texi (Adding Global Lisp Variables): + * internals/internals.texi (Writing Macros): + * internals/internals.texi (Proper Use of Unsigned Types): + * internals/internals.texi (Major Textual Changes): + * internals/internals.texi (Great Integral Type Renaming): + * internals/internals.texi (Text/Char Type Renaming): + * internals/internals.texi (Debugging and Testing): + * internals/internals.texi (Modules for Regression Testing): + * internals/internals.texi (Merging a Branch into the Trunk): + * internals/internals.texi (XEmacs from the Inside): + * internals/internals.texi (Basic Types): + * internals/internals.texi (Low-Level Allocation): + * internals/internals.texi (Basic Heap Allocation): + * internals/internals.texi (Stack Allocation): + * internals/internals.texi (Dynamic Arrays): + * internals/internals.texi (Allocation by Blocks): + * internals/internals.texi (Modules for Allocation): + * internals/internals.texi (Critical Redisplay Sections): + * internals/internals.texi (Control-G (Quit) Checking): + * internals/internals.texi (Future Work Discussion): + * internals/internals.texi (Discussion -- Garbage Collection): + * internals/internals.texi (Discussion -- Pure Space): + * internals/internals.texi (Discussion -- Hashtable-Based Marking and Cleanup): + * internals/internals.texi (Discussion -- The Anti-Cons): + * internals/internals.texi (Discussion -- Glyphs): + * internals/internals.texi (Discussion -- Dialog Boxes): + * internals/internals.texi (Discussion -- Multilingual Issues): + * internals/internals.texi (Discussion -- Instantiators and Generic Property Accessors): + * internals/internals.texi (image-instance-property): New. + * internals/internals.texi (set-image-instance-property): New. + * internals/internals.texi (Discussion -- Switching to C++): + * internals/internals.texi (Discussion -- Windows External Widget): + + Add sections on Basic Types and Low-Level Allocation. Move module + docs here. Incorporate dynamic array and blocktype docs from + source. + + Add info on beta releases up to present. + + Redo chapter on "Rules When Writing New C Code", grouping stuff + together properly. Put "Major Textual Changes" under this + chapter. Incorporate etc/CODING-STANDARDS. + + Add discussion sections on "Instantiators and Generic Property + Accessors" and "Switching to C++". Fill out discussion on garbage + collection. + + Incorporate backtraces showing crashes due to problems with + redisplay-critical-section protection. + +2004-11-04 Ben Wing <ben@xemacs.org> + + * lispref/mule.texi (CCL Syntax): + * lispref/mule.texi (INT-OR-CHAR): New. + * lispref/mule.texi (CCL Statements): + Update CCL docs. + +2004-11-04 Ben Wing <ben@xemacs.org> + + * internals/internals.texi (Top): + * internals/internals.texi (NOTE): New. + * internals/internals.texi (list-to-texinfo): New. + * internals/internals.texi (remove-spacing): New. + * internals/internals.texi (table-to-texinfo): New. + * internals/internals.texi (convert-text-to-texinfo): New. + * internals/internals.texi ('make-future): New. + * internals/internals.texi ('make-discussion): New. + * internals/internals.texi ('make-old-future): New. + * internals/internals.texi ('make-section): New. + * internals/internals.texi ('make-subsection): New. + * internals/internals.texi (Introduction): + * internals/internals.texi (divisions): New. + * internals/internals.texi (Authorship of XEmacs): + * internals/internals.texi (XEmacs): + * internals/internals.texi (The XEmacs Split): + * internals/internals.texi (Author): New. + * internals/internals.texi (XEmacs from the Outside): + * internals/internals.texi (The Lisp Language): + * internals/internals.texi (XEmacs from the Perspective of Building): + * internals/internals.texi (Build-Time Dependencies): + * internals/internals.texi (The Modules of XEmacs): + * internals/internals.texi (A Summary of the Various XEmacs Modules): + * internals/internals.texi (ways): Removed. + * internals/internals.texi (Low-Level Modules): + * internals/internals.texi (Basic Lisp Modules): + * internals/internals.texi (Modules for Standard Editing Operations): + * internals/internals.texi (files): Removed. + * internals/internals.texi (Modules for Interfacing with the File System): + * internals/internals.texi (some_variable): Removed. + * internals/internals.texi (Modules for Other Aspects of the Lisp Interpreter and Object System): + * internals/internals.texi (Modules for Interfacing with the Operating System): + * internals/internals.texi (character): Removed. + * internals/internals.texi (Major Textual Changes): + * internals/internals.texi (Great Integral Type Renaming): + * internals/internals.texi (commands): Removed. + * internals/internals.texi (Text/Char Type Renaming): + * internals/internals.texi (pattern): Removed. + * internals/internals.texi (Rules When Writing New C Code): + * internals/internals.texi (A Reader's Guide to XEmacs Coding Conventions): + * internals/internals.texi (General Coding Rules): + * internals/internals.texi (examples): Removed. + * internals/internals.texi (Object-Oriented Techniques for C): + * internals/internals.texi (Writing Lisp Primitives): + * internals/internals.texi (Writing Good Comments): + * internals/internals.texi (Adding Global Lisp Variables): + * internals/internals.texi (Writing Macros): + * internals/internals.texi (Proper Use of Unsigned Types): + * internals/internals.texi (Techniques for XEmacs Developers): + * internals/internals.texi (Regression Testing XEmacs): + * internals/internals.texi (How to Regression-Test): + * internals/internals.texi (Modules for Regression Testing): + * internals/internals.texi (CVS Techniques): + * internals/internals.texi (Merging a Branch into the Trunk): + * internals/internals.texi (XEmacs from the Inside): + * internals/internals.texi (The XEmacs Object System (Abstractly Speaking)): + * internals/internals.texi (How Lisp Objects Are Represented in C): + * internals/internals.texi (Allocation of Objects in XEmacs Lisp): + * internals/internals.texi (Introduction to Allocation): + * internals/internals.texi (Garbage Collection): + * internals/internals.texi (GCPROing): + * internals/internals.texi (Garbage Collection - Step by Step): + * internals/internals.texi (Invocation): + * internals/internals.texi (garbage_collect_1): + * internals/internals.texi (mark_object): + * internals/internals.texi (gc_sweep): + * internals/internals.texi (sweep_lcrecords_1): + * internals/internals.texi (compact_string_chars): + * internals/internals.texi (sweep_strings): + * internals/internals.texi (sweep_bit_vectors_1): + * internals/internals.texi (Integers and Characters): + * internals/internals.texi (Allocation from Frob Blocks): + * internals/internals.texi (lrecords): + * internals/internals.texi (Low-level allocation): + * internals/internals.texi (Cons): + * internals/internals.texi (Vector): + * internals/internals.texi (Bit Vector): + * internals/internals.texi (Symbol): + * internals/internals.texi (Marker): + * internals/internals.texi (String): + * internals/internals.texi (Compiled Function): + * internals/internals.texi (The Lisp Reader and Compiler): + * internals/internals.texi (Evaluation; Stack Frames; Bindings): + * internals/internals.texi (Evaluation): + * internals/internals.texi (Dynamic Binding; The specbinding Stack; Unwind-Protects): + * internals/internals.texi (Simple Special Forms): + * internals/internals.texi (Catch and Throw): + * internals/internals.texi (Error Trapping): + * internals/internals.texi (Symbols and Variables): + * internals/internals.texi (Introduction to Symbols): + * internals/internals.texi (Obarrays): + * internals/internals.texi (Symbol Values): + * internals/internals.texi (Buffers): + * internals/internals.texi (Introduction to Buffers): + * internals/internals.texi (Buffer Lists): + * internals/internals.texi (Markers and Extents): + * internals/internals.texi (The Buffer Object): + * internals/internals.texi (Text): + * internals/internals.texi (The Text in a Buffer): + * internals/internals.texi (Ibytes and Ichars): + * internals/internals.texi (Byte-Char Position Conversion): + * internals/internals.texi (Searching and Matching): + * internals/internals.texi (Multilingual Support): + * internals/internals.texi (Introduction to Multilingual Issues #1): + * internals/internals.texi (Introduction to Multilingual Issues #2): + * internals/internals.texi (Introduction to Multilingual Issues #3): + * internals/internals.texi (Introduction to Multilingual Issues #4): + * internals/internals.texi (Character Sets): + * internals/internals.texi (Encodings): + * internals/internals.texi (Japanese EUC (Extended Unix Code)): + * internals/internals.texi (JIS7): + * internals/internals.texi (Internal Mule Encodings): + * internals/internals.texi (Internal String Encoding): + * internals/internals.texi (Internal Character Encoding): + * internals/internals.texi (Byte/Character Types; Buffer Positions; Other Typedefs): + * internals/internals.texi (Byte Types): + * internals/internals.texi (Different Ways of Seeing Internal Text): + * internals/internals.texi (Buffer Positions): + * internals/internals.texi (Other Typedefs): + * internals/internals.texi (Usage of the Various Representations): + * internals/internals.texi (Working With the Various Representations): + * internals/internals.texi (Internal Text API's): + * internals/internals.texi (Basic internal-format API's): + * internals/internals.texi (The DFC API): + * internals/internals.texi (The Eistring API): + * internals/internals.texi (Coding for Mule): + * internals/internals.texi (Character-Related Data Types): + * internals/internals.texi (Working With Character and Byte Positions): + * internals/internals.texi (Conversion to and from External Data): + * internals/internals.texi (General Guidelines for Writing Mule-Aware Code): + * internals/internals.texi (An Example of Mule-Aware Code): + * internals/internals.texi (Mule-izing Code): + * internals/internals.texi (CCL): + * internals/internals.texi (Microsoft Windows-Related Multilingual Issues): + * internals/internals.texi (Microsoft Documentation): + * internals/internals.texi (Locales): + * internals/internals.texi (More about code pages): + * internals/internals.texi (More about locales): + * internals/internals.texi (Unicode support under Windows): + * internals/internals.texi (The golden rules of writing Unicode-safe code): + * internals/internals.texi (The format of the locale in setlocale()): + * internals/internals.texi (Random other Windows I18N docs): + * internals/internals.texi (Modules for Internationalization): + * internals/internals.texi (Consoles; Devices; Frames; Windows): + * internals/internals.texi (Introduction to Consoles; Devices; Frames; Windows): + * internals/internals.texi (Point): + * internals/internals.texi (Window Hierarchy): + * internals/internals.texi (The Window Object): + * internals/internals.texi (Modules for the Basic Displayable Lisp Objects): + * internals/internals.texi (The Redisplay Mechanism): + * internals/internals.texi (Critical Redisplay Sections): + * internals/internals.texi (Line Start Cache): + * internals/internals.texi (Redisplay Piece by Piece): + * internals/internals.texi (Modules for the Redisplay Mechanism): + * internals/internals.texi (Modules for other Display-Related Lisp Objects): + * internals/internals.texi (Extents): + * internals/internals.texi (Introduction to Extents): + * internals/internals.texi (Extent Ordering): + * internals/internals.texi (Format of the Extent Info): + * internals/internals.texi (Zero-Length Extents): + * internals/internals.texi (Mathematics of Extent Ordering): + * internals/internals.texi (Extent Fragments): + * internals/internals.texi (Faces): + * internals/internals.texi (Glyphs): + * internals/internals.texi (Specifiers): + * internals/internals.texi (Menus): + * internals/internals.texi (Events and the Event Loop): + * internals/internals.texi (Introduction to Events): + * internals/internals.texi (Main Loop): + * internals/internals.texi (Specifics of the Event Gathering Mechanism): + * internals/internals.texi (Specifics About the Emacs Event): + * internals/internals.texi (Event Queues): + * internals/internals.texi (Event Stream Callback Routines): + * internals/internals.texi (Other Event Loop Functions): + * internals/internals.texi (Stream Pairs): + * internals/internals.texi (Converting Events): + * internals/internals.texi (Dispatching Events; The Command Builder): + * internals/internals.texi (Focus Handling): + * internals/internals.texi (Editor-Level Control Flow Modules): + * internals/internals.texi (Asynchronous Events; Quit Checking): + * internals/internals.texi (Signal Handling): + * internals/internals.texi (Control-G (Quit) Checking): + * internals/internals.texi (Profiling): + * internals/internals.texi (Asynchronous Timeouts): + * internals/internals.texi (Exiting): + * internals/internals.texi (Lstreams): + * internals/internals.texi (Creating an Lstream): + * internals/internals.texi (Lstream Types): + * internals/internals.texi (Lstream Functions): + * internals/internals.texi (Lstream Methods): + * internals/internals.texi (Subprocesses): + * internals/internals.texi (Interface to MS Windows): + * internals/internals.texi (Different kinds of Windows environments): + * internals/internals.texi (Windows Build Flags): + * internals/internals.texi (Windows I18N Introduction): + * internals/internals.texi (Modules for Interfacing with MS Windows): + * internals/internals.texi (Interface to the X Window System): + * internals/internals.texi (Lucid Widget Library): + * internals/internals.texi (Generic Widget Interface): + * internals/internals.texi (dependencies): New. + * internals/internals.texi (routines): New. + * internals/internals.texi (Summary): New. + * internals/internals.texi (Scrollbars): + * internals/internals.texi (Menubars): + * internals/internals.texi (Checkboxes and Radio Buttons): + * internals/internals.texi (Progress Bars): + * internals/internals.texi (Tab Controls): + * internals/internals.texi (Modules for Interfacing with X Windows): + * internals/internals.texi (Dumping): + * internals/internals.texi (Dumping Justification): + * internals/internals.texi (Overview): + * internals/internals.texi (Data descriptions): + * internals/internals.texi (Dumping phase): + * internals/internals.texi (Object inventory): + * internals/internals.texi (Address allocation): + * internals/internals.texi (The header): + * internals/internals.texi (Data dumping): + * internals/internals.texi (Pointers dumping): + * internals/internals.texi (Reloading phase): + * internals/internals.texi (Abstract): New. + * internals/internals.texi (Remaining issues): + * internals/internals.texi (Future Work): + * internals/internals.texi (Future Work -- General Suggestions): + * internals/internals.texi (Future Work -- Elisp Compatibility Package): + * internals/internals.texi (Future Work -- Drag-n-Drop): + * internals/internals.texi (Future Work -- Standard Interface for Enabling Extensions): + * internals/internals.texi (Future Work -- Better Initialization File Scheme): + * internals/internals.texi (Future Work -- Keyword Parameters): + * internals/internals.texi (Future Work -- Property Interface Changes): + * internals/internals.texi (Future Work -- Toolbars): + * internals/internals.texi (Future Work -- Easier Toolbar Customization): + * internals/internals.texi (Future Work -- Toolbar Interface Changes): + * internals/internals.texi (Future Work -- Menu API Changes): + * internals/internals.texi (Future Work -- Removal of Misc-User Event Type): + * internals/internals.texi (Future Work -- Mouse Pointer): + * internals/internals.texi (Future Work -- Abstracted Mouse Pointer Interface): + * internals/internals.texi (Future Work -- Busy Pointer): + * internals/internals.texi (Future Work -- Extents): + * internals/internals.texi (Future Work -- Everything should obey duplicable extents): + * internals/internals.texi (Future Work -- Version Number and Development Tree Organization): + * internals/internals.texi (Future Work -- Improvements to the @code{xemacs.org} Website): + * internals/internals.texi (Future Work -- Keybindings): + * internals/internals.texi (Future Work -- Keybinding Schemes): + * internals/internals.texi (Future Work -- Better Support for Windows Style Key Bindings): + * internals/internals.texi (Future Work -- Misc Key Binding Ideas): + * internals/internals.texi (Future Work -- Byte Code Snippets): + * internals/internals.texi (Future Work -- Autodetection): + * internals/internals.texi (Future Work -- Conversion Error Detection): + * internals/internals.texi (Future Work -- Unicode): + * internals/internals.texi (Future Work -- BIDI Support): + * internals/internals.texi (Future Work -- Localized Text/Messages): + * internals/internals.texi (Future Work -- Lisp Stream API): + * internals/internals.texi (Future Work -- Multiple Values): + * internals/internals.texi (Future Work -- Macros): + * internals/internals.texi (Future Work -- Specifiers): + * internals/internals.texi (Future Work -- Display Tables): + * internals/internals.texi (Future Work -- Making Elisp Function Calls Faster): + * internals/internals.texi (Future Work -- Lisp Engine Replacement): + * internals/internals.texi (Future Work -- Lisp Engine Discussion): + * internals/internals.texi (Future Work -- Lisp Engine Replacement -- Implementation): + * internals/internals.texi (Future Work -- Startup File Modification by Packages): + * internals/internals.texi (Future Work Discussion): + * internals/internals.texi (Discussion -- garbage collection): + * internals/internals.texi (Discussion -- glyphs): + * internals/internals.texi (Discussion -- Dialog Boxes): + * internals/internals.texi (Discussion -- Multilingual Issues): + * internals/internals.texi (Discussion -- Windows External Widget): + * internals/internals.texi (Discussion -- Packages): + * internals/internals.texi (Discussion -- Distribution Layout): + * internals/internals.texi (Old Future Work): + * internals/internals.texi (Old Future Work -- A Portable Unexec Replacement): + * internals/internals.texi (backtrace): New. + * internals/internals.texi (Old Future Work -- Indirect Buffers): + * internals/internals.texi (emacs-lisp): New. + * internals/internals.texi (Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X): + * internals/internals.texi (Newsgroups): New. + * internals/internals.texi (Old Future Work -- RTF Clipboard Support): + * internals/internals.texi (own-selection): New. + * internals/internals.texi (Old Future Work -- xemacs.org Mailing Address Changes): + * internals/internals.texi (COMMENT): New. + * internals/internals.texi (Old Future Work -- Lisp callbacks from critical areas of the C code): + * internals/internals.texi (Now): Removed. + * internals/internals.texi (Proof): Removed. + * internals/internals.texi (Note): Removed. + * internals/internals.texi (Date): New. + * internals/internals.texi (ben): Removed. + * internals/internals.texi (importance): New. + * internals/internals.texi (From): New. + Major work on internals manual. Rearranged many chapters so as to + lie in coherent divisions. + Add tons of stuff to Future Work, Old Future Work, Discussions. + Add lots of stuff to Mule section (Multilingual ...). + Remove index.texi, incorporate into internals.texi. + Section on early history and an introduction. + Section on XEmacs split. Lots of new MS Windows docs + Mostly recently: Windows-I18N docs. Lots if new I18N docs. + Loads of other stuff. + +2004-11-02 Ben Wing <ben@xemacs.org> + + * internals/index.texi: + Deleted. Incorporated into internals.texi. Having a separate + index file messes up texinfo-master-menu. + + * internals/internals.texi: + * internals/internals.texi (Top): + * internals/internals.texi (Introduction): + * internals/internals.texi (Authorship of XEmacs): + * internals/internals.texi (A History of Emacs): + * internals/internals.texi (Through Version 18): + * internals/internals.texi (Lucid Emacs): + * internals/internals.texi (GNU Emacs 19): + * internals/internals.texi (GNU Emacs 20): + * internals/internals.texi (XEmacs): + * internals/internals.texi (XEmacs From the Outside): + * internals/internals.texi (The Lisp Language): + * internals/internals.texi (XEmacs From the Perspective of Building): + * internals/internals.texi (The XEmacs Object System (Abstractly Speaking)): + * internals/internals.texi (How Lisp Objects Are Represented in C): + * internals/internals.texi (Major Textual Changes): + * internals/internals.texi (Great Integral Type Renaming): + * internals/internals.texi (Text/Char Type Renaming): + * internals/internals.texi (Rules When Writing New C Code): + * internals/internals.texi (A Reader's Guide to XEmacs Coding Conventions): + * internals/internals.texi (General Coding Rules): + * internals/internals.texi (Object-Oriented Techniques for C): + * internals/internals.texi (Writing Lisp Primitives): + * internals/internals.texi (Writing Good Comments): + * internals/internals.texi (Adding Global Lisp Variables): + * internals/internals.texi (Writing Macros): + * internals/internals.texi (Proper Use of Unsigned Types): + * internals/internals.texi (Techniques for XEmacs Developers): + * internals/internals.texi (Regression Testing XEmacs): + * internals/internals.texi (How to Regression-Test): + * internals/internals.texi (Modules for Regression Testing): + * internals/internals.texi (CVS Techniques): + * internals/internals.texi (Merging a Branch into the Trunk): + * internals/internals.texi (The Modules of XEmacs): + * internals/internals.texi (A Summary of the Various XEmacs Modules): + * internals/internals.texi (Low-Level Modules): + * internals/internals.texi (Basic Lisp Modules): + * internals/internals.texi (Modules for Standard Editing Operations): + * internals/internals.texi (Modules for Interfacing with the File System): + * internals/internals.texi (Modules for Other Aspects of the Lisp Interpreter and Object System): + * internals/internals.texi (Modules for Interfacing with the Operating System): + * internals/internals.texi (Allocation of Objects in XEmacs Lisp): + * internals/internals.texi (Introduction to Allocation): + * internals/internals.texi (Garbage Collection): + * internals/internals.texi (GCPROing): + * internals/internals.texi (Garbage Collection - Step by Step): + * internals/internals.texi (Invocation): + * internals/internals.texi (garbage_collect_1): + * internals/internals.texi (mark_object): + * internals/internals.texi (gc_sweep): + * internals/internals.texi (sweep_lcrecords_1): + * internals/internals.texi (compact_string_chars): + * internals/internals.texi (Integers and Characters): + * internals/internals.texi (Allocation from Frob Blocks): + * internals/internals.texi (lrecords): + * internals/internals.texi (Low-level allocation): + * internals/internals.texi (Cons): + * internals/internals.texi (Vector): + * internals/internals.texi (Symbol): + * internals/internals.texi (Marker): + * internals/internals.texi (String): + * internals/internals.texi (Dumping): + * internals/internals.texi (Dumping Justification): + * internals/internals.texi (Overview): + * internals/internals.texi (Data descriptions): + * internals/internals.texi (Dumping phase): + * internals/internals.texi (Object inventory): + * internals/internals.texi (Address allocation): + * internals/internals.texi (The header): + * internals/internals.texi (Data dumping): + * internals/internals.texi (Pointers dumping): + * internals/internals.texi (Reloading phase): + * internals/internals.texi (Remaining issues): + * internals/internals.texi (Events and the Event Loop): + * internals/internals.texi (Introduction to Events): + * internals/internals.texi (Main Loop): + * internals/internals.texi (Specifics of the Event Gathering Mechanism): + * internals/internals.texi (Specifics About the Emacs Event): + * internals/internals.texi (Event Queues): + * internals/internals.texi (Event Stream Callback Routines): + * internals/internals.texi (IMPORTANT): New. + * internals/internals.texi (Other Event Loop Functions): + * internals/internals.texi (Stream Pairs): + * internals/internals.texi (Converting Events): + * internals/internals.texi (Dispatching Events; The Command Builder): + * internals/internals.texi (Focus Handling): + * internals/internals.texi (Editor-Level Control Flow Modules): + * internals/internals.texi (Asynchronous Events; Quit Checking): + * internals/internals.texi (Control-G (Quit) Checking): + * internals/internals.texi (completely): New. + * internals/internals.texi (Profiling): + * internals/internals.texi (Exiting): + * internals/internals.texi (BEWARE): New. + * internals/internals.texi (Evaluation; Stack Frames; Bindings): + * internals/internals.texi (Evaluation): + * internals/internals.texi (Dynamic Binding; The specbinding Stack; Unwind-Protects): + * internals/internals.texi (Simple Special Forms): + * internals/internals.texi (Catch and Throw): + * internals/internals.texi (Introduction to Symbols): + * internals/internals.texi (Obarrays): + * internals/internals.texi (Symbol Values): + * internals/internals.texi (Buffers): + * internals/internals.texi (Introduction to Buffers): + * internals/internals.texi (Buffer Lists): + * internals/internals.texi (Markers and Extents): + * internals/internals.texi (The Buffer Object): + * internals/internals.texi (Text): + * internals/internals.texi (The Text in a Buffer): + * internals/internals.texi (Ibytes and Ichars): + * internals/internals.texi (Byte-Char Position Conversion): + * internals/internals.texi (Searching and Matching): + * internals/internals.texi (Multilingual Support): + * internals/internals.texi (Introduction to Multilingual Issues #1): + * internals/internals.texi (Introduction to Multilingual Issues #2): + * internals/internals.texi (Introduction to Multilingual Issues #3): + * internals/internals.texi (Introduction to Multilingual Issues #4): + * internals/internals.texi (Character Sets): + * internals/internals.texi (Encodings): + * internals/internals.texi (Japanese EUC (Extended Unix Code)): + * internals/internals.texi (JIS7): + * internals/internals.texi (Internal Mule Encodings): + * internals/internals.texi (Internal String Encoding): + * internals/internals.texi (Internal Character Encoding): + * internals/internals.texi (Byte/Character Types; Buffer Positions; Other Typedefs): + * internals/internals.texi (Byte Types): + * internals/internals.texi (Different Ways of Seeing Internal Text): + * internals/internals.texi (prefixes): New. + * internals/internals.texi (C): New. + * internals/internals.texi (U): New. + * internals/internals.texi (S): New. + * internals/internals.texi (Specifically): New. + * internals/internals.texi (Buffer Positions): + * internals/internals.texi (Other Typedefs): + * internals/internals.texi (Usage of the Various Representations): + * internals/internals.texi (Working With the Various Representations): + * internals/internals.texi (Internal Text API's): + * internals/internals.texi (Basic internal-format API's): + * internals/internals.texi (The DFC API): + * internals/internals.texi (The Eistring API): + * internals/internals.texi (Coding for Mule): + * internals/internals.texi (Character-Related Data Types): + * internals/internals.texi (Working With Character and Byte Positions): + * internals/internals.texi (Conversion to and from External Data): + * internals/internals.texi (General Guidelines for Writing Mule-Aware Code): + * internals/internals.texi (An Example of Mule-Aware Code): + * internals/internals.texi (Mule-izing Code): + * internals/internals.texi (CCL): + * internals/internals.texi (Modules for Internationalization): + * internals/internals.texi (The Lisp Reader and Compiler): + * internals/internals.texi (Lstreams): + * internals/internals.texi (Creating an Lstream): + * internals/internals.texi (Lstream Types): + * internals/internals.texi (Lstream Functions): + * internals/internals.texi (Lstream Methods): + * internals/internals.texi (Introduction to Consoles; Devices; Frames; Windows): + * internals/internals.texi (Point): + * internals/internals.texi (Window Hierarchy): + * internals/internals.texi (The Window Object): + * internals/internals.texi (Modules for the Basic Displayable Lisp Objects): + * internals/internals.texi (The Redisplay Mechanism): + * internals/internals.texi (Critical Redisplay Sections): + * internals/internals.texi (Line Start Cache): + * internals/internals.texi (Redisplay Piece by Piece): + * internals/internals.texi (Modules for the Redisplay Mechanism): + * internals/internals.texi (Modules for other Display-Related Lisp Objects): + * internals/internals.texi (Introduction to Extents): + * internals/internals.texi (Extent Ordering): + * internals/internals.texi (Format of the Extent Info): + * internals/internals.texi (Zero-Length Extents): + * internals/internals.texi (Mathematics of Extent Ordering): + * internals/internals.texi (Extent Fragments): + * internals/internals.texi (Faces): + * internals/internals.texi (Glyphs): + * internals/internals.texi (Specifiers): + * internals/internals.texi (Menus): + * internals/internals.texi (Subprocesses): + * internals/internals.texi (Interface to MS Windows): + * internals/internals.texi (Different kinds of Windows environments): + * internals/internals.texi (Windows Build Flags): + * internals/internals.texi (Windows I18N Introduction): + * internals/internals.texi (Modules for Interfacing with MS Windows): + * internals/internals.texi (Interface to the X Window System): + * internals/internals.texi (Generic Widget Interface): + * internals/internals.texi (Scrollbars): + * internals/internals.texi (Menubars): + * internals/internals.texi (Checkboxes and Radio Buttons): + * internals/internals.texi (Modules for Interfacing with X Windows): + * internals/internals.texi (Future Work): + * internals/internals.texi (Future Work -- Elisp Compatibility Package): + * internals/internals.texi (Future Work -- Drag-n-Drop): + * internals/internals.texi (Future Work -- Standard Interface for Enabling Extensions): + * internals/internals.texi (Future Work -- Better Initialization File Scheme): + * internals/internals.texi (Future Work -- Keyword Parameters): + * internals/internals.texi (Future Work -- Property Interface Changes): + * internals/internals.texi (Future Work -- Easier Toolbar Customization): + * internals/internals.texi (Future Work -- Toolbar Interface Changes): + * internals/internals.texi (Future Work -- Menu API Changes): + * internals/internals.texi (Future Work -- Removal of Misc-User Event Type): + * internals/internals.texi (Future Work -- Mouse Pointer): + * internals/internals.texi (Future Work -- Abstracted Mouse Pointer Interface): + * internals/internals.texi (Future Work -- Busy Pointer): + * internals/internals.texi (Future Work -- Extents): + * internals/internals.texi (Future Work -- Everything should obey duplicable extents): + * internals/internals.texi (Future Work -- Version Number and Development Tree Organization): + * internals/internals.texi (Future Work -- Improvements to the @code{xemacs.org} Website): + * internals/internals.texi (Future Work -- Keybinding Schemes): + * internals/internals.texi (Future Work -- Better Support for Windows Style Key Bindings): + * internals/internals.texi (Future Work -- Misc Key Binding Ideas): + * internals/internals.texi (Future Work -- Byte Code Snippets): + * internals/internals.texi (Future Work -- Autodetection): + * internals/internals.texi (Future Work -- Conversion Error Detection): + * internals/internals.texi (Future Work -- BIDI Support): + * internals/internals.texi (Future Work -- Localized Text/Messages): + * internals/internals.texi (freeze): New. + * internals/internals.texi (fail-safe): New. + * internals/internals.texi (like): New. + * internals/internals.texi (user): New. + * internals/internals.texi (ben): New. + * internals/internals.texi ('type): New. + * internals/internals.texi (NOTE): New. + * internals/internals.texi (ILLEGIBLE): New. + * internals/internals.texi (language): New. + * internals/internals.texi (preprocessing): New. + * internals/internals.texi (Subject): New. + * internals/internals.texi (http): New. + * internals/internals.texi (Now): Removed. + * internals/internals.texi (wrong): New. + * internals/internals.texi (Proof): Removed. + + Add bunches and bunches and bunches and bunches of stuff, taken + from documentation floating around in various places -- text.c, + file-coding.c, other .c and .h files, stuff that I wrote up for an + old XEmacs contract, proposals written up in the process of an + e-mail discussion, etc. Fix up some mistakes, esp. in CCL. Extra + crap from CCL, duplicated with Lispref, removed. Sections on Old + Future Work and Future Work Discussion added. + + Bunches of other work. Add bunches of documentation taken from the + source code. Fixup various places to use @strong{}, @code{}, + @file{}. Create new Text chapter, split off from Buffers and + Textual Representation. Create new chapter for MS Windows, mostly + written from scratch. Consolidate all Mule info under + "Multilingual Support". Break up chapter on modules and move some + parts to the sections discussing the modules, for consolidation + purposes. Add a big cross-reference table for all the modules to + where they're discussed (or not). New chapter Asynchronous + Events; Quit Checking. (Taken from various parts of the code.) New + Introduction. New section on Focus Handling (from the code). + + NOTE that in the process, I discovered that we essentially have + FOUR redundant introductions to Mule issues! Someone really needs + to go through and clean them up and integrate them (sjt?). + +2003-07-18 Alexey Mahotkin <alexm@hsys.msk.ru> + + * lispref/windows.texi (Basic Windows): Fix typo. + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/man/Makefile' 'xemacs-21.5.19/man/Makefile' Index: ./man/Makefile --- ./man/Makefile Fri Oct 10 21:39:27 2003 +++ ./man/Makefile Tue Feb 1 05:08:47 2005 @@ -22,14 +22,16 @@ SHELL = /bin/sh MAKEINFO = makeinfo TEXI2DVI = texi2dvi -TEXI2HTML = texi2html -verbose -split chapter +TEXI2HTML = texi2html -verbose -subdir $(HTMLDIR) +TEXI2HTML_SPLIT = $(TEXI2HTML) -split chapter RM = rm -f +CP = cp .SUFFIXES: .SUFFIXES: .html .info .texi .dvi .pdf -RECURSIVE_MAKE = $(MAKE) $(MFLAGS) MAKEINFO='$(MAKEINFO)' TEXI2DVI='$(TEXI2DVI)' +RECURSIVE_MAKE_ARGS = $(MFLAGS) MAKEINFO='$(MAKEINFO)' TEXI2DVI='$(TEXI2DVI)' all : info @@ -37,8 +39,10 @@ INFODIR = ../info HTMLDIR = ../html +PHOTODIR = ../etc/photos info_files = \ + $(INFODIR)/beta.info \ $(INFODIR)/cl.info \ $(INFODIR)/custom.info \ $(INFODIR)/emodules.info \ @@ -56,6 +60,7 @@ $(INFODIR)/xemacs-faq.info html_files = \ + $(HTMLDIR)/beta.html \ $(HTMLDIR)/cl.html \ $(HTMLDIR)/custom.html \ $(HTMLDIR)/emodules.html \ @@ -73,6 +78,7 @@ $(HTMLDIR)/xemacs-faq.html dvi_files = \ + beta.dvi \ cl.dvi \ custom.dvi \ emodules.dvi \ @@ -90,6 +96,7 @@ xemacs-faq.dvi pdf_files = \ + beta.pdf \ cl.pdf \ custom.pdf \ emodules.pdf \ @@ -234,6 +241,9 @@ new-users-guide/search.texi \ new-users-guide/xmenu.texi +$(INFODIR)/beta.info : beta.texi + $(MAKEINFO) -o $(INFODIR)/beta.info beta.texi + $(INFODIR)/cl.info : cl.texi $(MAKEINFO) -o $(INFODIR)/cl.info cl.texi @@ -337,51 +347,63 @@ ############################################################################ +$(HTMLDIR)/beta.html : beta.texi + $(TEXI2HTML) beta.texi + $(HTMLDIR)/cl.html : cl.texi - $(TEXI2HTML) -subdir $(HTMLDIR) cl.texi + $(TEXI2HTML_SPLIT) cl.texi $(HTMLDIR)/custom.html : custom.texi - $(TEXI2HTML) -subdir $(HTMLDIR) custom.texi + $(TEXI2HTML_SPLIT) custom.texi $(HTMLDIR)/emodules.html : emodules.texi - $(TEXI2HTML) -subdir $(HTMLDIR) emodules.texi + $(TEXI2HTML_SPLIT) emodules.texi $(HTMLDIR)/external-widget.html : external-widget.texi - $(TEXI2HTML) -subdir $(HTMLDIR) external-widget.texi + $(TEXI2HTML_SPLIT) external-widget.texi $(HTMLDIR)/info.html : info.texi - $(TEXI2HTML) -subdir $(HTMLDIR) info.texi + $(TEXI2HTML_SPLIT) info.texi $(HTMLDIR)/standards.html : standards.texi - $(TEXI2HTML) -subdir $(HTMLDIR) standards.texi + $(TEXI2HTML_SPLIT) standards.texi $(HTMLDIR)/term.html : term.texi - $(TEXI2HTML) -subdir $(HTMLDIR) term.texi + $(TEXI2HTML_SPLIT) term.texi $(HTMLDIR)/termcap.html : termcap.texi - $(TEXI2HTML) -subdir $(HTMLDIR) termcap.texi + $(TEXI2HTML_SPLIT) termcap.texi $(HTMLDIR)/texinfo.html : texinfo.texi - $(TEXI2HTML) -subdir $(HTMLDIR) texinfo.texi + $(TEXI2HTML_SPLIT) texinfo.texi $(HTMLDIR)/widget.html : widget.texi - $(TEXI2HTML) -subdir $(HTMLDIR) widget.texi + $(TEXI2HTML_SPLIT) widget.texi $(HTMLDIR)/xemacs-faq.html : xemacs-faq.texi - $(TEXI2HTML) -top_file xemacs-faq_1.html -subdir $(HTMLDIR) xemacs-faq.texi + $(TEXI2HTML) xemacs-faq.texi + $(TEXI2HTML_SPLIT) -top_file xemacs-faq_1.html xemacs-faq.texi + $(CP) $(PHOTODIR)/ben.png $(HTMLDIR) + $(CP) $(PHOTODIR)/cthomp.png $(HTMLDIR) + $(CP) $(PHOTODIR)/hniksic.png $(HTMLDIR) + $(CP) $(PHOTODIR)/jwz.png $(HTMLDIR) + $(CP) $(PHOTODIR)/martin.png $(HTMLDIR) + $(CP) $(PHOTODIR)/mly.png $(HTMLDIR) + $(CP) $(PHOTODIR)/piper.png $(HTMLDIR) + $(CP) $(PHOTODIR)/slb.png $(HTMLDIR) # Manuals with their own subdirectory $(HTMLDIR)/xemacs.html : $(xemacs-srcs) - $(TEXI2HTML) -subdir $(HTMLDIR) xemacs/xemacs.texi + $(TEXI2HTML_SPLIT) xemacs/xemacs.texi $(HTMLDIR)/lispref.html : $(lispref-srcs) - $(TEXI2HTML) -subdir $(HTMLDIR) lispref/lispref.texi + $(TEXI2HTML_SPLIT) lispref/lispref.texi $(HTMLDIR)/internals.html : $(internals-srcs) - $(TEXI2HTML) -subdir $(HTMLDIR) internals/internals.texi + $(TEXI2HTML_SPLIT) internals/internals.texi $(HTMLDIR)/new-users-guide.html : $(new-users-guide-srcs) - $(TEXI2HTML) -subdir $(HTMLDIR) new-users-guide/new-users-guide.texi + $(TEXI2HTML_SPLIT) new-users-guide/new-users-guide.texi xemacs : $(HTMLDIR)/xemacs.html lispref : $(HTMLDIR)/lispref.html diff --text -u /dev/null 'xemacs-21.5.19/man/beta.texi' Index: ./man/beta.texi --- ./man/beta.texi Thu Jan 1 09:00:00 1970 +++ ./man/beta.texi Thu Feb 3 15:14:40 2005 @@ -0,0 +1,958 @@ +\input texinfo @c -*-texinfo-*- + +@c This file is in Texinfo format. +@c If for some reason you do not have the formatted version available, +@c this file is more or less readable as plain text. +@c Skip to the line beginning "@node Introduction". + +@c %**start of header +@setfilename ../info/beta.info +@settitle Info on beta versions of XEmacs +@direntry +* Beta: (beta). Info on beta versions of XEmacs. +@end direntry +@c footnotestyle separate +@c paragraphindent 2 +@c %**end of header + +@ifinfo +This file describes info relevant to beta versions of XEmacs. + +Copyright @copyright{} 2005 Ben Wing. +Copyright @copyright{} 2005 Free Software Foundation, Inc. + +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. +@end ifinfo + +@c Combine indices. +@syncodeindex fn cp +@syncodeindex vr cp +@syncodeindex ky cp +@syncodeindex pg cp +@syncodeindex tp cp + +@setchapternewpage odd +@finalout + +@titlepage +@title Info on beta versions of XEmacs + +@author XEmacs Development Team +@page +@vskip 0pt plus 1fill + +@noindent +Copyright @copyright{} 2005 Ben Wing. @* + +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. +@end titlepage +@page + +@ifinfo +@node Top, Introduction, (dir), (dir) +This Info file describes info relevant to beta versions of XEmacs. +@menu +* Introduction:: +* Compiling Beta XEmacs:: +* Packages:: +* Improving XEmacs:: +* Index:: + +@detailmenu + --- The Detailed Node Listing --- + +Introduction + +* Mailing Lists:: +* Beta Release Schedule:: +* Reporting Problems:: +* Getting the Source:: + +Mailing Lists + +* XEmacs Beta Mailing List:: +* XEmacs Patches Mailing List:: +* XEmacs Design Mailing List:: +* List Administrivia:: +* Managing your subscription via the Web:: +* Subscribing by e-mail:: +* Unsubscribing by e-mail:: + +Compiling Beta XEmacs + +* Building an XEmacs from patches:: +* Building XEmacs from a full distribution:: + +Packages + +* Binary package installation:: +* Manual procedures for package management:: +* Building XEmacs and XEmacs packages from scratch:: + +Improving XEmacs + +* Creating patches for submission:: +* Large contributions:: + +Creating patches for submission + +* Patch discussion etiquette:: + +Large contributions + +* Updates to existing packages:: +* New packages:: +* Syncing with GNU Emacs:: + +@end detailmenu +@end menu + +@end ifinfo + +@node Introduction, Compiling Beta XEmacs, Top, Top +@chapter Introduction + +You are running a potentially unstable version of XEmacs. Please do +not report problems with Beta XEmacs to comp.emacs.xemacs. Report +them to @uref{mailto:xemacs-beta@@xemacs.org}, preferably with +@kbd{M-x report-xemacs-bug RET}. + +@menu +* Mailing Lists:: +* Beta Release Schedule:: +* Reporting Problems:: +* Getting the Source:: +@end menu + +@node Mailing Lists, Beta Release Schedule, Introduction, Introduction +@section Mailing Lists + +@menu +* XEmacs Beta Mailing List:: +* XEmacs Patches Mailing List:: +* XEmacs Design Mailing List:: +* List Administrivia:: +* Managing your subscription via the Web:: +* Subscribing by e-mail:: +* Unsubscribing by e-mail:: +@end menu + +@node XEmacs Beta Mailing List, XEmacs Patches Mailing List, Mailing Lists, Mailing Lists +@subsection XEmacs Beta Mailing List + +If you are not subscribed to the XEmacs beta list you should be. +Currently all discussion of development issues, including bug reports +and coding discussion, takes place on the XEmacs Beta mailing list. +Only patches and administrative actions regarding patches are sent +elsewhere (to the XEmacs Patches list). + +@node XEmacs Patches Mailing List, XEmacs Design Mailing List, XEmacs Beta Mailing List, Mailing Lists +@subsection XEmacs Patches Mailing List + +XEmacs Patches records proposed changes to XEmacs, and their +disposition. It is open subscription, and all patches that are +seriously proposed for inclusion in XEmacs should be posted here. You +can follow progress of your patch by subscribing to the mailing list +or in the archives. + +Besides patches, only actions by members of the XEmacs Review Board +should be posted to this list. All discussion should be redirected to +XEmacs Beta or XEmacs Design. + +@node XEmacs Design Mailing List, List Administrivia, XEmacs Patches Mailing List, Mailing Lists +@subsection XEmacs Design Mailing List + +XEmacs Design is for design discussions such as adding major features +or whole modules, or reimplementation of existing functions, to XEmacs. + +@node List Administrivia, Managing your subscription via the Web, XEmacs Design Mailing List, Mailing Lists +@subsection List Administrivia + +In the descriptions below, the word LIST (all uppercase) is a +variable. Substitute "beta", "design", or "patches" as appropriate +(to get "xemacs-beta" as the mailbox for the XEmacs Beta mailing list, +or @uref{http://www.xemacs.org/Lists/#xemacs-beta} for its URL). + +The XEmacs mailing lists are managed by the Mailman mailing list package, +and the usual Mailman commands work. Do not send mailing list requests to +the main address (@uref{mailto:xemacs-LIST@@xemacs.org}), always send them +to @uref{mailto:xemacs-LIST-request@@xemacs.org}. If you have problems with +the list itself, they should be brought to the attention of the XEmacs +Mailing List manager @uref{mailto:list-manager@@xemacs.org} (the same +mailbox, "list-manager", for all lists). All public mailing lists have +searchable archives. The URL is + + @uref{http://list-archive.xemacs.org/xemacs-LIST} + +Note that the xemacs-LIST-admin address is used internally by the +Mailman software; it is NOT a synonym for xemacs-LIST-request. + +@node Managing your subscription via the Web, Subscribing by e-mail, List Administrivia, Mailing Lists +@subsection Managing your subscription via the Web + +Subscription, unsubscription, and options (such as digests and +temporarily suspending delivery) can be accomplished via the web +interface at @uref{http://www.xemacs.org/Lists/#xemacs-LIST}. + +@node Subscribing by e-mail, Unsubscribing by e-mail, Managing your subscription via the Web, Mailing Lists +@subsection Subscribing by e-mail + +Send an email message to @uref{mailto:xemacs-LIST-request@@xemacs.org} with +@samp{subscribe} (without the quotes) as the BODY of the message. + +@node Unsubscribing by e-mail, , Subscribing by e-mail, Mailing Lists +@subsection Unsubscribing by e-mail + +Send an email message to @uref{mailto:xemacs-LIST-request@@xemacs.org} with +@samp{unsubscribe} (without the quotes) as the BODY of the message. + +@node Beta Release Schedule, Reporting Problems, Mailing Lists, Introduction +@section Beta Release Schedule + +We would like to achieve a weekly or fortnightly release cycle (you +know the Open Source model: release early, release often), and in a +perfect world that would indeed be the case. There are at least three +things that often get in the way of that goal: 1) The Release Manager +has a life outside of XEmacs (hard to believe, I know, but true), +2) we like to make releases that will build (at least on the Release +Manager's box), and 3) Murphy likes to throw a spanner in the works +right when you least expect it (Murphy's Law: Whatever can go wrong, +will go wrong). + +If you'd like to keep right up to date and ride the bleeding edge, use +CVS (see @uref{http://www.xemacs.org/Develop/cvsaccess.html}). If you +can't use CVS for some reason and must use FTP, please let us know. +it will make it more likely that we release betas more often. + + +@node Reporting Problems, Getting the Source, Beta Release Schedule, Introduction +@section Reporting Problems + +The best way to get problems fixed in XEmacs is to submit good problem +reports, @kbd{M-x report-xemacs-bug RET} will help you do this (assuming +you have a usable XEmacs). Since this is beta software, problems are +certain to exist. Please read through all of part II of the XEmacs +FAQ for an overview of problem reporting. Other items which are most +important are: + +@enumerate +@item +Do not submit C stack backtraces without line numbers. Since it +is possible to compile optimized with debug information with GCC +it is never a good idea to compile XEmacs without the -g flag. +XEmacs runs on a variety of platforms, and often it is not +possible to recreate problems which afflict a specific platform. +The line numbers in the C stack backtrace help isolate where the +problem is actually occurring. + +@item +Attempt to recreate the problem starting with an invocation of +XEmacs with @code{xemacs -no-autoloads}. Quite often, problems are +due to package interdependencies, and the like. An actual bug +in XEmacs should be reproducible in a default configuration +without loading any special packages (or the one or two specific +packages that cause the bug to appear). If you have trouble +getting anything to work at all with the above invocation, use +@code{xemacs -vanilla} instead. If you need to load your user init +file or the site file to get the problem to occur, then it has +something to do with them, and you should try to isolate the +issue in those files. + +@item +A picture can be worth a thousand words. When reporting an +unusual display, it is generally best to capture the problem in a +screen dump and include that with the problem report. The easiest +way to get a screen dump is to use the xv program and its grab +function. Save the image as a GIF to keep bandwidth requirements +down without loss of information. MIME is the preferred method +for making the image attachments. +@end enumerate + +@node Getting the Source, , Reporting Problems, Introduction +@section Getting the Source + +In addition to the normal tar distribution, XEmacs source is now +available via CVS. Please see + + @uref{http://www.xemacs.org/Develop/cvsaccess.html} + +@node Compiling Beta XEmacs, Packages, Introduction, Top +@chapter Compiling Beta XEmacs + +@menu +* Building an XEmacs from patches:: +* Building XEmacs from a full distribution:: +@end menu + +@node Building an XEmacs from patches, Building XEmacs from a full distribution, Compiling Beta XEmacs, Compiling Beta XEmacs +@section Building an XEmacs from patches + +All beta releases of XEmacs are included with patches from the previous +version in an attempt to keep bandwidth requirements down. Patches +should be applied with the GNU patch program in something like the +following. Let's say you're upgrading XEmacs 21.5-beta9 to XEmacs +21.5-beta10 and you have a full unmodified XEmacs 21.5-beta9 source +tree to work with. Change to the top level directory and issue the +shell command: + +@example +$ gunzip -c /tmp/xemacs-21.5.9-21.5.10.patch.gz | patch -p1 +@end example + +After patching, check to see that no patches were missed by doing + +@example +$ find . -name \*.rej -print +@end example + +Any rejections should be treated as serious problems to be resolved +before building XEmacs. + +After seeing that there were no rejections, issue the commands + +@example +$ ./config.status --recheck +$ make beta > ./beta.err 2>&1 +$ make check > ./xemacs-make-check.err 2>&1 +@end example + +Redirect the output from make to those files because you'll use them +later when you send off a build report with @kbd{M-x build-report RET} + +@node Building XEmacs from a full distribution, , Building an XEmacs from patches, Compiling Beta XEmacs +@section Building XEmacs from a full distribution + +@enumerate +@item +Locate a convenient place where you have at least 100MB of free space +and issue the command + +@example +$ gunzip -c /tmp/xemacs-21.5.10.tar.gz | tar xvf - +@end example + +(or simply @code{tar zxvf /tmp/xemacs-21.5.10.tar.gz} if you use GNU tar). + +@item +cd to the top level directory and issue an appropriate configure +command. + +@item +Run @code{configure}. If you are new, just consider running it with no +options, to see if you can get a succesful build. When you are more +experienced, you should put various flags in. Here is what we suggest: + +@enumerate +@item +It's a good idea to use + +@example +--extra-verbose +--debug +--memory-usage-stats +--error-checking=all +@end example + +These turn on extra debugging info and checks. The last one in particular +will add a great deal of extra error-checking -- which will slow your XEmacs +down somewhat but is likely to catch bugs much sooner and make your bug +reports much more useful. + +@item +You should also strongly consider + +@example +--with-mule +--use-pkcc +--pdump +--with-clash-detection +--with-wmcommand +--with-xfs +@end example + +These turn on optional features, which can always use testing. + +@item +If you have gcc, consider using + +@example +--compiler=gcc +--xemacs-compiler=g++ +@end example + +This will compile XEmacs using g++, which will turn on a lot of additional +error-checking. + +@item +If your packages are not installed under /usr/local, you should add a +line like + +@example +--package-path=~/.xemacs::/xemacs/site-packages:/xemacs/xemacs-packages:/xemacs/mule-packages +@end example + +@item +If you want to build multiple configurations from the same source +tree, make separate build directories for each configuration, run +@code{configure} from the top level of these (currently empty) +directories and use an option like + +@example +--srcdir=/xemacs/source-tree +@end example + +(or wherever your source tree is). This will magically create symlinks and +populate your build directory. + +@item +Use --site-prefixes (or --site-includes and --site-libraries) if you have +some packages that XEmacs can compile with that are located in an unusual +place. For example: + +@example +--site-prefixes=/usr/local/pgsql:/usr/local/BerkeleyDB.4.1 +@end example + +@item +Depending on your build environment, consuder setting or not setting +options for menubars, scrollbars, window systems, native sound, etc. If +you're not sure, leave them out and let configure do the auto-detection. +(If you get bugs compiling GTK, use @code{--with-gtk=no --with-gnome=no}.) + +Part of the configure output is a summary that looks something +like the following. (this summary is also available as the file +'Installation' in the top directory of your build tree, and via +the command @kbd{M-x describe-installation RET}). + +@example +uname -a: Linux eicq 2.4.20 #1 Wed Dec 18 02:14:29 EST 2002 i586 unknown + +./configure '--extra-verbose' '--site-prefixes=/usr/local/pgsql:/usr/local/BerkeleyDB.4.1' '--dynamic=yes' '--with-gtk=no' '--with-gnome=no' '--with-toolbars' '--with-wmcommand' '--with-athena=next' '--with-menubars=lucid' '--with-scrollbars=athena' '--with-dialogs=athena' '--with-widgets=athena' '--with-gif' '--with-sound=native,noesd' '--with-site-lisp=no' '--with-site-modules' '--pdump' '--with-mule' '--with-xfs' '--debug' '--error-checking=all' '--memory-usage-stats' '--use-kkcc' '--with-clash-detection' + + +XEmacs 21.5-b10 "burdock" (+CVS-20030131) configured for `i586-pc-linux'. + + +Compilation / Installation: + Source code location: /usr/local/src/xemacs + Installation prefix: /usr/local + Additional prefixes: /usr/local/pgsql /usr/local/BerkeleyDB.4.1 + Operating system description file: `s/linux.h' + Machine description file: `m/intel386.h' + Compiler: gcc -Wall -Wno-switch -Winline -Wmissing-prototypes -Wsign-compare -Wundef -Wstrict-prototypes -Wshadow -Wmissing-declarations -O1 -ggdb3 -Wall -Wchar-subscripts -Wunused -Wundef -Wshadow -Wsign-compare -Wmissing-declarations -march=k6 + Relocating allocator for buffers: no + GNU version of malloc: yes + - Using Doug Lea's new malloc from the GNU C Library. + +Window System: + Compiling in support for the X window system: + - X Windows headers location: /usr/X11/include + - X Windows libraries location: /usr/X11/lib + - Handling WM_COMMAND properly. + Compiling in support for the Athena widget set: + - Athena headers location: X11/neXtaw + - Athena library to link: neXtaw + Using Lucid menubars. + Using Athena scrollbars. + Using Athena dialog boxes. + Using Athena native widgets. + +TTY: + Compiling in support for ncurses. + Compiling in support for GPM (General Purpose Mouse). + +Images: + Compiling in support for GIF images (builtin). + Compiling in support for XPM images. + Compiling in support for PNG images. + Compiling in support for JPEG images. + Compiling in support for TIFF images. + Compiling in support for X-Face message headers. + +Sound: + Compiling in support for sound (native). + +Databases: + Compiling in support for Berkeley database. + Compiling in support for PostgreSQL. + - Using PostgreSQL header file: libpq-fe.h + - Using PostgreSQL V7 bindings. + +Internationalization: + Compiling in support for Mule (multi-lingual Emacs). + Compiling in support for XIM (X11R5+ I18N input method). + - Using raw Xlib to provide XIM support. + - Using XFontSet to provide bilingual menubar. + +Mail: + Compiling in support for "dot-locking" mail spool file locking method. + +Other Features: + Inhibiting IPv6 canonicalization at startup. + Compiling in support for dynamic shared object modules. + Using the new GC algorithms. + Using the new portable dumper. + Compiling in support for extra debugging code. + WARNING: WARNING: Compiling in support for runtime error checking. + WARNING: XEmacs will run noticeably more slowly as a result. + WARNING: Error checking is on by default for XEmacs beta releases. + WARNING: +@end example +@end enumerate + + +@item +Then... + +@example +$ make > ./beta.err 2>&1 +$ make check > ./xemacs-make-check.err 2>&1 +@end example + +...and you should have a working XEmacs. + +@item +After you have verified that you have a functional editor, fire up +your favorite mail program and send a build report to +@uref{mailto:xemacs-buildreports@@xemacs.org}. + +Preferably this is best done from XEmacs, following these simple steps: + +@enumerate +@kbd{M-x customize-group RET build-report RET} +@kbd{M-x build-report RET} +@end enumerate + +See also +@uref{http://www.xemacs.org/Releases/Public-21.2/tester.html#reporting} + +If you create the report manually by other means, here is what the +build report should include: + +@enumerate +@item +Your hardware configuration (OS version, etc.) + +@item +Version numbers of software in use (X11 version, system library +versions if appropriate, graphics library versions if appropriate). +If you're on a system like Linux, include all the version numbers +you can because chances are it makes a difference. + +@item +The options given to configure + +@item +The configuration report illustrated above + +For convenience all of the above items are placed in a file called +`Installation' in the top level build directory. They are also +available by performing @kbd{M-x describe-installation} inside XEmacs. + +@item +Any other unusual items you feel should be brought to the attention +of the developers. +@end enumerate +@end enumerate + +@node Packages, Improving XEmacs, Compiling Beta XEmacs, Top +@chapter Packages + +[Note: these instructions have been partly updated, but not carefully +reviewed in some time. Caveat tester.] + +Starting with XEmacs 21.1, much of the functionality of XEmacs has +been unbundled into "the packages." For more information about the +package system, see the Info nodes on Packages (in the XEmacs User +Manual) and on Packaging (in the Lisp Reference). + +When bootstrapping XEmacs, you may need to manually install some +packages (at least xemacs-base and efs). These packages are available +by FTP at @uref{ftp://ftp.xemacs.org/pub/xemacs/packages/}. + +@menu +* Binary package installation:: +* Manual procedures for package management:: +* Building XEmacs and XEmacs packages from scratch:: +@end menu + +@node Binary package installation, Manual procedures for package management, Packages, Packages +@section Binary package installation + +Prerequisite: XEmacs 21.0-b1. + +Binary packages are complete entities that can be untarred at the top +level of an XEmacs package hierarchy and work at runtime. To install files +in this directory, run the command @kbd{M-x package-admin-add-binary-package} +and fill in appropriate values to the prompts. + +@node Manual procedures for package management, Building XEmacs and XEmacs packages from scratch, Binary package installation, Packages +@section Manual procedures for package management + +Prerequisite: XEmacs 21.0 + +When adding and deleting files from a lisp directory the +auto-autoloads.el (global symbols) and custom-load.el (Customization +groups) must be kept in synch. Assuming one is manipulating a +directory called `lisp-utils', the command to rebuild the +auto-autoloads.el file is: + +@example +xemacs -vanilla -batch \ + -eval \("setq autoload-package-name \"lisp-utils\""\) \ + -f batch-update-directory lisp-utils +@end example + +The command to rebuild the custom-load.el file is: + +@example +xemacs -vanilla -batch -f Custom-make-dependencies lisp-utils +@end example + +To byte-compile both of these files the command is: + +@example +xemacs -vanilla -batch -f batch-byte-compile \ + lisp-utils/auto-autoloads.el lisp-utils/custom-load.el +@end example + +Of course, being a beta tester, you'd be aware that it is much easier +to manage your XEmacs packages with PUI. + +@node Building XEmacs and XEmacs packages from scratch, , Manual procedures for package management, Packages +@section Building XEmacs and XEmacs packages from scratch + +To build everything completely from scratch isn't hard, just time +consuming. + +@subheading Step 1 - grab the sources (core and packages) + +@example +$ cvs -d :pserver:cvs@@cvs.xemacs.org:/pack/xemacscvs login + [password: "cvs" (sans quotes)] + +$ cvs -d :pserver:cvs@@cvs.xemacs.org:/pack/xemacscvs co -d xemacs-21.5 xemacs + +$ cvs -d :pserver:cvs@@cvs.xemacs.org:/pack/xemacscvs co packages +@end example + +@subheading Step 2 - build XEmacs + +@example +$ cd xemacs-21.5 +$ ./configure [options...] +$ make > ./beta.err 2>&1 +$ make check > ./xemacs-make-check.err 2>&1 +@end example + +And optionally: + +@example +$ make install > ./xemacs-make-install.err 2>&1 +@end example + +@subheading Step 3 - build and install the packages + +@example +$ cd packages +$ cp Local.rules.template Local.rules +@end example + +Then edit Local.rules to suit your needs/environment +(@pxref{Local.rules file,,, xemacs, XEmacs User's Manual}) for details +about this file. + +And then: + +@example +$ make install +@end example + +@node Improving XEmacs, Index, Packages, Top +@chapter Improving XEmacs + +@menu +* Creating patches for submission:: +* Large contributions:: +@end menu + +@node Creating patches for submission, Large contributions, Improving XEmacs, Improving XEmacs +@section Creating patches for submission + +All patches to XEmacs that are seriously proposed for inclusion (eg, +bug fixes) should be mailed to @uref{mailto:xemacs-patches@@xemacs.org}. Each +patch will be reviewed by the patches review board, and will be +acknowledged and added to the distribution, or rejected with an +explanation. Progress of the patch is tracked on the XEmacs Patches +mailing list, which is open subscription. (If a patch is simply +intended to facilitate discussion, "I mean something that works like +this but this is really rough", a Cc to XEmacs Patches is optional, +but doesn't hurt.) + +Patches to XEmacs Lisp packages should be sent to the maintainer of +the package. If the maintainer is listed as `XEmacs Development Team' +patches should be sent to @uref{mailto:xemacs-patches@@xemacs.org}. + +Emailed patches should preferably be sent in MIME format and quoted +printable encoding (if necessary). + +The simplest way to create well-formed patches is to use CVS and +Didier Verna's Patcher library (available as patcher.el in the +xemacs-devel package). Patcher is new and requires some setup, but +most of the core developers are now using it for their own patches. +Patcher also can be configured to create patches for several projects, +and recognize the project from the directory it is invoked in. This +makes it a useful general tool (as long as XEmacs-style patches are +accepted at your other projects, which is likely since they conform to +the GNU standards). + +When making patches by hand, please use the `-u' option, or if your +diff doesn't support it, `-c'. Using ordinary (context-free) diffs +are notoriously prone to error, since line numbers tend to change when +others make changes to the same source file. + +An example of the `diff' usage: + +@example +$ diff -u OLDFILE NEWFILE +@end example + +-or- + +@example +$ diff -c OLDFILE NEWFILE +@end example + +Also, it is helpful if you create the patch in the top level of the +XEmacs source directory: + +@example +$ cp -p lwlib/xlwmenu.c lwlib/xlwmenu.c.orig + hack, hack, hack.... +$ diff -u lwlib/xlwmenu.c.orig lwlib/xlwmenu.c +@end example + +Also note that if you cut & paste from an xterm to an XEmacs mail +buffer you will probably lose due to tab expansion. The best thing to +do is to use an XEmacs shell buffer to run the diff commands, or ... +@kbd{M-x cd} to the appropriate directory, and issue the command +@kbd{C-u M-!} from within XEmacs. + +Patches should be as single-minded as possible. Mammoth patches can +be very difficult to place into the right slot. They are much easier +to deal with when broken down into functional or conceptual chunks. +The patches submitted by Kyle Jones and Hrvoje Niksic are stellar +examples of how to "Do The Right Thing". + +Each patch should be accompanied by an update to the appropriate +ChangeLog file. Guidelines for writing ChangeLog entries is governed +by the GNU coding standards. Please see +@uref{http://www.gnu.org/prep/standards_toc.html} [Change Logs section] +for details. + +Do not submit context diffs (either -c or -u) of ChangeLogs. Because +of the "stack" nature of ChangeLogs (new entries are always pushed on +the top), context diffs will fail to apply more often than they +succeed. Simply cutting and pasting the entry from an Emacs buffer to +the mail buffer (beware of tab expansion!) is probably easiest. The +Patcher library also will set up your ChangeLogs for you, and copy +them to the mail. Context-less unified diffs (-U 0) are also +acceptable. + +@menu +* Patch discussion etiquette:: +@end menu + +@node Patch discussion etiquette, , Creating patches for submission, Creating patches for submission +@subsection Patch discussion etiquette + +If you intend a patch for _application_ to the sources as is, _always_ +post it to xemacs-patches, even if there are minor points you would +like to have discussed by others. Not doing so will resulting in +patches getting "lost". If you expect that the patch will not be +acceptable, but are using it to stimulate discussion, then don't post +to xemacs-patches. Intermediate cases are up to your judgment; +unless you're sure you'll follow up with a "real" patch, better to err +on the side of posting to xemacs-patches. + +Discussion of the _content_ of the patch (ie responses to reviewer +comments beyond "that's right, ok, I'll do it your way") should _always_ +be posted to xemacs-beta or to xemacs-design. If you're not sure +which is more appropriate, send it to xemacs-beta. That is the most +widely read channel. + +If discussion results in a bright idea and you come up with a new +patch, normally you should post it to both mailing lists. The people +discussing on XEmacs Beta will want to know the outcome of the thread, +and you need to submit to XEmacs Patches as the "list of record." + +If the old patch has been applied to CVS, then just submit the new one +as usual. If it has not been applied, then it is best to submit a new +patch against CVS. If possible do this as a reply to the original +patch post, or something following it in the thread. (The point is to +get the original patch post's Message-ID in your References header.) +In this case, also use the keyword SUPERSEDES in the Subject header to +indicate that the old patch is no longer valid, and that this one +replaces it. + +These rules will result in a fair number of cross posts, but we don't +yet have a better way to handle that. + +Note: Developers should never post to xemacs-patches unless there is a +patch in the post. We plan to enforce this with an automatic filter. + +The exceptions are administrative. If you have commit authorization, +then post a short COMMIT notice to xemacs-patches when you commit to +CVS. Members of the Review Board will also post short notices of +administrative action (APPROVE, VETO, QUERY, etc) to xemacs-patches. + +@node Large contributions, , Creating patches for submission, Improving XEmacs +@section Large contributions + +Perhaps you have a whole new mode, or a major synchronization with +upstream for a neglected package, or a synchronization with GNU Emacs +you would like to contribute. We welcome such contributions, but they +are likely to be relatively controversial, generate more comments and +requests for revision, and take longer to integrate. Please be +patient with the process. + +@menu +* Updates to existing packages:: +* New packages:: +* Syncing with GNU Emacs:: +@end menu + +@node Updates to existing packages, New packages, Large contributions, Large contributions +@subsection Updates to existing packages + +If a package has gotten a bit out of date, or even started to bitrot, +we welcome patches to synchronize it with upstream/GNU Emacs versions. +Most packages end up varying somewhat from their GNU origins. See +"Syncing with GNU Emacs" for hints. Note that if you do a reasonably +large amount of syncing with GNU Emacs, you should log this in the +file itself as well as in the ChangeLog. + +If the package is important to you, please consider becoming the +maintainer. (See "New packages", below.) + +@node New packages, Syncing with GNU Emacs, Updates to existing packages, Large contributions +@subsection New packages + +If you have a new mode or other large addition that does not require +changes to the core, please consider submitting it as a package, and +becoming the maintainer. You get direct commit privileges to the +repository for your package, "approval" privileges for your own +patches as well as third party patches to your package, and some +degree of veto power over patches you don't like. In return, you are +expected to maintain friendly liaison with the upstream developer (if +you aren't the upstream developer), keep watch on the XEmacs Patches +list for relevant patches, and be available by email to other +developers for discussion of changes that impact your package. It's +also a pretty standard route to the "core" development group, where we +have plenty of extra work waiting for volunteers. + +You don't have to become the maintainer, but it virtually ensures +rapid acceptance of the package. + +For help in creating new packages, see the (rather sparse) discussions +in the XEmacs User's Guide and the Lisp Reference Manual. The +participants in the XEmacs Beta mailing list +@uref{mailto:xemacs-beta@@xemacs.org} and the XEmacs Package Release +Engineer are the most likely sources of advice. See +@uref{http://www.xemacs.org/Develop/jobs.html#package,jobs.html} for +current information about package release engineers. + +@node Syncing with GNU Emacs, , New packages, Large contributions +@subsection Syncing with GNU Emacs + +Syncing with GNU Emacs is an important activity. Although each +version has its advantages and areas of concentration, it is very +desirable that common functionality share specifications and APIs. +When porting GNU code to XEmacs, the following points should be given +special attention: + +@itemize @bullet +@item +Recent GNU Emacsen cannot be built without Mule, but XEmacs can. +Make sure that changes that depend on the presence of Mule are +appropriately conditionalized, with @samp{#ifdef MULE} in C code and +with @samp{(featurep 'mule)} in Lisp. + +@item +GNU Emacs nomenclature often differs from that of XEmacs. +Sometimes syncing the names is desirable, other times not. + +@item +GNU Emacs functionality often differs from that of XEmacs. +Syncing functionality is often controversial. +@end itemize + +It is important that you let other developers know that +synchronization has taken place, to what degree, and when. For this +purpose, we use comments of the form + +@example +/* Synched up with: GNU 21.3 by Stephen Turnbull */ +@end example + +in the source file itself, as the last element of the prefatory +material (copyright notice and commentary). Obviously the comment +marker needs to be changed to leading semicolons for Lisp, but +otherwise the format is the same. (Older sync comments may have ``FSF'' +in place of ``GNU''. They're equally accurate in our opinion, but +Richard Stallman and other GNU developers consider the term ``FSF +Emacs'' ``insulting''. Please use ``GNU'' in new sync comments.) + +Of course you should note syncing as the purpose in the ChangeLog, +too. But entries get buried deep in the ChangeLog file, and may even +get moved to a separate ChangeLog.OLD file for rarely synched files. + +Rather than dates we use the version of GNU Emacs to sync to. If the +synchronization is partial, add a new comment describing what has +actually been synched, leaving the description of the last full sync +in place. At each full sync, remove all previous synchronization +comments. + +This applies to Lisp that we have broken out into packages, but +remains in the GNU Emacs core, as well to core Lisp in XEmacs. + +@c Print the tables of contents +@contents +@c That's all + +@node Index, , Improving XEmacs, Top +@unnumbered Index + +@printindex cp + +@bye diff --text -u 'xemacs-21.5.18/man/internals/internals.texi' 'xemacs-21.5.19/man/internals/internals.texi' Index: ./man/internals/internals.texi --- ./man/internals/internals.texi Tue Sep 14 23:39:57 2004 +++ ./man/internals/internals.texi Wed Jan 26 18:48:27 2005 @@ -1,4 +1,4 @@ -\input texinfo @c -*-texinfo-*- + \input texinfo @c -*-texinfo-*- @c %**start of header @setfilename ../../info/internals.info @settitle XEmacs Internals Manual @@ -10,7 +10,17 @@ * Internals: (internals). XEmacs Internals Manual. @end direntry -Copyright @copyright{} 1992 - 1996 Ben Wing. +Edition History: + +Created November 1995 (?) by Ben Wing. +XEmacs Internals Manual Version 1.0, March, 1996. +XEmacs Internals Manual Version 1.1, March, 1997. +XEmacs Internals Manual Version 1.4, March, 2001. +XEmacs Internals Manual Version 21.5, October, 2004. +@c Please REMEMBER to update edition number in *four* places in this file, +@c including adding a line above. + +Copyright @copyright{} 1992 - 2004 Ben Wing. Copyright @copyright{} 1996, 1997 Sun Microsystems. Copyright @copyright{} 1994 - 1998, 2002, 2003 Free Software Foundation. Copyright @copyright{} 1994, 1995 Board of Trustees, University of Illinois. @@ -63,25 +73,35 @@ @titlepage @title XEmacs Internals Manual -@subtitle Version 1.4, March 2001 +@subtitle Version 21.5, October 2004 @author Ben Wing +@sp 1 + +Improvements by + +@sp 1 + +@author Stephen Turnbull @author Martin Buchholz @author Hrvoje Niksic @author Matthias Neubauer @author Olivier Galibert +@author Andy Piper + + @page @vskip 0pt plus 1fill @noindent -Copyright @copyright{} 1992 - 1996, 2001 Ben Wing. @* -Copyright @copyright{} 1996, 1997 Sun Microsystems, Inc. @* -Copyright @copyright{} 1994 - 1998 Free Software Foundation. @* +Copyright @copyright{} 1992 - 2004 Ben Wing. @* +Copyright @copyright{} 1996, 1997 Sun Microsystems. @* +Copyright @copyright{} 1994 - 1998, 2002, 2003 Free Software Foundation. @* Copyright @copyright{} 1994, 1995 Board of Trustees, University of Illinois. @sp 2 -Version 1.4 @* -March 2001.@* +Version 21.5 @* +October 2004.@* Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -102,212 +122,419 @@ @end titlepage @page -@node Top, A History of Emacs, (dir), (dir) +@node Top, Introduction, (dir), (dir) @ifinfo -This Info file contains v1.4 of the XEmacs Internals Manual, March 2001. +This Info file contains v21.5 of the XEmacs Internals Manual, October 2004. @end ifinfo +@ignore +Don't update this by hand!!!!!! +Use C-u C-c C-u m (aka C-u M-x texinfo-master-list). +NOTE: This command does not include the Index:: menu entry. +You must add it by hand. + +Here are some useful Lisp routines for quickly Texinfo-izing text that +has been formatted into ASCII lists and tables. + +(defun list-to-texinfo (b e) + "Convert the selected region from an ASCII list to a Texinfo list." + (interactive "r") + (save-restriction + (narrow-to-region b e) + (goto-char (point-min)) + (let ((dash-type "^ *-+ +") + ;; allow single-letter numbering or roman numerals + (letter-type "^ *[[(]?\\([a-zA-Z]\\|[IVXivx]+\\)[]).] +") + (num-type "^ *[[(]?[0-9]+[]).] +") + dash regexp) + (save-excursion + (re-search-forward "\\s-*") + (cond ((looking-at dash-type) (setq regexp dash-type dash t)) + ((looking-at letter-type) (setq regexp letter-type)) + ((looking-at num-type) (setq regexp num-type)) + ((re-search-forward num-type nil t) (setq regexp num-type)) + ((re-search-forward letter-type nil t) (setq regexp letter-type)) + ((re-search-forward dash-type nil t) + (setq regexp dash-type dash t)) + (t (error "No table entries?")))) + (if dash (insert "@itemize @bullet\n") + (insert "@enumerate\n")) + (re-search-forward regexp nil 'limit) + (while (not (eobp)) + (delete-region (point-at-bol) (point)) + (insert "@item\n") + ;; move forward over any text following the dash to not screw + ;; up remove-spacing. + (forward-line 1) + (let ((p (point))) + (or (re-search-forward regexp nil t) + (goto-char (point-max))) + ;; trick to avoid using a marker + (save-excursion + ;; back up so as not to affect the line we're on (beginning of + ;; next entry) + (forward-line -1) + (remove-spacing p (point))))) + (beginning-of-line) + (if dash (insert "@end itemize\n") + (insert "@end enumerate\n"))))) + +(defun remove-spacing (b e) + "Remove leading space from the selected region. +This finds the maximum leading blank area common to all lines in the region. +This includes all lines any part of which are in the region." + (interactive "r") + (save-excursion + (let ((min 999999) + seen) + (goto-char e) + (end-of-line) + (setq e (point)) + (goto-char b) + (beginning-of-line) + (setq b (point)) + (while (< (point) e) + (cond ((looking-at "^\\s-+") + (goto-char (match-end 0)) + (setq min (min min (current-column)) + seen t)) + ((looking-at "^\\s-*$")) + (t (setq min 0))) + (forward-line 1)) + (when (and seen (> min 0)) + (goto-char e) + (untabify b e) + ;; we are at end of line already. + (if (not (= (point) (point-at-eol))) + (error "Logic error")) + ;; Pad line with spaces if necessary (it may be just a blank line) + (if (< (current-column) min) + (insert-char ?\ (- min (current-column))) + (beginning-of-line) + (forward-char min)) + (kill-rectangle b (point)))))) + +(defun table-to-texinfo (b e) + "Convert the selected region from an ASCII table to a Texinfo table. +Assumes entries are separated by a blank line, and the first sexp in +each entry is the table heading." + (interactive "r") + (save-restriction + (narrow-to-region b e) + (goto-char (point-min)) + (insert "@table @code\n") + (while (not (eobp)) + ;; remember where we want to insert the @item. + ;; delete the spacing first since inserting the @item may create + ;; a line with no spacing, if there is text following the heading on + ;; the same line. + (let ((beg (point))) + ;; removing the space and inserting the @item will change the + ;; position of the end of the region, so to make it easy on us + ;; leave point at end so it will be adjusted. + (forward-line 1) + (let ((beg2 (point))) + (or (re-search-forward "^$" nil t) + (goto-char (point-max))) + (backward-char 1) + (remove-spacing beg2 (point))) + (ignore-errors (forward-char 2)) + (save-excursion + (goto-char beg) + (insert "@item ") + (forward-sexp) + (delete-char) + (insert "\n")))) + (beginning-of-line) + (insert "@end table\n"))) + +A useful Lisp routine for adding markup based on conventions used in plain +text files; see doc string below. + +(defun convert-text-to-texinfo (&optional no-narrow) + "Convert text to Texinfo. +If the region is active, do the region; otherwise, go from point to the end +of the buffer. This query-replaces for various kinds of conventions used +in text: @code{} surrounded by ` and ' or followed by a (); @strong{} +surrounded by *'s; @file{} something that looks like a file name." + (interactive) + (if (region-active-p) + (save-restriction + (narrow-to-region (region-beginning) (region-end)) + (convert-comments-to-texinfo t)) + (let ((p (point)) + (case-replace nil)) + (query-replace-regexp "`\\([^']+\\)'\\([^']\\)" "@code{\\1}\\2" nil) + (goto-char p) + (query-replace-regexp "\\(\\Sw\\)\\*\\(\\(?:\\s_\\|\\sw\\)+\\)\\*\\([^A-Za-z.}]\\)" "\\1@strong{\\2}\\3" nil) + (goto-char p) + (query-replace-regexp "\\(\\(\\s_\\|\\sw\\)+()\\)\\([^}]\\)" "@code{\\1}\\3" nil) + (goto-char p) + (query-replace-regexp "\\(\\(\\s_\\|\\sw\\)+\\.[A-Za-z]+\\)\\([^A-Za-z.}]\\)" "@file{\\1}\\3" nil) + ))) + +Macro the generate the "Future Work" section from a title; put +point at beginning. + +(defalias 'make-future (read-kbd-macro +"<S-end> <f3> <home> @node SPC <end> RET @section SPC <f4> <home> <up> <C-right> <right> Future SPC Work SPC - - SPC <home> <down> <C-right> <right> Future SPC Work SPC - - SPC <end> RET @cindex SPC future SPC work, SPC <f4> C-r , RET C-x C-x M-l RET @cindex SPC <f4> <home> <C-right> <S-end> M-l , SPC future SPC work RET")) + +Similar but generates a "Discussion" section. + +(defalias 'make-discussion (read-kbd-macro +"<S-end> <f3> <home> @node SPC <end> RET @section SPC <f4> <home> <up> <C-right> <right> Discussion SPC - - SPC <home> <down> <C-right> <right> Discussion SPC - - SPC <end> RET @cindex SPC discussion, SPC <f4> C-r , RET C-x C-x M-l RET @cindex SPC <f4> <home> <C-right> <S-end> M-l , SPC discussion RET")) + +Similar but generates an "Old Future Work" section. + +(defalias 'make-old-future (read-kbd-macro +"<S-end> <f3> <home> @node SPC <end> RET @section SPC <f4> <home> <up> <C-right> <right> Old SPC Future SPC Work SPC - - SPC <home> <down> <C-right> <right> Old SPC Future SPC Work SPC - - SPC <end> RET @cindex SPC old SPC future SPC work, SPC <f4> C-r , RET C-x C-x M-l RET @cindex SPC <f4> <home> <C-right> <S-end> M-l , SPC old SPC future SPC work RET")) + +Similar but generates a general section. + +(defalias 'make-section (read-kbd-macro +"<S-end> <f3> <home> @node SPC <end> RET @section SPC <f4> RET @cindex SPC C-SPC C-g <f4> C-x C-x M-l <home> <down>")) + +Similar but generates a general subsection. + +(defalias 'make-subsection (read-kbd-macro +"<S-end> <f3> <home> @node SPC <end> RET @subsection SPC <f4> RET @cindex SPC C-SPC C-g <f4> C-x C-x M-l <home> <down>")) +@end ignore + @menu +* Introduction:: Overview of this manual. +* Authorship of XEmacs:: * A History of Emacs:: Times, dates, important events. -* XEmacs From the Outside:: A broad conceptual overview. +* The XEmacs Split:: +* XEmacs from the Outside:: A broad conceptual overview. * The Lisp Language:: An overview. -* XEmacs From the Perspective of Building:: -* Build-Time Dependencies:: -* XEmacs From the Inside:: -* The XEmacs Object System (Abstractly Speaking):: -* How Lisp Objects Are Represented in C:: -* Major Textual Changes:: -* Rules When Writing New C Code:: -* Regression Testing XEmacs:: -* CVS Techniques:: -* A Summary of the Various XEmacs Modules:: -* Allocation of Objects in XEmacs Lisp:: -* Dumping:: -* Events and the Event Loop:: -* Evaluation; Stack Frames; Bindings:: -* Symbols and Variables:: -* Buffers and Textual Representation:: -* MULE Character Sets and Encodings:: -* The Lisp Reader and Compiler:: -* Lstreams:: -* Consoles; Devices; Frames; Windows:: -* The Redisplay Mechanism:: -* Extents:: -* Faces:: -* Glyphs:: -* Specifiers:: -* Menus:: -* Subprocesses:: -* Interface to the X Window System:: -* Index:: +* XEmacs from the Perspective of Building:: +* Build-Time Dependencies:: +* The Modules of XEmacs:: +* Rules When Writing New C Code:: +* Regression Testing XEmacs:: +* CVS Techniques:: +* XEmacs from the Inside:: +* Basic Types:: +* Low-Level Allocation:: +* The XEmacs Object System (Abstractly Speaking):: +* How Lisp Objects Are Represented in C:: +* Allocation of Objects in XEmacs Lisp:: +* The Lisp Reader and Compiler:: +* Evaluation; Stack Frames; Bindings:: +* Symbols and Variables:: +* Buffers:: +* Text:: +* Multilingual Support:: +* Consoles; Devices; Frames; Windows:: +* The Redisplay Mechanism:: +* Extents:: +* Faces:: +* Glyphs:: +* Specifiers:: +* Menus:: +* Events and the Event Loop:: +* Asynchronous Events; Quit Checking:: +* Lstreams:: +* Subprocesses:: +* Interface to MS Windows:: +* Interface to the X Window System:: +* Dumping:: +* Future Work:: +* Future Work Discussion:: +* Old Future Work:: +* Index:: @detailmenu - ---- The Detailed Node Listing --- + --- The Detailed Node Listing --- A History of Emacs * Through Version 18:: Unification prevails. +* Epoch:: An early graphical split of GNU Emacs. * Lucid Emacs:: One version 19 Emacs. * GNU Emacs 19:: The other version 19 Emacs. * GNU Emacs 20:: The other version 20 Emacs. * XEmacs:: The continuation of Lucid Emacs. -Rules When Writing New C Code +The Modules of XEmacs -* General Coding Rules:: -* Writing Lisp Primitives:: -* Writing Good Comments:: -* Adding Global Lisp Variables:: -* Proper Use of Unsigned Types:: -* Coding for Mule:: -* Techniques for XEmacs Developers:: +* A Summary of the Various XEmacs Modules:: +* Low-Level Modules:: +* Basic Lisp Modules:: +* Modules for Standard Editing Operations:: +* Modules for Interfacing with the File System:: +* Modules for Other Aspects of the Lisp Interpreter and Object System:: +* Modules for Interfacing with the Operating System:: -Coding for Mule +Rules When Writing New C Code -* Character-Related Data Types:: -* Working With Character and Byte Positions:: -* Conversion to and from External Data:: -* General Guidelines for Writing Mule-Aware Code:: -* An Example of Mule-Aware Code:: +* Introduction to Writing C Code:: +* Writing New Modules:: +* Working with Lisp Objects:: +* Writing Lisp Primitives:: +* Writing Good Comments:: +* Adding Global Lisp Variables:: +* Writing Macros:: +* Proper Use of Unsigned Types:: +* Major Textual Changes:: +* Debugging and Testing:: -CVS Techniques +Major Textual Changes -* Merging a Branch into the Trunk:: +* Great Integral Type Renaming:: +* Text/Char Type Renaming:: Regression Testing XEmacs -A Summary of the Various XEmacs Modules - -* Low-Level Modules:: -* Basic Lisp Modules:: -* Modules for Standard Editing Operations:: -* Editor-Level Control Flow Modules:: -* Modules for the Basic Displayable Lisp Objects:: -* Modules for other Display-Related Lisp Objects:: -* Modules for the Redisplay Mechanism:: -* Modules for Interfacing with the File System:: -* Modules for Other Aspects of the Lisp Interpreter and Object System:: -* Modules for Interfacing with the Operating System:: -* Modules for Interfacing with X Windows:: -* Modules for Internationalization:: -* Modules for Regression Testing:: - -Allocation of Objects in XEmacs Lisp - -* Introduction to Allocation:: -* Garbage Collection:: -* GCPROing:: -* Garbage Collection - Step by Step:: -* Integers and Characters:: -* Allocation from Frob Blocks:: -* lrecords:: -* Low-level allocation:: -* Cons:: -* Vector:: -* Bit Vector:: -* Symbol:: -* Marker:: -* String:: -* Compiled Function:: +* How to Regression-Test:: +* Modules for Regression Testing:: -Garbage Collection - Step by Step +CVS Techniques -* Invocation:: -* garbage_collect_1:: -* mark_object:: -* gc_sweep:: -* sweep_lcrecords_1:: -* compact_string_chars:: -* sweep_strings:: -* sweep_bit_vectors_1:: +* Merging a Branch into the Trunk:: -Dumping +Low-Level Allocation -* Overview:: -* Data descriptions:: -* Dumping phase:: -* Reloading phase:: +* Basic Heap Allocation:: +* Stack Allocation:: +* Dynamic Arrays:: +* Allocation by Blocks:: +* Modules for Allocation:: -Dumping phase +Allocation of Objects in XEmacs Lisp -* Object inventory:: -* Address allocation:: -* The header:: -* Data dumping:: -* Pointers dumping:: +* Introduction to Allocation:: +* Garbage Collection:: +* GCPROing:: +* Garbage Collection - Step by Step:: +* Integers and Characters:: +* Allocation from Frob Blocks:: +* lrecords:: +* Low-level allocation:: +* Cons:: +* Vector:: +* Bit Vector:: +* Symbol:: +* Marker:: +* String:: +* Compiled Function:: -Events and the Event Loop +Garbage Collection - Step by Step -* Introduction to Events:: -* Main Loop:: -* Specifics of the Event Gathering Mechanism:: -* Specifics About the Emacs Event:: -* The Event Stream Callback Routines:: -* Other Event Loop Functions:: -* Converting Events:: -* Dispatching Events; The Command Builder:: +* Invocation:: +* garbage_collect_1:: +* mark_object:: +* gc_sweep:: +* sweep_lcrecords_1:: +* compact_string_chars:: +* sweep_strings:: +* sweep_bit_vectors_1:: Evaluation; Stack Frames; Bindings -* Evaluation:: -* Dynamic Binding; The specbinding Stack; Unwind-Protects:: -* Simple Special Forms:: -* Catch and Throw:: +* Evaluation:: +* Dynamic Binding; The specbinding Stack; Unwind-Protects:: +* Simple Special Forms:: +* Catch and Throw:: +* Error Trapping:: Symbols and Variables -* Introduction to Symbols:: -* Obarrays:: -* Symbol Values:: +* Introduction to Symbols:: +* Obarrays:: +* Symbol Values:: -Buffers and Textual Representation +Buffers * Introduction to Buffers:: A buffer holds a block of text such as a file. -* The Text in a Buffer:: Representation of the text in a buffer. * Buffer Lists:: Keeping track of all buffers. * Markers and Extents:: Tagging locations within a buffer. -* Ibytes and Ichars:: Representation of individual characters. * The Buffer Object:: The Lisp object corresponding to a buffer. + +Text + +* The Text in a Buffer:: Representation of the text in a buffer. +* Ibytes and Ichars:: Representation of individual characters. +* Byte-Char Position Conversion:: * Searching and Matching:: Higher-level algorithms. -MULE Character Sets and Encodings +Multilingual Support -* Character Sets:: -* Encodings:: -* Internal Mule Encodings:: -* CCL:: +* Introduction to Multilingual Issues #1:: +* Introduction to Multilingual Issues #2:: +* Introduction to Multilingual Issues #3:: +* Introduction to Multilingual Issues #4:: +* Character Sets:: +* Encodings:: +* Internal Mule Encodings:: +* Byte/Character Types; Buffer Positions; Other Typedefs:: +* Internal Text API's:: +* Coding for Mule:: +* CCL:: +* Microsoft Windows-Related Multilingual Issues:: +* Modules for Internationalization:: Encodings -* Japanese EUC (Extended Unix Code):: -* JIS7:: +* Japanese EUC (Extended Unix Code):: +* JIS7:: Internal Mule Encodings -* Internal String Encoding:: -* Internal Character Encoding:: +* Internal String Encoding:: +* Internal Character Encoding:: -Lstreams +Byte/Character Types; Buffer Positions; Other Typedefs -* 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. +* Byte Types:: +* Different Ways of Seeing Internal Text:: +* Buffer Positions:: +* Other Typedefs:: +* Usage of the Various Representations:: +* Working With the Various Representations:: + +Internal Text API's + +* Basic internal-format API's:: +* The DFC API:: +* The Eistring API:: + +Coding for Mule + +* Character-Related Data Types:: +* Working With Character and Byte Positions:: +* Conversion to and from External Data:: +* General Guidelines for Writing Mule-Aware Code:: +* An Example of Mule-Aware Code:: +* Mule-izing Code:: + +Microsoft Windows-Related Multilingual Issues + +* Microsoft Documentation:: +* Locales:: +* More about code pages:: +* More about locales:: +* Unicode support under Windows:: +* The golden rules of writing Unicode-safe code:: +* The format of the locale in setlocale():: +* Random other Windows I18N docs:: Consoles; Devices; Frames; Windows -* Introduction to Consoles; Devices; Frames; Windows:: -* Point:: -* Window Hierarchy:: -* The Window Object:: +* Introduction to Consoles; Devices; Frames; Windows:: +* Point:: +* Window Hierarchy:: +* The Window Object:: +* Modules for the Basic Displayable Lisp Objects:: The Redisplay Mechanism -* Critical Redisplay Sections:: -* Line Start Cache:: -* Redisplay Piece by Piece:: +* Critical Redisplay Sections:: +* Line Start Cache:: +* Redisplay Piece by Piece:: +* Modules for the Redisplay Mechanism:: +* Modules for other Display-Related Lisp Objects:: Extents @@ -318,10 +545,411 @@ * Mathematics of Extent Ordering:: A rigorous foundation. * Extent Fragments:: Cached information useful for redisplay. +Events and the Event Loop + +* 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:: + +Asynchronous Events; Quit Checking + +* Signal Handling:: +* Control-G (Quit) Checking:: +* Profiling:: +* Asynchronous Timeouts:: +* Exiting:: + +Lstreams + +* 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. + +Interface to MS Windows + +* Different kinds of Windows environments:: +* Windows Build Flags:: +* Windows I18N Introduction:: +* Modules for Interfacing with MS Windows:: + +Interface to the X Window System + +* Lucid Widget Library:: An interface to various widget sets. +* Modules for Interfacing with X Windows:: + +Lucid Widget Library + +* Generic Widget Interface:: The lwlib generic widget interface. +* Scrollbars:: +* Menubars:: +* Checkboxes and Radio Buttons:: +* Progress Bars:: +* Tab Controls:: + +Dumping + +* Dumping Justification:: +* Overview:: +* Data descriptions:: +* Dumping phase:: +* Reloading phase:: +* Remaining issues:: + +Dumping phase + +* Object inventory:: +* Address allocation:: +* The header:: +* Data dumping:: +* Pointers dumping:: + +Future Work + +* 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 @code{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:: + +Future Work -- Toolbars + +* Future Work -- Easier Toolbar Customization:: +* Future Work -- Toolbar Interface Changes:: + +Future Work -- Mouse Pointer + +* Future Work -- Abstracted Mouse Pointer Interface:: +* Future Work -- Busy Pointer:: + +Future Work -- Extents + +* Future Work -- Everything should obey duplicable extents:: + +Future Work -- Keybindings + +* Future Work -- Keybinding Schemes:: +* Future Work -- Better Support for Windows Style Key Bindings:: +* Future Work -- Misc Key Binding Ideas:: + +Future Work -- Byte Code Snippets + +* Future Work -- Autodetection:: +* Future Work -- Conversion Error Detection:: +* Future Work -- Unicode:: +* Future Work -- BIDI Support:: +* Future Work -- Localized Text/Messages:: + +Future Work -- Lisp Engine Replacement + +* Future Work -- Lisp Engine Discussion:: +* Future Work -- Lisp Engine Replacement -- Implementation:: +* Future Work -- Startup File Modification by Packages:: + +Future Work Discussion + +* 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:: + +Discussion -- Garbage Collection + +* Discussion -- Pure Space:: +* Discussion -- Hashtable-Based Marking and Cleanup:: +* Discussion -- The Anti-Cons:: + +Old Future Work + +* Old Future Work -- A Portable Unexec Replacement:: +* Old Future Work -- Indirect Buffers:: +* Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X:: +* Old Future Work -- RTF Clipboard Support:: +* Old Future Work -- xemacs.org Mailing Address Changes:: +* Old Future Work -- Lisp callbacks from critical areas of the C code:: + @end detailmenu @end menu -@node A History of Emacs, XEmacs From the Outside, Top, Top +@node Introduction, Authorship of XEmacs, Top, Top +@chapter Introduction +@cindex introduction +@cindex authorship, manual + +This manual documents the internals of XEmacs. It presumes knowledge of +how to use XEmacs (@pxref{Top,,, xemacs, XEmacs User's Manual}), and +especially, knowledge of XEmacs Lisp (@pxref{Top,,, lispref, XEmacs Lisp +Reference Manual}). Information in either of these manuals will not be +repeated here, and some information in the Lisp Reference Manual in +particular is more relevant to a person working on the internals than +the average XEmacs Lisp programmer. (In such cases, a cross-reference is +usually made to the Lisp Reference Manual.) + +Ideally, this manual would be complete and up-to-date. Unfortunately, +in reality it is neither, due to the limited resources of the +maintainers of XEmacs. (That said, it is much better than the internal +documentation of most programs.) Also, much information about the +internals is documented only in the code itself, in the form of +comments. Furthermore, since the maintainers are more likely to be +working on the code than on this manual, information contained in +comments may be more up-to-date than information in this manual. Do not +assume that all information in this manual is necessarily accurate as of +the snapshot of the code you are looking at, and in the case of +contradictions between the code comments and the manual, @strong{always} +assume that the code comments are correct. (Because of the proximity of +the comments to the code, comments will rarely be out-of-date.) + +The manual is organized in chapters which are broadly grouped into major +divisions: + +@enumerate +@item +First is the introduction, including this chapter and chapters on the +history and authorship of XEmacs. +@item +Next, starting with @ref{XEmacs from the Outside}, are a couple of chapters +giving a broad overview of the internal workings of XEmacs. +@item +Afterwards, starting with @ref{XEmacs from the Perspective of +Building}, are some chapters documenting important information relevant to +those working on the code. +@item +The remaining divisions document the nitty-gritty details of the +internal workings. First, starting with @ref{XEmacs from the Inside}, +is a division on the low-level types and allocation routines and the +workings of the Lisp interpreter that drives XEmacs. +@item +Next, starting with @ref{Buffers}, is a division on the parts of the +code specifically devoted to text processing, including multilingual +support (Mule). +@item +Afterwards, starting with @ref{Consoles; Devices; Frames; Windows}, is a +division covering the display mechanism and the objects and modules +relevant to this. +@item +Then, starting with @ref{Events and the Event Loop}, is a division +covering the interface between XEmacs and the outside world, including +user interactions, subprocesses, file I/O, interfaces to particular +windowing systems, and dumping. +@item +Finally, starting with @ref{Future Work}, is a division containing +proposals and discussion relating to future work on XEmacs. +@end enumerate + +This manual was primarily written by Ben Wing. Certain sections were +written by others, including those mentioned on the title page as well +as other coders. Some sections were lifted directly from comments in +the code, and in those cases we may not completely be aware of the +authorship. In addition, due to the collaborative nature of XEmacs, +many people have made small changes and emendations as they have +discovered problems. + +The following is a (necessarily incomplete) list of the work that was +@emph{not} done by Ben Wing (for more complete information, take a look +at the ChangeLog for the @file{man} directory and the CVS records of +actual changes): + +@table @asis +@item Stephen Turnbull +Various cleanup work, mostly post-2000. Object-Oriented Techniques in +XEmacs. A Reader's Guide to XEmacs Coding Conventions. Searching and +Matching. Regression Testing XEmacs. Modules for Regression Testing. +Lucid Widget Library. A number of sections in the Future Work chapter. +@item Martin Buchholz +Various cleanup work, mostly pre-2001. Docs on inline functions. Docs +on dfc conversion functions (Conversion to and from External Data). +Improvements in support for non-ASCII (European) keysyms under X. +A section or two in the Future Work chapter. +@item Hrvoje Niksic +Coding for Mule. +@item Matthias Neubauer +Garbage Collection - Step by Step. +@item Olivier Galibert +Portable dumper documentation. +@item Andy Piper +Redisplay Piece by Piece. Glyphs. +@item Chuck Thompson +Line Start Cache. +@item Kenichi Handa +CCL. +@item Jamie Zawinski +A couple of sections in the Future Work chapter. +@end table + +@node Authorship of XEmacs, A History of Emacs, Introduction, Top +@chapter Authorship of XEmacs +@cindex authorship, XEmacs + +General authorship in chronological order: + +@table @asis + +@item Jamie Zawinski, Eric Benson, Matthieu Devin, Harlan Sexton +These were the early creators of Lucid Emacs, the predecessor of Xemacs. +Jamie Zawinski was the primary maintainer and coder for Lucid Emacs— +active between early 1991 and June 1994. He presided over versions 19.0 +through 19.10, and then abruptly left for Netscape. He wrote the +advanced stream code, the Xt interface code, the byte compiler, the +original version of the X selection code, the first, second and third +versions of the face code which appeared in 19.0, 19.6 and 19.9 +respectively. Part of the keymap code separated the Lisp directories +into many subdirectories and many smaller changes. Matthieu Devin wrote +the original version of the Extents code. Someone else at Lucid wrote +the Lucid widget library (LWLIB), with the exception of the scrollbar +code, which was added later. + +@item Richard Mlynarik +Active 1991 to 1993, author of much of the current Lisp object scheme, +including Lrecords and LC records (added this support in 1993 to allow +for 28-bit pointers, which had previously been restricted to 26 bits.) +Moved the minibuffer and abbreve code into Lisp, worked on the keymap +code and did the initial synching between Xemacs and the first released +version of GNU Emacs version 19 in mid-1993. + +@item Martin Buchholz +Active 1995 to 2001, maintainer of Xemacs late 1999 to ?, author of the +current configure support, mini optimizations to the byte interpreter, +many improvements to the case changing code and many bug fixes to the +process and system-specific code, also general spell checking and code +cleanliness guru. + +@item Steve Baur +Maintainer of Xemacs 1996 to 1999, responsible for many improvements to +the Xemacs development process, for example, creation of the review +board and arranging for Xemacs to be placed under CVS. Author of the +package code. + +@item Chuck Thompson +Active January 1993 to June of 1996, author of the current and previous +ve3rsions of the redisplay code and maintainer of Xemacs from mid-1994 +to mid-1996. Creator of XEMacs.org. Also wrote the scrollbar code, the +original configure support, and prototype versions of the toolbar and +device code. + +@item Ben Wing +Active April 1993 to April 1996 and February 2000 to present. Chief +coder for Xemacs between 1994 and 1996. Ben Wing was never the +maintainer of Xemacs, and as a result, is the author of more of the +Xemacs specific code in Xemacs than anyone else. Author of the mule +support (Extense code), the glis-phonetically spelled-and specifiers +code most of the toolbars, and device distraction code, the error +checking code, the Lstream code, the bit vector, char-table, and +range-table code, much of the current Xt code, much, much of the events +code (including most of the TTY event code), some of the phase code, and +numerous other aspects of the code. Also author of most of the Xemacs +documentation including the internals manual and the Xemacs editions to +the Lisp reference manual, and responsible for much of the synching +between Xemacs and GNU Emacs. + +@item Kyle Jones +Author of the minimal tag bits support, which allows for 32-bit +pointers and 31-bit integers. + +@item Olivier Galibert +Author of the portable dumping mechanism. + +@item Andy Piper +Author of the widget support, the gutter support and much of the +Microsoft Windows support. + +@item Kirill Katsnelson +Author of many improvements to Microsoft Windows support, the current +sub-process code, and revamping of the display size change mechanism. + +@item Jonathan Harris +Author of much of the Microsoft Windows support. +@end table + +Authorship of some of the modules: + +@table @file +@item alloc.c +Inherited 1991 from a prototype of GNU Emacs 19. Around mid-1993 +Richard Mlynarik redid much of the code, creating the existing system of +object abstractions, (where each object can define its own marking +method, printing method, and so on) and the existing scheme of Lrecords +and LC records. This was done both to increase the number of bits that +a pointer can occupy from 26 to 28, and provide a general framework for +creating new object types easily. The garbage collection and +froblock-phonetically spelled-allocation code is left over from the +original version, but was cleaned up somewhat by Mlynarik. Later in +1993, Jamie Zawinski improved the code that kept track of pure space +usage so it would report exactly where you exceeded the pure space and +how much pure space you are going to have to add to get everything to +fit. He also added code to issue nice pure space and garbage +collections statistics at the end of dumping. Early in 1995, Ben Wing +cleaned up the froblock code to be as compact as possible, added the +various bits of error checking, which are controlled using the +_ErrorCheck*. He also added the ability of strings to be resized, which +is necessary under MULE, because you can replace one character in a +string with another character of a different size. As a result, the +string resizes. Ben Wing also added bit factors for 1913 around +September 1995, and Elsie record lists for 1914 around December 1995. +Steve Baur did some work on the purification and dump time code, and +added Doug Lea Malloc support from Emacs 20.2 circa 1998. Kyle Jones +continued to work done by Mlynarik, reducing the number of primitive +Lisp types so that there are only three: integer character and pointer +type, which encompasses all other types. This allows for 31-bit +integers and 32-bit pointers, although there is potential slowdown in +some extra in directions when determining the type of an object, and +some memory increase for the objects that previously were considered to +be the most primitive types. Martin Buchholz has recently (February +2000) done some work to eliminate most of the slowdown. + +Olivier Galibert, mid-1999 to 2000, implemented the portable +dumper. This writes out the state of the Lisp object heap to +disk file in a real locatable fashion so that it can later be +read in at any memory location. This work entails a number of +changes in Alec.C. For example, pure space was removed and +structures were created to define the types of all the elements +contained in the various lisp object structures and associated +structures. + +@item alloca.c +Inherited a long time ago from a prerelease version of GNU Emacs 19, +kept in sync with more recent versions very few changes from Xemacs. +Most changes consist of converting the code to ANSI C, and fixing up the +includes at the top of the file to follow Xemacs conventions. + +@item alloca.s +Inherited almost unchanged from FSF kept in sync up through 19.30 +basically no changes for Xemacs. +@end table + +@node A History of Emacs, The XEmacs Split, Authorship of XEmacs, Top @chapter A History of Emacs @cindex history of Emacs, a @cindex Emacs, a history of @@ -336,145 +964,284 @@ @cindex Free Software Foundation XEmacs is a powerful, customizable text editor and development -environment. It began as Lucid Emacs, which was in turn derived from -GNU Emacs, a program written by Richard Stallman of the Free Software -Foundation. GNU Emacs dates back to the 1970's, and was modelled -after a package called ``Emacs'', written in 1976, that was a set of -macros on top of TECO, an old, old text editor written at MIT on the -DEC PDP 10 under one of the earliest time-sharing operating systems, -ITS (Incompatible Timesharing System). (ITS dates back well before -Unix.) ITS, TECO, and Emacs were products of a group of people at MIT -who called themselves ``hackers'', who shared an idealistic belief -system about the free exchange of information and were fanatical in -their devotion to and time spent with computers. (The hacker -subculture dates back to the late 1950's at MIT and is described in -detail in Steven Levy's book @cite{Hackers}. This book also includes -a lot of information about Stallman himself and the development of -Lisp, a programming language developed at MIT that underlies Emacs.) +environment. It began in 1991 as Lucid Emacs, which was in turn +derived from GNU Emacs, a program written by Richard Stallman of the +Free Software Foundation. GNU Emacs dates back to 1985 and was +modelled after Unipress Emacs, an editor written by James Gosling in +1981 and based on a series of other "Emacs"-like editors, including +EINE (EINE Is Not EMACS), c. 1976, by Dan Weinreb, which run on the +MIT Lisp Machine and was the first Emacs written in Lisp; ZWEI (ZWEI +Was EINE Initially), c. 1978, by Dan Weinreb and Mike McMahon; Multics +Emacs, c. 1978, by Bernie Greenberg, which was written in MacLisp and +also used Lisp as its extension language; and ZMACS, c. 1980, a direct +descendant of ZWEI that on ran the Symbolics LM-2, LMI LispM, and +later, TI Explorer (1983-1989). These in turn were inspired by the +first Emacs, a package called EMACS, written in 1976 by Richard +Stallman, Guy Steele, and Dave Moon. This was a merger of TECMAC and +TMACS, a pair of "TECO-macro realtime editors" written by Guy Steele, +Dave Moon, Richard Greenblatt, Charles Frankston, et al., and added a +dynamic loader and Meta-key cmds. It ran under ITS (the Incompatible +Timesharing System) on a DEC PDP 10 and under TWENEX on a Tops-20 and +was written in TECO and PDP 10 assembly. ITS was one of the first +time-sharing operating systems and dates back well before Unix. ITS, +TECO, and Emacs were products of a group of people at MIT who called +themselves ``hackers'', who shared an idealistic belief system about +the free exchange of information and were fanatical in their devotion +to and time spent with computers. (The hacker subculture dates back to +the late 1950's at MIT and is described in detail in Steven Levy's +book @cite{Hackers}. This book also includes a lot of information +about Stallman himself and the development of Lisp, a programming +language developed at MIT that underlies Emacs.) @menu * Through Version 18:: Unification prevails. +* Epoch:: An early graphical split of GNU Emacs. * Lucid Emacs:: One version 19 Emacs. * GNU Emacs 19:: The other version 19 Emacs. * GNU Emacs 20:: The other version 20 Emacs. * XEmacs:: The continuation of Lucid Emacs. @end menu -@node Through Version 18 +@node Through Version 18, Epoch, A History of Emacs, A History of Emacs @section Through Version 18 @cindex version 18, through @cindex Gosling, James @cindex Great Usenet Renaming - Although the history of the early versions of GNU Emacs is unclear, -the history is well-known from the middle of 1985. A time line is: +As described above, Emacs began life in the mid-1970's as a series of +editor macros for TECO, an early editor on the PDP-10. In the early +1980's it was rewritten in C as a collaboration between Richard +M. Stallman (RMS) and James Gosling (the creator of Java); its extension +language was known as @dfn{Mocklisp}. This version of Emacs-in-C formed +the basis for the early versions of GNU Emacs and also for Gosling's +Unipress Emacs, a commercial product. Because of bad blood between the +two over the issue of commercialism, RMS pretty much disowned this +collaboration, referring to it as "Gosling Emacs". + +At this point we pick up with a time line of events. (A broader timeline +is available at @uref{http://http://www.jwz.org/doc/emacs-timeline.html, +``Emacs Timeline''}.) + +@strong{NOTE}: Sometimes there are two release dates listed below. In +this case, the first one is the date listed in the source code, and +the second one is when the official announcement was made on +Usenet. (Sometimes, one or the other of the dates is missing, and then +the date below reflects the only existing one.) @itemize @bullet @item -GNU Emacs version 15 (15.34) was released sometime in 1984 or 1985 and -shared some code with a version of Emacs written by James Gosling (the -same James Gosling who later created the Java language). +Unipress Emacs, a $395 commercial product, was released on May 6, 1983. +This was an outgrowth of the Emacs-in-C collaboration written by Gosling +and RMS. + +@item +The first entry on @file{net.emacs} available on Google is dated +August 20, 1984: + +@example +From: B.BURGER (btb@@hogpc.UUCP) +Subject: Arrow Key Problems +Newsgroups: net.emacs +Date: 1984-08-20 11:15:46 PST + +I would greatly appreciate some help getting my arrow keys to work +with EMACS 4.5 on an AT&T 3B20. My terminal is an AT&T PC6300 +(IBM-compatible) using an AT&T 4410 terminal emulator. While this +may not yet be a common configuration, I believe the same problem +has come up using an hp2621 emulator or a real live vt100. + +The problem is that, when I press an arrow key, it isn't +transmitted/read by emacs (one or the other) correctly. +The 4410 terminal description that I'm using defines up=M-[A +(it appears as ^[[A, with the initial ^[ as one character). +Pressting cntrl-Q up_arrow while in emacs shows me the same thing. +On the vt100 the same thing happens but the terminal file says up=M-A +(it appears as ^[A). I've tried every other imaginable up= but get +the same results. I've also been unsuccessful writing a macro that +understands what my keyboard is saying. + +Any ideas on how I can get the arrow keys to do somethingt? +Anything? Thanks in advance. + +--Bruce Burger AT&T-Information Systems Freehold, NJ + @{...ihnp4!@}hogpc!btb (201) 577-5230 +@end example + +@item +GNU Emacs versions 1.0 through 1.12 were apparently released in early +1985. The next version after this was 13.0; there were no GNU Emacs +versions 2 through 12. + +@item +GNU Emacs version 13.0? 1.0? was released on March 20, 1985. This +appears to be the initial public release. This was also based on this +same Emacs-in-C collaboration. + +Here is the release notice: + +@example +From: Chuck Wegrzyn (wegrzyn@@encore.UUCP) +Subject: Public Domain EMACS available from GNU Project +Newsgroups: net.emacs, net.general, net.unix, net.unix-wizards +Date: 1985-03-20 08:03:20 PST + + The GNU project has released its first major subsystem, + the EMACS editor. This editor is a sophisticated screen + editor that is compatible and comparable with the EMACS + editors being sold by UniPress and CCA. It comes with + Mock Lisp ( did you know that UniPress trademarked MLISP??), + and all the little bells and features most of us expect + with EMACS. + + The GNU version of EMACS, written by Richard Stallman, is + available for distribution. The distribution includes all + source code for EMACS and a source code level debugger. + Furthermore, under the GNU project banner, the EMACS system + can be distributed (in source code form) by one and all. + + I was thinking of sending out the source code over the net, + but resisted : it is over 1Mbyte of code. If there is + enough demand, I will add a UUCP dial-in to our system, or + send out tapes, or ... ? + + Is anyone interested in EMACS? If so, please tell me how + you think I should distribute it? + + Chuck Wegrzyn + @{allegra,decvax,ihnp4,princeton@}!encore!wegrzyn +@end example + +@item +GNU Emacs version 15.10 was released on April 11, 1985. + +@item +GNU Emacs version 15.34 was released on May 7, 1985. This appears +to be the last release of version 15. + @item GNU Emacs version 16 (first released version was 16.56) was released on July 15, 1985. All Gosling code was removed due to potential copyright problems with the code. @item -version 16.57: released on September 16, 1985. +Version 16.57: released on September 16, 1985. @item -versions 16.58, 16.59: released on September 17, 1985. +Versions 16.58, 16.59: released on September 17, 1985. @item -version 16.60: released on September 19, 1985. These later version 16's +Version 16.60: released on September 19, 1985. These later version 16's incorporated patches from the net, esp. for getting Emacs to work under System V. @item -version 17.36 (first official v17 release) released on December 20, +Version 17.36 (first official v17 release) released on December 20, 1985. Included a TeX-able user manual. First official unpatched version that worked on vanilla System V machines. @item -version 17.43 (second official v17 release) released on January 25, +Version 17.43 (second official v17 release) released on January 25, 1986. @item -version 17.45 released on January 30, 1986. +Version 17.45 released on January 30, 1986. @item -version 17.46 released on February 4, 1986. +Version 17.46 released on February 4, 1986. @item -version 17.48 released on February 10, 1986. +Version 17.48 released on February 10, 1986 (February 9 on net.emacs). @item -version 17.49 released on February 12, 1986. +Version 17.49 released on February 12, 1986. @item -version 17.55 released on March 18, 1986. +Version 17.55 released on March 18, 1986. @item -version 17.57 released on March 27, 1986. +Version 17.57 released on March 27, 1986. @item -version 17.58 released on April 4, 1986. +Version 17.58 released on April 4, 1986. @item -version 17.61 released on April 12, 1986. +Version 17.61 released on April 12 (?), 1986 (April 22 on net.emacs). @item -version 17.63 released on May 7, 1986. +Version 17.63 released on May 7, 1986. @item -version 17.64 released on May 12, 1986. +Version 17.64 released on May 12, 1986. @item -version 18.24 (a beta version) released on October 2, 1986. +Version 18.24 (a beta version) released on October 2, 1986. @item -version 18.30 (a beta version) released on November 15, 1986. +Version 18.30 (a beta version) released on November 15, 1986. @item -version 18.31 (a beta version) released on November 23, 1986. +Version 18.31 (a beta version) released on November 23, 1986. @item -version 18.32 (a beta version) released on December 7, 1986. +Version 18.32 (a beta version) released on December 6 or 7, 1986. @item -version 18.33 (a beta version) released on December 12, 1986. +Version 18.33 (a beta version) released on December 12, 1986. @item -version 18.35 (a beta version) released on January 5, 1987. +Version 18.35 (a beta version) released on January 5, 1987. @item -version 18.36 (a beta version) released on January 21, 1987. +Version 18.36 (a beta version) released on January 21, 1987. @item January 27, 1987: The Great Usenet Renaming. net.emacs is now comp.emacs. @item -version 18.37 (a beta version) released on February 12, 1987. +Version 18.37 (a beta version) released on February 9 or 12, 1987. @item -version 18.38 (a beta version) released on March 3, 1987. +Version 18.38 (a beta version) released on March 2 or 3, 1987. @item -version 18.39 (a beta version) released on March 14, 1987. +Version 18.39 (a beta version) released on March 14, 1987. @item -version 18.40 (a beta version) released on March 18, 1987. +Version 18.40 (a beta version) released on March 18, 1987. @item -version 18.41 (the first ``official'' release) released on March 22, +Version 18.41 (the first ``official'' release) released on March 22, 1987. @item -version 18.45 released on June 2, 1987. +Version 18.45 released on June 2, 1987. +@item +Version 18.46 released on June 8 or 9, 1987. @item -version 18.46 released on June 9, 1987. +Version 18.47 released on June 10 or 18, 1987. @item -version 18.47 released on June 18, 1987. +Version 18.48 released on August 30 or September 3, 1987. @item -version 18.48 released on September 3, 1987. +Version 18.49 released on September 16 or 18, 1987. @item -version 18.49 released on September 18, 1987. +Version 18.50 released on February 11 or 13, 1988. @item -version 18.50 released on February 13, 1988. +Version 18.51 released on May 6 or 7, 1988. @item -version 18.51 released on May 7, 1988. +Version 18.52 released on September 1, 1988. @item -version 18.52 released on September 1, 1988. +Version 18.53 released on February 23 or 24, 1989. @item -version 18.53 released on February 24, 1989. +Version 18.54 released on April 26, 1989. @item -version 18.54 released on April 26, 1989. +Version 18.55 released on August 18 or 23, 1989. This is the earliest version +that is still available by FTP. (Verified in November 2004.) +@item +Version 18.56 released on January 16 or 17, 1991. +@item +Version 18.57 released on January 25, 1991. +@item +Version 18.58 released on February 18, 1991. +@item +Version 18.59 released on October 30 or 31, 1992. +@end itemize + + +@node Epoch, Lucid Emacs, Through Version 18, A History of Emacs +@section Epoch +@cindex Epoch +@cindex UIUC + +#### Document Epoch + + A time line for Epoch is + +@itemize @bullet @item -version 18.55 released on August 23, 1989. This is the earliest version -that is still available by FTP. +Epoch 1.0 released December 14, 1989. (by Simon Kaplan, Chris Love, et al.) @item -version 18.56 released on January 17, 1991. +Epoch 2.0 released December 23, 1989. @item -version 18.57 released late January, 1991. +Epoch 3.1 released February 6, 1990. @item -version 18.58 released ?????. +Epoch 3.2 released December[????] 11, 1990. @item -version 18.59 released October 31, 1992. +Epoch 4.0 released August 27, 1990. @end itemize -@node Lucid Emacs +@node Lucid Emacs, GNU Emacs 19, Epoch, A History of Emacs @section Lucid Emacs @cindex Lucid Emacs @cindex Lucid Inc. @@ -515,32 +1282,40 @@ @itemize @bullet @item -version 19.0 shipped with Energize 1.0, April 1992. +Version 19.0 shipped with Energize 1.0, April 1992. @item -version 19.1 released June 4, 1992. +Version 19.1 released June 4, 1992. @item -version 19.2 released June 19, 1992. +Version 19.2 released June 19, 1992. @item -version 19.3 released September 9, 1992. +Version 19.3 released September 9, 1992. @item -version 19.4 released January 21, 1993. +Version 19.4 released January 21, 1993. @item -version 19.5 was a repackaging of 19.4 with a few bug fixes and -shipped with Energize 2.0. Never released to the net. +Version 19.5 released February 5, 1993. This was a repackaging of 19.4 with a +few bug fixes and shipped with Energize 2.0. It was a trade-show giveaway +and never released to the net. @item -version 19.6 released April 9, 1993. +Version 19.6 released April 9, 1993. @item -version 19.7 was a repackaging of 19.6 with a few bug fixes and +Version 19.7 was a repackaging of 19.6 with a few bug fixes and shipped with Energize 2.1. Never released to the net. @item -version 19.8 released September 6, 1993. -@item -version 19.9 released January 12, 1994. -@item -version 19.10 released May 27, 1994. +Version 19.8 released September 6, 1993. (Epoch 4.0 merger of +redisplay code, preliminary I18N support, code merged from GNU Emacs +19.8 beta) +@item +Version 19.9 released January 12, 1994. (Scrollbars, Athena.) +@item +Version 19.10 released May 27, 1994. (Uses `configure'; code merged +from GNU Emacs 19.23 beta and further merging with Epoch 4.0) Known as +"Lucid Emacs" when shipped by Lucid, and as "XEmacs" when shipped by +Sun; but Lucid went out of business a few days later and it's unclear +very many copies of 19.10 were released by Lucid. (Last release by +Jamie Zawinski.) @end itemize -@node GNU Emacs 19 +@node GNU Emacs 19, GNU Emacs 20, Lucid Emacs, A History of Emacs @section GNU Emacs 19 @cindex GNU Emacs 19 @cindex Emacs 19, GNU @@ -555,71 +1330,77 @@ @itemize @bullet @item -version 19.8 (beta) released May 27, 1993. +Version 19.7 beta released May 22, 1993. First public beta v19 release. @item -version 19.9 (beta) released May 27, 1993. +Version 19.8 beta released May 25 or 27, 1993. @item -version 19.10 (beta) released May 30, 1993. +Version 19.9 beta released May 27, 1993. @item -version 19.11 (beta) released June 1, 1993. +Version 19.10 beta released May 30, 1993. @item -version 19.12 (beta) released June 2, 1993. +Version 19.11 beta released June 1, 1993. @item -version 19.13 (beta) released June 8, 1993. +Version 19.12 beta released June 1 or 2, 1993. @item -version 19.14 (beta) released June 17, 1993. +Version 19.13 beta released June 8, 1993. @item -version 19.15 (beta) released June 19, 1993. +Version 19.14 beta released June 17, 1993. @item -version 19.16 (beta) released July 6, 1993. +Version 19.15 beta released June 19, 1993. @item -version 19.17 (beta) released late July, 1993. +Version 19.16 beta released July 6, 1993. @item -version 19.18 (beta) released August 9, 1993. +Version 19.17 beta released July 17, 1993. @item -version 19.19 (beta) released August 15, 1993. +Version 19.18 beta released August 8 or 9, 1993. @item -version 19.20 (beta) released November 17, 1993. +Version 19.19 beta released August 14 or 15, 1993. @item -version 19.21 (beta) released November 17, 1993. +Version 19.20 beta released November 11 or 17, 1993. @item -version 19.22 (beta) released November 28, 1993. +Version 19.21 beta released November 16 or 17, 1993. @item -version 19.23 (beta) released May 17, 1994. +Version 19.22 beta released November 27 or 28, 1993. @item -version 19.24 (beta) released May 16, 1994. +Version 19.23 beta released May 17, 1994. @item -version 19.25 (beta) released June 3, 1994. +Version 19.24 beta released May 23 or 16 (?), 1994. @item -version 19.26 (beta) released September 11, 1994. +Version 19.25 beta released May 30 or June 3, 1994. @item -version 19.27 (beta) released September 14, 1994. +Version 19.26 beta released September 7 or 11, 1994. @item -version 19.28 (first ``official'' release) released November 1, 1994. +Version 19.27 beta released September 11 or 14, 1994. @item -version 19.29 released June 21, 1995. +Version 19.28 (first ``official'' release) released November 1, 1994. @item -version 19.30 released November 24, 1995. +Version 19.29 released June 19 or 21, 1995. @item -version 19.31 released May 25, 1996. +Version 19.30 released November 24, 1995. @item -version 19.32 released July 31, 1996. +Version 19.31 released May 25, 1996. @item -version 19.33 released August 11, 1996. +Version 19.32 released July 31, 1996. @item -version 19.34 released August 21, 1996. +Version 19.33 released August 11, 1996. @item -version 19.34b released September 6, 1996. +Version 19.34 released August 21, 1996. +@item +Version 19.34b released September 6, 1996. @end itemize @cindex Mlynarik, Richard +@cindex Baur, Steve In some ways, GNU Emacs 19 was better than Lucid Emacs; in some ways, worse. Lucid soon began incorporating features from GNU Emacs 19 into -Lucid Emacs; the work was mostly done by Richard Mlynarik, who had been -working on and using GNU Emacs for a long time (back as far as version -16 or 17). +Lucid Emacs; for the first year, the work was mostly done by Richard +Mlynarik, who had been working on and using GNU Emacs for a long time +(back as far as version 16 or 17). After that, Lucid folded and Sun +continued with XEmacs; further merging work has continued up through +the present, done mostly by Ben Wing but a good deal of synching was +done by Steve Baur in 1996 with GNU Emacs 19.34. -@node GNU Emacs 20 +@node GNU Emacs 20, XEmacs, GNU Emacs 19, A History of Emacs @section GNU Emacs 20 @cindex GNU Emacs 20 @cindex Emacs 20, GNU @@ -629,18 +1410,37 @@ On February 2, 1997 work began on GNU Emacs to integrate Mule. The first release was made in September of that year. -A timeline for Emacs 20 is +A timeline for GNU Emacs 20 is + +@itemize @bullet +@item +Version 20.1 released September 15 or 17, 1997. +@item +Version 20.2 released September 19 or 20, 1997. +@item +Version 20.3 released August 19, 1998. +@item +version 20.4 released July 12, 1999; on comp.emacs, July 27. +@item +version 20.5 released December 4, 1999. +@item +version 20.6 released February 26, 2000. +@item +version 20.7 released June 13, 2000. +@end itemize + +A timeline for GNU Emacs 21 is @itemize @bullet @item -version 20.1 released September 17, 1997. +version 21.1 released October 20, 2001. @item -version 20.2 released September 20, 1997. +Version 21.2 released March 16, 2002. @item -version 20.3 released August 19, 1998. +Version 21.3 released March 19, 2003. @end itemize -@node XEmacs +@node XEmacs, , GNU Emacs 20, A History of Emacs @section XEmacs @cindex XEmacs @@ -673,19 +1473,27 @@ involvement, punctuated by a six-month contract with Amdahl Corporation. @cindex rename to XEmacs +@cindex Thompson, Chuck +@cindex Wing, Ben In 1994, Sun and Lucid agreed to rename Lucid Emacs to XEmacs (a name not favorable to either company); the first release called XEmacs was version 19.11. In June 1994, Lucid folded and Jamie quit to work for the newly formed Mosaic Communications Corp., later Netscape Communications Corp. (co-founded by the same Marc Andreessen, who had quit his Epoch job to work on a graphical browser for the World Wide -Web). Chuck then become the primary maintainer of XEmacs, and put out -versions 19.11 through 19.14 in conjunction with Ben. For 19.12 and -19.13, Chuck added the new redisplay and many other display improvements -and Ben added MULE support (support for Asian and other languages) and -redesigned most of the internal Lisp subsystems to better support the -MULE work and the various other features being added to XEmacs. After -19.14 Chuck retired as primary maintainer and Steve Baur stepped in. +Web). Chuck and Ben then become the primary authors and maintainers +of XEmacs, with Chuck putting out versions 19.11 through 19.14 in +conjunction with Ben. For 19.12 through 19.14, Chuck added the new +redisplay and various other display improvements and Ben added MULE +support (support for Asian and other languages), multi-device support, +glyphs, specifiers, and GIF/JPG/PNG support, and redesigned most of +the internal Lisp subsystems to better support the MULE work, display +work and the various other features being added to XEmacs. After +19.14 Chuck retired from XEmacs and Steve Baur stepped in as release +engineer. Ben Wing continued on as the primary author and architect +of XEmacs and has remained, sometimes on-and-off, with XEmacs until +the present day (late 2004), being responsible for perhaps 75% of all +the non-FSF code in the core (i.e. not the packages) of XEmacs. @cindex MULE merged XEmacs appears Soon after 19.13 was released, work began in earnest on the MULE @@ -700,15 +1508,91 @@ @cindex Baur, Steve @cindex Buchholz, Martin -@cindex Jones, Kyle -@cindex Niksic, Hrvoje @cindex XEmacs goes it alone In 1997, Sun finally dropped all pretense of support for XEmacs and Martin Buchholz left the company in November. Since then, and mostly for the previous year, because Steve Baur was never paid to work on XEmacs, XEmacs has existed solely on the contributions of volunteers -from the Free Software Community. Starting from 1997, Hrvoje Niksic and -Kyle Jones have figured prominently in XEmacs development. +from the Free Software Community. + +@cindex Jones, Kyle +@cindex Niksic, Hrvoje +@cindex Galibert, Olivier +@cindex Piper, Andy +@cindex Harris, Jonathan +@cindex Katsnelson, Kirill +@cindex Turnbull, Stephen +@cindex Shelton, Vin +@cindex Wing, Ben + Between 1997 and 2000, MS-Windows support was added and stabilized by +Jonathan Harris, Andy Piper, Ben Wing and Kirill Katsnelson. Hrvoje +Niksic and Kyle Jones figured prominently in XEmacs development during +these same years. Steve Baur added the package system in 1997 (?), +and Olivier Galibert also added the portable dumper support around +2000. Martin Buchholz took over from Steve Baur as release manager in +late 1998 (?), and continued in this position through to eary 2000 +(?), when Stephen Turnbull took it over. XEmacs has also been split +into stable and experimental branches since early 1999, and Vin +Shelton has been the release manager of the stable branches since the +beginning. Ben Wing suffered severe pain problems throughout much of +this time, making him unable to use his hands, but he contributed when +he could, especially in the form of dictated design documents. + +@cindex Sperber, Michael +@cindex Turnbull, Stephen +@cindex James, Jerry +@cindex Youngs, Steve +@cindex Aichner, Adrian +@cindex Wing, Ben +@cindex Crestani, Marcus +@cindex Perry, Bill +@cindex Purvis, Malcolm +@cindex Shelton, Vin + Starting around 2000, Kyle, Hrvoje, Martin and Kirill became less active. +Jonathan Harris had dropped out of the project around 1998, and Andy +Piper became mostly inactive by the year 2001 or 2002. New faces +appeared, however, and others continued strong: + +@itemize @bullet +@item +Michael Sperber, who had been in the background as a beta tester for a +fair amount of time, began to assume a more active role. He revamped +the path-searching code at initialization time, did some major work on +the CVS repositories, and is in the process of a major project to +replace the garbage collector, which he is overseeing with some of his +students (e.g. Marcus Crestani). +@item +Steve Youngs stepped in as package maintainer in late 1998 (?). +@item +Stephen Turnbull has contained to produce the experimental beta +releases, write code when he can, produce many design documents, and +generally oversee the managerial aspects of the project. +@item +Jerry James appeared on the scene in early 2002 and has contributed a +large amount of code, including the module subsystem, bignums, and +lots of other code cleanup. +@item +Bill Perry, who had been active on and off in XEmacs since the early +1990's (e.g. he did a fair amount of work on the JPG and PNG interface +and added the TIFF interface, in addition to writing the Emacs/W3 +browser), added GTK support for XEmacs, a major project for which he +received a multi-month contract through BeOpen (?). He has since +disappeared but Malcolm Purvis has taken up the GTK project again and +is keeping it going when he has time. +@item +Adrian Aichner is continuing to create and update the web site on +@uref{www.xemacs.org,XEmacs Web Site}, and is a particularly active +beta tester. +@item +Ben Wing has recovered somewhat from the bad years of 1997 - 1999 and +has resumed his position as Architect of XEmacs and chief code +contributor to the project. He added Mule on Windows support, Unicode +support, the Internals manual (originally written by him during his +last days at Sun) and many other projects, and is now working on a new +behaviors system and cleanups of various other subsystems. +@item +Vin Shelton continues to put out stable releases of XEmacs. +@end itemize @cindex merging attempts Many attempts have been made to merge XEmacs and GNU Emacs, but they @@ -716,27 +1600,64 @@ A more detailed history is contained in the XEmacs About page. + For more detailed information about the features added to each version, +see the files @file{NEWS}, @file{ONEWS}, and @file{OONEWS} in the +@file{etc/} directory. + A time line for XEmacs is @itemize @bullet @item version 19.11 (first XEmacs) released September 13, 1994. @item -version 19.12 released June 23, 1995. +Initial work on Mule support begins September 1994 by both Ben Wing and +Stig. Both projects got bogged down in other issues. @item -version 19.13 released September 1, 1995. -@item -version 19.14 released June 23, 1996. +version 19.12 released June 23, 1995. (The Release Times 10. Included +rewritten redisplay, TTY support, multi-device support, device and +console objects, specifiers, glyphs, toolbars, horizontal scrollbars, +Lucid scrollbar widget, 3-d modeline, stay-up Lucid menus, resizable +minibuffer, echo area is a true buffer, MD5 hashing support, expanded +menubar, redone menu specification format (including menu filters), +rewritten extents, renamed "screen" to "frame", misc-user events, +rewritten face code, rewritten mouse code, warnings system, CL +backquote syntax, critical C-g, code merging with GNU Emacs 19.28. +New packages Hyperbole, OOBR, hm--html-menus, viper, lazy-lock, +ksh-mode, rsz-minibuf.) +@item +Mule work done in earnest from May through November, 1995 by Ben Wing. +Early on, much of the work involved Mule-izing and was incorporated +into 19.12 and 19.13. After the release of 19.13, further work was +forked onto a new development branch, which eventually became 20.0. +@item +version 19.13 released September 1, 1995. (Bug-fix release. Message +logging, background pixmaps, sticky modifiers, Linux audio support, +new Elisp manual, keyboard-translate-table. New packages ada-mode, +arc-mode, auto-show-mode, completion, dabbrev, easymenu, live-icon, +mailcrypt 3.2, two-column.) +@item +xemacs.org created, date ??? -- early 1996?. +@item +version 19.14 released June 23, 1996. (TTY colors, mousable/color +modeline, GIF/JPEG/PNG support, file dialog box, blinking cursor, +gnuattach, auto scrolling horizontally to keep point in view, major +code merging with GNU Emacs 19.30, key bindings from GNU Emacs 19.30, +surrogate minibuffers, function-key-map, key-translation-map. New +packages PSGML, Java/VRML modes, GNUS 5.2.) @item version 20.0 released February 9, 1997. @item -version 19.15 released March 28, 1997. +version 19.15 released March 28, 1997. (Custom, widget, new logo and +background color, introduction of `compatible' variables, major code +merging with GNU Emacs 19.30. New packages EFS, TM, AUC Tex, redo, +igrep, uniquify, many others.) @item version 20.1 (not released to the net) April 15, 1997. @item version 20.2 released May 16, 1997. @item -version 19.16 released October 31, 1997. +version 19.16 released October 31, 1997. (Bug-fix release. Faster +font-locking. Not much else.) @item version 20.3 (the first stable version of XEmacs 20.x) released November 30, 1997. @@ -854,21 +1775,312 @@ @item version 21.2.40 released January 8, 2001. @item -version 21.2.41 released January 17, 2001. +version 21.2.41 "Polyhymnia" released January 17, 2001. +@item +version 21.2.42 "Poseidon" released January 20, 2001. +@item +version 21.2.43 "Terspichore" released January 26, 2001. +@item +version 21.2.44 "Thalia" released February 8, 2001. +@item +version 21.2.45 "Thelxepeia" released February 23, 2001. +@item +version 21.2.46 "Urania" released March 21, 2001. +@item +version 21.2.47 "Zephir" released April 14, 2001. +@item +XEmacs 21.4.0 "Solid Vapor" released April 16, 2001. +@item +XEmacs 21.4.1 "Copyleft" released April 19, 2001. +@item +XEmacs 21.4.2 "Developer-Friendly Unix APIs" released May 10, 2001. +@item +XEmacs 21.4.3 "Academic Rigor" released May 17, 2001. +@item +XEmacs 21.4.4 "Artificial Intelligence" released July 28, 2001. +@item +XEmacs 21.4.5 "Civil Service" released October 23, 2001. +@item +XEmacs 21.4.6 "Common Lisp" released December 17, 2001. +@item +XEmacs 21.4.7 "Economic Science" released May 4, 2002. +@item +XEmacs 21.4.8 "Honest Recruiter" released May 9, 2002. +@item +XEmacs 21.4.9 "Informed Management" released August 23, 2002. +@item +XEmacs 21.4.10 "Military Intelligence" released November 2, 2002. +@item +XEmacs 21.4.11 "Native Windows TTY Support" released January 3, 2003. +@item +XEmacs 21.4.12 "Portable Code" released January 15, 2003. +@item +XEmacs 21.4.13 "Rational FORTRAN" released May 25, 2003. +@item +XEmacs 21.4.14 "Reasonable Discussion" released September 3, 2003. +@item +XEmacs 21.4.15 "Security Through Obscurity" released February 2, 2004. +@item +version 21.5.0 "alfalfa" released April 18, 2001. +@item +version 21.5.1 "anise" released May 9, 2001. +@item +version 21.5.2 "artichoke" released July 28, 2001. +@item +version 21.5.3 "asparagus" released September 7, 2001. +@item +version 21.5.4 "bamboo" released January 8, 2002. +@item +version 21.5.5 "beets" released March 5, 2002. +@item +version 21.5.6 "bok choi" released April 5, 2002. @item -version 21.2.42 released January 20, 2001. +version 21.5.7 "broccoflower" released July 2, 2002. @item -version 21.2.43 released January 26, 2001. +version 21.5.8 "broccoli" released July 27, 2002. @item -version 21.2.44 released February 8, 2001. +version 21.5.9 "brussels sprouts" released August 30, 2002. @item -version 21.2.45 released February 23, 2001. +version 21.5.10 "burdock" released January 4, 2003. @item -version 21.2.46 released March 21, 2001. +version 21.5.11 "cabbage" released February 16, 2003. +@item +version 21.5.12 "carrot" released April 24, 2003. +@item +version 21.5.13 "cauliflower" released May 10, 2003. +@item +version 21.5.14 "cassava" released June 1, 2003. +@item +version 21.5.15 "celery" released September 3, 2003. +@item +version 21.5.16 "celeriac" released September 26, 2003. +@item +version 21.5.17 "chayote" released March 22, 2004. +@item +version 21.5.18 "chestnut" released October 22, 2004. +@end itemize + +@node The XEmacs Split, XEmacs from the Outside, A History of Emacs, Top +@chapter The XEmacs Split +@cindex XEmacs split + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@subheading Ben Wing's attempts + +@strong{NOTE NOTE NOTE}: The following is a @strong{highly} opinionated +piece written by one of the main authors of XEmacs. This reflects his +opinions, and his only! It is included here because it may help to +clarify some of the issues that are keeping the two versions of Emacs +separate. + +Many people look at the split between GNU Emacs and XEmacs and are +convinced that the XEmacs team is being needlessly divisive and just needs +to cooperate a bit with RMS, and the two versions of Emacs will merge. In +fact there have been six to seven major attempts at merging, each running +hundreds of messages long and all of them coming from the XEmacs side. All +have failed because they have eventually come to the same conclusion, which +is that RMS has no real interest in cooperation at all. If you work with +him, you have to do it his way -- "my way or the highway". Specifically: + +@enumerate +@item + +RMS insists on having legal papers signed for every bit of code that goes +into GNU Emacs. RMS's lawyers have told him that every contribution over +ten lines long requires legal papers. These papers cannot be filled out +over to the web but must be done so in person and mailed to the FSF. +Obviously this by itself has a tendency to inhibit contributions because of +the hassle factor. Furthermore, many people (and especially organizations) +are either hesitant to or refuse to sign legal papers, for reasons +mentioned below. Because of these reasons, XEmacs has never enforced legal +signed papers for the code in it. Such papers are not a part of the GPL and +are not required by any projects other than those of the FSF (for example, +Linux does not require such papers). Since we do not know exactly who is +the author of every bit of code that has been contributed to XEmacs in the +last nine years, we would essentially have to rewrite large sections of the +code. The situation however, is worse than that because many of the large +copyright holders of XEmacs (for example Sun Microsystems) refuse to sign +legal papers. Although they have not stated their reasons, there are quite +a number of reasons not to sign legal papers: + +@itemize @bullet +@item +By doing so you essentially give up all control over your code. You can +no longer release your code under a different license. If you want to +use your code that you've contributed to the FSF in a project of your +own, and that project is not released under the GPL, you are not allowed +to do this. Obviously, large companies tend to want to reuse their code +in many different projects and as a result feel very uncomfortable about +signing legal papers. +@item +One of the dangers of assigning copyright to the FSF is that if the FSF +happens to be taken over by some evil corporate identity or anyone with +different ideas than RMS, they will own all copyright-assigned code, and +can revoke the GPL and enforce any license they please. If the code has +many different copyright holders, this is much less likely of a +scenario. @end itemize -@node XEmacs From the Outside, The Lisp Language, A History of Emacs, Top -@chapter XEmacs From the Outside +@item +RMS does not like abstract data structures. Abstract data structures are +the foundation of XEmacs and most other modern programming projects. In +my opinion, is difficult to impossible to write maintainable and +expandable code without using abstract data structures. In merging talks +with RMS he has said we can have any abstract data structures we want in +a merged version but must allow direct access to the implementation as +well, which defeats the primary purpose of having abstract data +structures. + +@item +RMS is very unwilling to compromise when it comes to divergent +implementations of the same functionality, which is very common between +XEmacs and GNU Emacs. Rather than taking the better interface on +technical grounds, RMS insists that both interfaces must be implemented +in C at the same level (rather than implementing one in C and the other +on top if it), so that code that uses either interface is just as +fast. This means that the resulting merged Emacs would be filled with a +lot of very complicated code to simultaneously support two divergent +interfaces, and would be difficult to maintain in this state. + +@item +RMS's idea of compromise and cooperation is almost purely political +rather than technical. The XEmacs maintainers would like to have issues +resolved by examining them technically and deciding what makes the most +sense from a technical prospective. RMS however, wants to proceed on a +tit for tat kind of basis, which is to say, “If we support this feature +of yours, we also get to support this other feature of mine.” The +result of such a process is typically a big mess, because there is no +overarching design but instead a great deal of incompatible things +hodgepodged together. +@end enumerate + +If only some of the above differences were firmly held by RMS, and if he +were willing to compromise effectively on the others and to demonstrate +willingness to work with us on the issues that he is less willing to +compromise on, we might go ahead with the merge despite misgivings. However +RMS has shown no real interest at all in compromising. He has never stated +how all of the redundant work that would be required to support his +preconditions would get done. It's unlikely that he would do it all and +it's certainly not clear that the XEmacs project would be willing to do it +all, given that it is a tremendous amount of extra work and the XEmacs +project is already strapped for coding resources. (Not to mention the +inherent difficulty in convincing people to redo existing work for +primarily political reasons.) In general the free software community is +quite strapped as a whole for coding resources; duplicative efforts amount +to very little positively and have a lot of negative effects in that they +take away what few resources we do have from projects that would actually +be useful. + +RMS however, does not seem to be bothered by this. He is more interested in +sticking firm to his principles, though the heavens may fall down, than in +working forward to create genuinely useful software. It is abundantly clear +that RMS has no real interest in unity except if it happens to be on his +own terms and allows him ultimate control over the result. He would rather +see nothing happen at all than something that is not exactly according to +his principles. The fact that few if any people share his principles is +meaningless to him. + +@subheading Jamie Zawinski's attempts + +In 1991, I was working at Lucid Inc., and our newest product, +Energize, was an integrated development environment for C and C++ on +Unix. The design of this development environment involved very tight +integration between the various tools: compilers, linkers, debuggers, +graphers, and editors. So of course we needed a powerful editor to tie +the whole thing together, and it was obvious to all of us that there +was only one editor that would do: Emacs. + +At the time, the current version of GNU Emacs from the FSF was Emacs +18. There was another version of GNU Emacs called Epoch, that had been +developed at NCSA, which was a set of patches to Emacs 18 that gave it +much better GUI support (Emacs 18 was very much a tty program, with +GUI support crudely grafted on as an afterthought.) + +For the last few years, Emacs 19 had been due to be released ``real +soon now,'' and was expected to integrate the various features of +Epoch in a cleaner way. The Epoch maintainers themselves saw Epoch as +an interim measure, awaiting the release of Emacs 19. + +So, at Lucid we didn't want to tie ourselves to Emacs 18 or on Epoch, +because those code bases were considered obsolete by their +maintainers. We wanted to use Emacs 19 with our product: the idea was +that our product would operate with the off-the-shelf version of Emacs +19, which most people would already have pre-installed on their system +anyway. That way, Energize would make use, to some extent, of tools +you already had and were already using. + +The only problem was, Emacs 19 wasn't done yet. So, we decided we +could help solve that problem, by providing money and resources to get +Emacs 19 finished. + +Even though Energize was a proprietary, commercial product, all of our +work on Emacs (and on GCC and GDB) was released under the GPL. We even +assigned the copyright on all of our work back to the FSF, because we +had no proprietary interest in Emacs per se: it was just a tool that +we wanted to use, and we wanted it to work well, and that was best +achieved by making our modifications to it be as freely available as +possible. (This was one of the earliest, if not the earliest, example +of a commercial product being built to a significant extent out of +open source software.) + +Well, our attempts to help the FSF complete their Emacs 19 project +were pretty much a disaster, and we reached the point where we just +couldn't wait any longer: we needed to ship our product to customers, +and our product needed to have an editor in it. So we bundled up our +work on GNU Emacs 19, called it Lucid Emacs, and released it to the +world. + +This incident has become famous as one of the most significant +``forks'' in a free software code base. + +When Lucid went out of business in 1994, and I came to Netscape, I +passed the torch for the maintenance of Lucid Emacs to Chuck Thompson +(at NCSA) and Ben Wing (at Sun), who renamed it from ``Lucid Emacs'' +to ``XEmacs.'' + +To this day, XEmacs is as popular as FSFmacs, because it still +provides features and a design that many people find superior to the +FSF's version. + +I attribute Lucid Emacs's success to two things, primarily: + + +First, that my focus was on user interface, and an attempt to both +make Emacs be a good citizen of modern GUI desktops, and to make it as +easy for new users to pick up Emacs as any other GUI editor; + +Second, that I ran the Lucid Emacs project in a much more open, +inclusive way than RMS ran his project. I was not just willing, but +eager, to delegate significant and critical pieces of the project to +other hackers once they had shown that they knew what they were +doing. RMS was basically never willing to do this with anybody. Other +things that helped Lucid Emacs's success, but were probably less +important than the above: + + +We gave the users what they wanted first. People had been anticipating +Emacs 19 for years, and we stopped dragging our feet and finished +it. So this got us a lot of users up front. However, XEmacs's current +popularity can't be attributed to this, not since 1993, anyway. + +Lucid Emacs was technically superior in many ways. This won us the +mindshare of many good developers, who preferred working with Lucid +Emacs to FSF Emacs. It would be nice if technical superiority was all +that mattered, but realistically, the other factors were probably more +important than this one, as far as number of users is concerned. The +following messages, from the Lucid Emacs mailing lists in 1992 and +1993, comprise the bulk (if not the entirety) of the public +discussions between the Lucid and FSF camps on why the split happened +and why a merger never did. + +The current XEmacs maintainers have a much more pusillanimous summary +of this history on their XEmacs versus GNU Emacs page. + +-- jwz, 11-Feb-2000. + +@node XEmacs from the Outside, The Lisp Language, The XEmacs Split, Top +@chapter XEmacs from the Outside @cindex XEmacs from the outside @cindex outside, XEmacs from the @cindex read-eval-print @@ -911,7 +2123,7 @@ as well make it do your taxes, compute pi, play bridge, etc. You'd just have to write functions to do those operations in Lisp. -@node The Lisp Language, XEmacs From the Perspective of Building, XEmacs From the Outside, Top +@node The Lisp Language, XEmacs from the Perspective of Building, XEmacs from the Outside, Top @chapter The Lisp Language @cindex Lisp language, the @cindex Lisp vs. C @@ -1133,8 +2345,8 @@ that makes it a full-fledged application platform, very much like an OS inside the real OS. -@node XEmacs From the Perspective of Building, Build-Time Dependencies, The Lisp Language, Top -@chapter XEmacs From the Perspective of Building +@node XEmacs from the Perspective of Building, Build-Time Dependencies, The Lisp Language, Top +@chapter XEmacs from the Perspective of Building @cindex XEmacs from the perspective of building @cindex building, XEmacs from the perspective of @@ -1244,7 +2456,7 @@ get mighty confused by the tricks played by the XEmacs build process, such as allocating memory in one process, and freeing it in the next. -@node Build-Time Dependencies, XEmacs From the Inside, XEmacs From the Perspective of Building, Top +@node Build-Time Dependencies, The Modules of XEmacs, XEmacs from the Perspective of Building, Top @chapter Build-Time Dependencies @cindex build-time dependencies @cindex dependencies, build-time @@ -1289,7 +2501,7 @@ @end enumerate Put these together and you'll see it's perfectly acceptable to build -auto-autoloads *after* dumping if no @file{.elc} files are out-of-date. +auto-autoloads @strong{after} dumping if no @file{.elc} files are out-of-date. @end quotation These Lisp driver programs typically run from temacs, not a dumped @@ -1308,2457 +2520,2481 @@ @code{custom-declare-variable-list} to prevent the @samp{void-variable} error. (Currently this is only needed for @file{make-docfile.el}.) -@node XEmacs From the Inside, The XEmacs Object System (Abstractly Speaking), Build-Time Dependencies, Top -@chapter XEmacs From the Inside -@cindex XEmacs from the inside -@cindex inside, XEmacs from the - -Internally, XEmacs is quite complex, and can be very confusing. To -simplify things, it can be useful to think of XEmacs as containing an -event loop that ``drives'' everything, and a number of other subsystems, -such as a Lisp engine and a redisplay mechanism. Each of these other -subsystems exists simultaneously in XEmacs, and each has a certain -state. The flow of control continually passes in and out of these -different subsystems in the course of normal operation of the editor. +@node The Modules of XEmacs, Rules When Writing New C Code, Build-Time Dependencies, Top +@chapter The Modules of XEmacs +@cindex modules of XEmacs -It is important to keep in mind that, most of the time, the editor is -``driven'' by the event loop. Except during initialization and batch -mode, all subsystems are entered directly or indirectly through the -event loop, and ultimately, control exits out of all subsystems back up -to the event loop. This cycle of entering a subsystem, exiting back out -to the event loop, and starting another iteration of the event loop -occurs once each keystroke, mouse motion, etc. +@menu +* A Summary of the Various XEmacs Modules:: +* Low-Level Modules:: +* Basic Lisp Modules:: +* Modules for Standard Editing Operations:: +* Modules for Interfacing with the File System:: +* Modules for Other Aspects of the Lisp Interpreter and Object System:: +* Modules for Interfacing with the Operating System:: +@end menu -If you're trying to understand a particular subsystem (other than the -event loop), think of it as a ``daemon'' process or ``servant'' that is -responsible for one particular aspect of a larger system, and -periodically receives commands or environment changes that cause it to -do something. Ultimately, these commands and environment changes are -always triggered by the event loop. For example: +@node A Summary of the Various XEmacs Modules, Low-Level Modules, The Modules of XEmacs, The Modules of XEmacs +@section A Summary of the Various XEmacs Modules +@cindex summary of the various XEmacs modules +@cindex modules, summary of the various XEmacs + +The following is a list of the sections describing the various modules +(i.e. files) that implement XEmacs. Some of them are in this chapter; +some of them are attached to the chapters describing the modules in +question. @itemize @bullet @item -The window and frame mechanism is responsible for keeping track of what -windows and frames exist, what buffers are in them, etc. It is -periodically given commands (usually from the user) to make a change to -the current window/frame state: i.e. create a new frame, delete a -window, etc. - +@ref{Low-Level Modules}. @item -The buffer mechanism is responsible for keeping track of what buffers -exist and what text is in them. It is periodically given commands -(usually from the user) to insert or delete text, create a buffer, etc. -When it receives a text-change command, it notifies the redisplay -mechanism. - +@ref{Basic Lisp Modules}. @item -The redisplay mechanism is responsible for making sure that windows and -frames are displayed correctly. It is periodically told (by the event -loop) to actually ``do its job'', i.e. snoop around and see what the -current state of the environment (mostly of the currently-existing -windows, frames, and buffers) is, and make sure that state matches -what's actually displayed. It keeps lots and lots of information around -(such as what is actually being displayed currently, and what the -environment was last time it checked) so that it can minimize the work -it has to do. It is also helped along in that whenever a relevant -change to the environment occurs, the redisplay mechanism is told about -this, so it has a pretty good idea of where it has to look to find -possible changes and doesn't have to look everywhere. - +@ref{Modules for Standard Editing Operations}. @item -The Lisp engine is responsible for executing the Lisp code in which most -user commands are written. It is entered through a call to @code{eval} -or @code{funcall}, which occurs as a result of dispatching an event from -the event loop. The functions it calls issue commands to the buffer -mechanism, the window/frame subsystem, etc. - +@ref{Editor-Level Control Flow Modules}. @item -The Lisp allocation subsystem is responsible for keeping track of Lisp -objects. It is given commands from the Lisp engine to allocate objects, -garbage collect, etc. -@end itemize - -etc. - - The important idea here is that there are a number of independent -subsystems each with its own responsibility and persistent state, just -like different employees in a company, and each subsystem is -periodically given commands from other subsystems. Commands can flow -from any one subsystem to any other, but there is usually some sort of -hierarchy, with all commands originating from the event subsystem. - - XEmacs is entered in @code{main()}, which is in @file{emacs.c}. When -this is called the first time (in a properly-invoked @file{temacs}), it -does the following: - -@enumerate +@ref{Modules for the Basic Displayable Lisp Objects}. @item -It does some very basic environment initializations, such as determining -where it and its directories (e.g. @file{lisp/} and @file{etc/}) reside -and setting up signal handlers. +@ref{Modules for other Display-Related Lisp Objects}. @item -It initializes the entire Lisp interpreter. +@ref{Modules for the Redisplay Mechanism}. @item -It sets the initial values of many built-in variables (including many -variables that are visible to Lisp programs), such as the global keymap -object and the built-in faces (a face is an object that describes the -display characteristics of text). This involves creating Lisp objects -and thus is dependent on step (2). +@ref{Modules for Interfacing with the File System}. @item -It performs various other initializations that are relevant to the -particular environment it is running in, such as retrieving environment -variables, determining the current date and the user who is running the -program, examining its standard input, creating any necessary file -descriptors, etc. +@ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. @item -At this point, the C initialization is complete. A Lisp program that -was specified on the command line (usually @file{loadup.el}) is called -(temacs is normally invoked as @code{temacs -batch -l loadup.el dump}). -@file{loadup.el} loads all of the other Lisp files that are needed for -the operation of the editor, calls the @code{dump-emacs} function to -write out @file{xemacs}, and then kills the temacs process. -@end enumerate - - When @file{xemacs} is then run, it only redoes steps (1) and (4) -above; all variables already contain the values they were set to when -the executable was dumped, and all memory that was allocated with -@code{malloc()} is still around. (XEmacs knows whether it is being run -as @file{xemacs} or @file{temacs} because it sets the global variable -@code{initialized} to 1 after step (4) above.) At this point, -@file{xemacs} calls a Lisp function to do any further initialization, -which includes parsing the command-line (the C code can only do limited -command-line parsing, which includes looking for the @samp{-batch} and -@samp{-l} flags and a few other flags that it needs to know about before -initialization is complete), creating the first frame (or @dfn{window} -in standard window-system parlance), running the user's init file -(usually the file @file{.emacs} in the user's home directory), etc. The -function to do this is usually called @code{normal-top-level}; -@file{loadup.el} tells the C code about this function by setting its -name as the value of the Lisp variable @code{top-level}. +@ref{Modules for Interfacing with the Operating System}. +@item +@ref{Modules for Interfacing with MS Windows}. +@item +@ref{Modules for Interfacing with X Windows}. +@item +@ref{Modules for Internationalization}. +@item +@ref{Modules for Regression Testing}. +@end itemize - When the Lisp initialization code is done, the C code enters the event -loop, and stays there for the duration of the XEmacs process. The code -for the event loop is contained in @file{cmdloop.c}, and is called -@code{Fcommand_loop_1()}. Note that this event loop could very well be -written in Lisp, and in fact a Lisp version exists; but apparently, -doing this makes XEmacs run noticeably slower. +The following table contains cross-references from each module in XEmacs +21.5 to the section (if any) describing it. - Notice how much of the initialization is done in Lisp, not in C. -In general, XEmacs tries to move as much code as is possible -into Lisp. Code that remains in C is code that implements the -Lisp interpreter itself, or code that needs to be very fast, or -code that needs to do system calls or other such stuff that -needs to be done in C, or code that needs to have access to -``forbidden'' structures. (One conscious aspect of the design of -Lisp under XEmacs is a clean separation between the external -interface to a Lisp object's functionality and its internal -implementation. Part of this design is that Lisp programs -are forbidden from accessing the contents of the object other -than through using a standard API. In this respect, XEmacs Lisp -is similar to modern Lisp dialects but differs from GNU Emacs, -which tends to expose the implementation and allow Lisp -programs to look at it directly. The major advantage of -hiding the implementation is that it allows the implementation -to be redesigned without affecting any Lisp programs, including -those that might want to be ``clever'' by looking directly at -the object's contents and possibly manipulating them.) +@multitable {@file{intl-auto-encap-win32.c}} {@ref{Modules for Other Aspects of the Lisp Interpreter and Object System}} +@item @file{Emacs.ad.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsFrame.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsFrame.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsFrameP.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsManager.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsManager.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsManagerP.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsShell-sub.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsShell.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsShell.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{EmacsShellP.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{ExternalClient-Xlib.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{ExternalClient.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{ExternalClient.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{ExternalClientP.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{ExternalShell.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{ExternalShell.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{ExternalShellP.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{Makefile.in.in} @tab +@item @file{abbrev.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{alloc.c} @tab @ref{Basic Lisp Modules}. +@item @file{alloca.c} @tab @ref{Low-Level Modules}. +@item @file{alloca.s} @tab +@item @file{backtrace.h} @tab @ref{Basic Lisp Modules}. +@item @file{balloon-x.c} @tab +@item @file{balloon_help.c} @tab +@item @file{balloon_help.h} @tab +@item @file{base64-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{bitmaps.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{blocktype.c} @tab @ref{Low-Level Modules}. +@item @file{blocktype.h} @tab @ref{Low-Level Modules}. +@item @file{broken-sun.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{buffer.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{buffer.h} @tab @ref{Modules for Standard Editing Operations}. +@item @file{bufslots.h} @tab @ref{Modules for Standard Editing Operations}. +@item @file{byte-compiler-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{bytecode.c} @tab @ref{Basic Lisp Modules}. +@item @file{bytecode.h} @tab @ref{Basic Lisp Modules}. +@item @file{c-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{callint.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{case-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{casefiddle.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{casetab.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{casetab.h} @tab +@item @file{ccl-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{charset.h} @tab +@item @file{chartab.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{chartab.h} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{cm.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{cm.h} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{cmdloop.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{cmds.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{coding-system-slots.h} @tab +@item @file{commands.h} @tab @ref{Modules for Standard Editing Operations}. +@item @file{compiler.h} @tab +@item @file{config.h.in} @tab +@item @file{config.h} @tab @ref{Low-Level Modules}. +@item @file{conslots.h} @tab +@item @file{console-gtk-impl.h} @tab +@item @file{console-gtk.c} @tab +@item @file{console-gtk.h} @tab +@item @file{console-impl.h} @tab +@item @file{console-msw-impl.h} @tab +@item @file{console-msw.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console-msw.h} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console-stream-impl.h} @tab +@item @file{console-stream.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console-stream.h} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console-tty-impl.h} @tab +@item @file{console-tty.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console-tty.h} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console-x-impl.h} @tab +@item @file{console-x.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console-x.h} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{console.h} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{data.c} @tab @ref{Basic Lisp Modules}. +@item @file{database-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{database.c} @tab +@item @file{database.h} @tab +@item @file{debug.c} @tab @ref{Low-Level Modules}. +@item @file{debug.h} @tab @ref{Low-Level Modules}. +@item @file{depend} @tab +@item @file{device-gtk.c} @tab +@item @file{device-impl.h} @tab +@item @file{device-msw.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{device-tty.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{device-x.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{device.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{device.h} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{devslots.h} @tab +@item @file{dgif_lib.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{dialog-gtk.c} @tab +@item @file{dialog-msw.c} @tab +@item @file{dialog-x.c} @tab +@item @file{dialog.c} @tab +@item @file{dired-msw.c} @tab +@item @file{dired.c} @tab @ref{Modules for Interfacing with the File System}. +@item @file{doc.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{doprnt.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{dragdrop.c} @tab +@item @file{dragdrop.h} @tab +@item @file{dump-data.c} @tab +@item @file{dump-data.h} @tab +@item @file{dump-id.c} @tab +@item @file{dumper.c} @tab +@item @file{dumper.h} @tab +@item @file{dynarr.c} @tab @ref{Low-Level Modules}. +@item @file{ecrt0.c} @tab @ref{Low-Level Modules}. +@item @file{editfns.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{elhash.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{elhash.h} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{emacs-marshals.c} @tab +@item @file{emacs-new.c.old} @tab +@item @file{emacs-widget-accessors.c} @tab +@item @file{emacs.c} @tab @ref{Low-Level Modules}. +@item @file{emodules.c} @tab +@item @file{emodules.h} @tab +@item @file{esd.c} @tab +@item @file{eval.c} @tab @ref{Basic Lisp Modules}. +@item @file{event-Xt.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{event-gtk.c} @tab +@item @file{event-gtk.h} @tab +@item @file{event-msw.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{event-stream.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{event-tty.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{event-unixoid.c} @tab +@item @file{event-xlike-inc.c} @tab +@item @file{events-mod.h} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{events.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{events.h} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{extent-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{extents-impl.h} @tab +@item @file{extents.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{extents.h} @tab @ref{Modules for Standard Editing Operations}. +@item @file{extw-Xlib.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{extw-Xlib.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{extw-Xt.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{extw-Xt.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{faces.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{faces.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{file-coding.c} @tab @ref{Modules for Internationalization}. +@item @file{file-coding.h} @tab @ref{Modules for Internationalization}. +@item @file{fileio.c} @tab @ref{Modules for Interfacing with the File System}. +@item @file{filelock.c} @tab @ref{Modules for Interfacing with the File System}. +@item @file{filemode.c} @tab @ref{Modules for Interfacing with the File System}. +@item @file{floatfns.c} @tab @ref{Basic Lisp Modules}. +@item @file{fns.c} @tab @ref{Basic Lisp Modules}. +@item @file{font-lock.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{frame-gtk.c} @tab +@item @file{frame-impl.h} @tab +@item @file{frame-msw.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{frame-tty.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{frame-x.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{frame.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{frame.diff} @tab +@item @file{frame.h} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{frameslots.h} @tab +@item @file{free-hook.c} @tab @ref{Low-Level Modules}. +@item @file{gccache-gtk.c} @tab +@item @file{gccache-gtk.h} @tab +@item @file{general-slots.h} @tab +@item @file{general.c} @tab @ref{Basic Lisp Modules}. +@item @file{getloadavg.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{getpagesize.h} @tab @ref{Low-Level Modules}. +@item @file{gif_err.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{gif_io.c} @tab +@item @file{gif_lib.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{gifalloc.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{gifrlib.h} @tab +@item @file{glade.c} @tab +@item @file{glyphs-eimage.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{glyphs-gtk.c} @tab +@item @file{glyphs-gtk.h} @tab +@item @file{glyphs-msw.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{glyphs-msw.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{glyphs-shared.c} @tab +@item @file{glyphs-widget.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{glyphs-x.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{glyphs-x.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{glyphs.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{glyphs.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{gmalloc.c} @tab @ref{Low-Level Modules}. +@item @file{gpmevent.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{gpmevent.h} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{gtk-glue.c} @tab +@item @file{gtk-xemacs.c} @tab +@item @file{gtk-xemacs.h} @tab +@item @file{gui-gtk.c} @tab +@item @file{gui-msw.c} @tab +@item @file{gui-x.c} @tab +@item @file{gui.c} @tab +@item @file{gui.h} @tab +@item @file{gutter.c} @tab +@item @file{gutter.h} @tab +@item @file{hash-table-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{hash.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{hash.h} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{hftctl.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{hpplay.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{imgproc.c} @tab +@item @file{imgproc.h} @tab +@item @file{indent.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{inline.c} @tab @ref{Low-Level Modules}. +@item @file{input-method-motif.c} @tab +@item @file{input-method-xlib.c} @tab +@item @file{insdel.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{insdel.h} @tab @ref{Modules for Standard Editing Operations}. +@item @file{intl-auto-encap-win32.c} @tab +@item @file{intl-auto-encap-win32.h} @tab +@item @file{intl-encap-win32.c} @tab +@item @file{intl-win32.c} @tab +@item @file{intl-x.c} @tab +@item @file{intl.c} @tab @ref{Modules for Internationalization}. +@item @file{iso-wide.h} @tab @ref{Modules for Internationalization}. +@item @file{keymap.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{keymap.h} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{lastfile.c} @tab @ref{Low-Level Modules}. +@item @file{libinterface.c} @tab +@item @file{libinterface.h} @tab +@item @file{libsst.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{libsst.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{libst.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{line-number.c} @tab +@item @file{line-number.h} @tab +@item @file{linuxplay.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{lisp-disunion.h} @tab @ref{Basic Lisp Modules}. +@item @file{lisp-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{lisp-union.h} @tab @ref{Basic Lisp Modules}. +@item @file{lisp.h} @tab @ref{Basic Lisp Modules}. +@item @file{lread.c} @tab @ref{Basic Lisp Modules}. +@item @file{lrecord.h} @tab @ref{Basic Lisp Modules}. +@item @file{lstream.c} @tab @ref{Modules for Interfacing with the File System}. +@item @file{lstream.h} @tab @ref{Modules for Interfacing with the File System}. +@item @file{macros.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{macros.h} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{make-src-depend} @tab +@item @file{malloc.c} @tab @ref{Low-Level Modules}. +@item @file{marker.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{md5-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{md5.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{mem-limits.h} @tab @ref{Low-Level Modules}. +@item @file{menubar-gtk.c} @tab +@item @file{menubar-msw.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{menubar-msw.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{menubar-x.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{menubar.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{menubar.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{minibuf.c} @tab @ref{Editor-Level Control Flow Modules}. +@item @file{miscplay.c} @tab +@item @file{miscplay.h} @tab +@item @file{mule-canna.c} @tab @ref{Modules for Internationalization}. +@item @file{mule-ccl.c} @tab @ref{Modules for Internationalization}. +@item @file{mule-ccl.h} @tab +@item @file{mule-charset.c} @tab @ref{Modules for Internationalization}. +@item @file{mule-charset.h} @tab @ref{Modules for Internationalization}. +@item @file{mule-coding.c} @tab @ref{Modules for Internationalization}. +@item @file{mule-mcpath.c} @tab @ref{Modules for Internationalization}. +@item @file{mule-mcpath.h} @tab @ref{Modules for Internationalization}. +@item @file{mule-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{mule-wnnfns.c} @tab @ref{Modules for Internationalization}. +@item @file{mule.c} @tab @ref{Modules for Internationalization}. +@item @file{nas.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{native-gtk-toolbar.c} @tab +@item @file{ndir.h} @tab @ref{Modules for Interfacing with the File System}. +@item @file{nsselect.m} @tab +@item @file{nt.c} @tab +@item @file{ntheap.c} @tab +@item @file{ntplay.c} @tab +@item @file{number-gmp.c} @tab +@item @file{number-gmp.h} @tab +@item @file{number-mp.c} @tab +@item @file{number-mp.h} @tab +@item @file{number.c} @tab +@item @file{number.h} @tab +@item @file{objects-gtk-impl.h} @tab +@item @file{objects-gtk.c} @tab +@item @file{objects-gtk.h} @tab +@item @file{objects-impl.h} @tab +@item @file{objects-msw-impl.h} @tab +@item @file{objects-msw.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{objects-msw.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{objects-tty-impl.h} @tab +@item @file{objects-tty.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{objects-tty.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{objects-x-impl.h} @tab +@item @file{objects-x.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{objects-x.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{objects.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{objects.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{offix-cursors.h} @tab +@item @file{offix-types.h} @tab +@item @file{offix.c} @tab +@item @file{offix.h} @tab +@item @file{opaque.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{opaque.h} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{paths.h.in} @tab +@item @file{paths.h} @tab @ref{Low-Level Modules}. +@item @file{ppc.ldscript} @tab +@item @file{pre-crt0.c} @tab @ref{Low-Level Modules}. +@item @file{print.c} @tab @ref{Basic Lisp Modules}. +@item @file{process-nt.c} @tab +@item @file{process-slots.h} @tab +@item @file{process-unix.c} @tab +@item @file{process.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{process.el} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{process.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{procimpl.h} @tab +@item @file{profile.c.orig} @tab +@item @file{profile.c.rej} @tab +@item @file{profile.c} @tab +@item @file{profile.h} @tab +@item @file{ralloc.c} @tab @ref{Low-Level Modules}. +@item @file{rangetab.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{rangetab.h} @tab +@item @file{realpath.c} @tab @ref{Modules for Interfacing with the File System}. +@item @file{redisplay-gtk.c} @tab +@item @file{redisplay-msw.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{redisplay-output.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{redisplay-tty.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{redisplay-x.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{redisplay.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{redisplay.h} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{regex.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{regex.h} @tab @ref{Modules for Standard Editing Operations}. +@item @file{regexp-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{scrollbar-gtk.c} @tab +@item @file{scrollbar-gtk.h} @tab +@item @file{scrollbar-msw.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{scrollbar-msw.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{scrollbar-x.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{scrollbar-x.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{scrollbar.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{scrollbar.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{search.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{select-common.h} @tab +@item @file{select-gtk.c} @tab +@item @file{select-msw.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{select-x.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{select.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{select.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{sgiplay.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sheap.c} @tab +@item @file{signal.c} @tab @ref{Low-Level Modules}. +@item @file{sound.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sound.h} @tab +@item @file{specifier.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{specifier.h} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{src-headers} @tab +@item @file{strcat.c} @tab +@item @file{strcmp.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{strcpy.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{strftime.c} @tab +@item @file{sunOS-fix.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sunplay.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sunpro.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{symbol-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{symbols.c} @tab @ref{Basic Lisp Modules}. +@item @file{symeval.h} @tab @ref{Basic Lisp Modules}. +@item @file{symsinit.h} @tab @ref{Basic Lisp Modules}. +@item @file{syntax-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{syntax.c} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{syntax.h} @tab @ref{Modules for Other Aspects of the Lisp Interpreter and Object System}. +@item @file{sysdep.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sysdep.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sysdir.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sysdll.c} @tab +@item @file{sysdll.h} @tab +@item @file{sysfile.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sysfloat.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{sysproc.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{syspwd.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{syssignal.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{systime.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{systty.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{syswait.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{syswindows.h} @tab +@item @file{tag-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{termcap.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{terminfo.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{test-harness.el} @tab @ref{Modules for Regression Testing}. +@item @file{tests.c} @tab +@item @file{text.c} @tab +@item @file{text.h} @tab +@item @file{toolbar-common.c} @tab +@item @file{toolbar-common.h} @tab +@item @file{toolbar-gtk.c} @tab +@item @file{toolbar-msw.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{toolbar-x.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{toolbar.c} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{toolbar.h} @tab @ref{Modules for other Display-Related Lisp Objects}. +@item @file{tooltalk.c} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{tooltalk.h} @tab @ref{Modules for Interfacing with the Operating System}. +@item @file{tparam.c} @tab @ref{Modules for the Redisplay Mechanism}. +@item @file{ui-byhand.c} @tab +@item @file{ui-gtk.c} @tab +@item @file{ui-gtk.h} @tab +@item @file{undo.c} @tab @ref{Modules for Standard Editing Operations}. +@item @file{unexaix.c} @tab @ref{Low-Level Modules}. +@item @file{unexalpha.c} @tab @ref{Low-Level Modules}. +@item @file{unexapollo.c} @tab @ref{Low-Level Modules}. +@item @file{unexconvex.c} @tab @ref{Low-Level Modules}. +@item @file{unexcw.c} @tab +@item @file{unexec.c} @tab @ref{Low-Level Modules}. +@item @file{unexelf.c} @tab @ref{Low-Level Modules}. +@item @file{unexelfsgi.c} @tab @ref{Low-Level Modules}. +@item @file{unexencap.c} @tab @ref{Low-Level Modules}. +@item @file{unexenix.c} @tab @ref{Low-Level Modules}. +@item @file{unexfreebsd.c} @tab @ref{Low-Level Modules}. +@item @file{unexfx2800.c} @tab @ref{Low-Level Modules}. +@item @file{unexhp9k3.c} @tab @ref{Low-Level Modules}. +@item @file{unexhp9k800.c} @tab @ref{Low-Level Modules}. +@item @file{unexmips.c} @tab @ref{Low-Level Modules}. +@item @file{unexnext.c} @tab @ref{Low-Level Modules}. +@item @file{unexnt.c} @tab +@item @file{unexsni.c} @tab +@item @file{unexsol2-6.c} @tab +@item @file{unexsol2.c} @tab @ref{Low-Level Modules}. +@item @file{unexsunos4.c} @tab @ref{Low-Level Modules}. +@item @file{unicode.c} @tab +@item @file{universe.h} @tab @ref{Low-Level Modules}. +@item @file{vm-limit.c} @tab @ref{Low-Level Modules}. +@item @file{weak-tests.el} @tab @ref{Modules for Regression Testing}. +@item @file{widget.c} @tab +@item @file{win32.c} @tab +@item @file{window-impl.h} @tab +@item @file{window.c} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{window.h} @tab @ref{Modules for the Basic Displayable Lisp Objects}. +@item @file{winslots.h} @tab +@item @file{xemacs.def.in.in} @tab +@item @file{xgccache.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{xgccache.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{xintrinsic.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{xintrinsicp.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{xmmanagerp.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{xmotif.h} @tab +@item @file{xmprimitivep.h} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{xmu.c} @tab @ref{Modules for Interfacing with X Windows}. +@item @file{xmu.h} @tab @ref{Modules for Interfacing with X Windows}. +@end multitable - Moving code into Lisp makes the code easier to debug and maintain and -makes it much easier for people who are not XEmacs developers to -customize XEmacs, because they can make a change with much less chance -of obscure and unwanted interactions occurring than if they were to -change the C code. -@node The XEmacs Object System (Abstractly Speaking), How Lisp Objects Are Represented in C, XEmacs From the Inside, Top -@chapter The XEmacs Object System (Abstractly Speaking) -@cindex XEmacs object system (abstractly speaking), the -@cindex object system (abstractly speaking), the XEmacs - At the heart of the Lisp interpreter is its management of objects. -XEmacs Lisp contains many built-in objects, some of which are -simple and others of which can be very complex; and some of which -are very common, and others of which are rarely used or are only -used internally. (Since the Lisp allocation system, with its -automatic reclamation of unused storage, is so much more convenient -than @code{malloc()} and @code{free()}, the C code makes extensive use of it -in its internal operations.) +@node Low-Level Modules, Basic Lisp Modules, A Summary of the Various XEmacs Modules, The Modules of XEmacs +@section Low-Level Modules +@cindex low-level modules +@cindex modules, low-level - The basic Lisp objects are +@example +@file{config.h} +@end example -@table @code -@item integer -31 bits of precision, or 63 bits on 64-bit machines; the -reason for this is described below when the internal Lisp object -representation is described. -@item char -An object representing a single character of text; chars behave like -integers in many ways but are logically considered text rather than -numbers and have a different read syntax. (the read syntax for a char -contains the char itself or some textual encoding of it---for example, -a Japanese Kanji character might be encoded as @samp{^[$(B#&^[(B} using the -ISO-2022 encoding standard---rather than the numerical representation -of the char; this way, if the mapping between chars and integers -changes, which is quite possible for Kanji characters and other extended -characters, the same character will still be created. Note that some -primitives confuse chars and integers. The worst culprit is @code{eq}, -which makes a special exception and considers a char to be @code{eq} to -its integer equivalent, even though in no other case are objects of two -different types @code{eq}. The reason for this monstrosity is -compatibility with existing code; the separation of char from integer -came fairly recently.) -@item float -Same precision as a double in C. -@item bignum -@itemx ratio -@itemx bigfloat -As build-time options, arbitrary-precision numbers are available. -Bignums are integers, and when available they remove the restriction on -buffer size. Ratios are non-integral rational numbers. Bigfloats are -arbitrary-precision floating point numbers, with precision specified at -runtime. -@item symbol -An object that contains Lisp objects and is referred to by name; -symbols are used to implement variables and named functions -and to provide the equivalent of preprocessor constants in C. -@item string -Self-explanatory; behaves much like a vector of chars -but has a different read syntax and is stored and manipulated -more compactly. -@item bit-vector -A vector of bits; similar to a string in spirit. -@item vector -A one-dimensional array of Lisp objects providing constant-time access -to any of the objects; access to an arbitrary object in a vector is -faster than for lists, but the operations that can be done on a vector -are more limited. -@item compiled-function -An object containing compiled Lisp code, known as @dfn{byte code}. -@item subr -A Lisp primitive, i.e. a Lisp-callable function implemented in C. -@item cons -A simple container for two Lisp objects, used to implement lists and -most other data structures in Lisp. -@end table +This is automatically generated from @file{config.h.in} based on the +results of configure tests and user-selected optional features and +contains preprocessor definitions specifying the nature of the +environment in which XEmacs is being compiled. -Objects which are not conses are called atoms. -@cindex closure -Note that there is no basic ``function'' type, as in more powerful -versions of Lisp (where it's called a @dfn{closure}). XEmacs Lisp does -not provide the closure semantics implemented by Common Lisp and Scheme. -The guts of a function in XEmacs Lisp are represented in one of four -ways: a symbol specifying another function (when one function is an -alias for another), a list (whose first element must be the symbol -@code{lambda}) containing the function's source code, a -compiled-function object, or a subr object. (In other words, given a -symbol specifying the name of a function, calling @code{symbol-function} -to retrieve the contents of the symbol's function cell will return one -of these types of objects.) -XEmacs Lisp also contains numerous specialized objects used to implement -the editor: +@example +@file{paths.h} +@end example -@table @code -@item buffer -Stores text like a string, but is optimized for insertion and deletion -and has certain other properties that can be set. -@item frame -An object with various properties whose displayable representation is a -@dfn{window} in window-system parlance. -@item window -A section of a frame that displays the contents of a buffer; -often called a @dfn{pane} in window-system parlance. -@item window-configuration -An object that represents a saved configuration of windows in a frame. -@item device -An object representing a screen on which frames can be displayed; -equivalent to a @dfn{display} in the X Window System and a @dfn{TTY} in -character mode. -@item face -An object specifying the appearance of text or graphics; it has -properties such as font, foreground color, and background color. -@item marker -An object that refers to a particular position in a buffer and moves -around as text is inserted and deleted to stay in the same relative -position to the text around it. -@item extent -Similar to a marker but covers a range of text in a buffer; can also -specify properties of the text, such as a face in which the text is to -be displayed, whether the text is invisible or unmodifiable, etc. -@item event -Generated by calling @code{next-event} and contains information -describing a particular event happening in the system, such as the user -pressing a key or a process terminating. -@item keymap -An object that maps from events (described using lists, vectors, and -symbols rather than with an event object because the mapping is for -classes of events, rather than individual events) to functions to -execute or other events to recursively look up; the functions are -described by name, using a symbol, or using lists to specify the -function's code. -@item glyph -An object that describes the appearance of an image (e.g. pixmap) on -the screen; glyphs can be attached to the beginning or end of extents -and in some future version of XEmacs will be able to be inserted -directly into a buffer. -@item process -An object that describes a connection to an externally-running process. -@end table +This is automatically generated from @file{paths.h.in} based on supplied +configure values, and allows for non-standard installed configurations +of the XEmacs directories. It's currently broken, though. - There are some other, less-commonly-encountered general objects: -@table @code -@item hash-table -An object that maps from an arbitrary Lisp object to another arbitrary -Lisp object, using hashing for fast lookup. -@item obarray -A limited form of hash-table that maps from strings to symbols; obarrays -are used to look up a symbol given its name and are not actually their -own object type but are kludgily represented using vectors with hidden -fields (this representation derives from GNU Emacs). -@item specifier -A complex object used to specify the value of a display property; a -default value is given and different values can be specified for -particular frames, buffers, windows, devices, or classes of device. -@item char-table -An object that maps from chars or classes of chars to arbitrary Lisp -objects; internally char tables use a complex nested-vector -representation that is optimized to the way characters are represented -as integers. -@item range-table -An object that maps from ranges of integers to arbitrary Lisp objects. -@end table - And some strange special-purpose objects: +@example +@file{emacs.c} +@file{signal.c} +@end example -@table @code -@item charset -@itemx coding-system -Objects used when MULE, or multi-lingual/Asian-language, support is -enabled. -@item color-instance -@itemx font-instance -@itemx image-instance -An object that encapsulates a window-system resource; instances are -mostly used internally but are exposed on the Lisp level for cleanness -of the specifier model and because it's occasionally useful for Lisp -program to create or query the properties of instances. -@item subwindow -An object that encapsulate a @dfn{subwindow} resource, i.e. a -window-system child window that is drawn into by an external process; -this object should be integrated into the glyph system but isn't yet, -and may change form when this is done. -@item tooltalk-message -@itemx tooltalk-pattern -Objects that represent resources used in the ToolTalk interprocess -communication protocol. -@item toolbar-button -An object used in conjunction with the toolbar. -@end table - - And objects that are only used internally: - -@table @code -@item opaque -A generic object for encapsulating arbitrary memory; this allows you the -generality of @code{malloc()} and the convenience of the Lisp object -system. -@item lstream -A buffering I/O stream, used to provide a unified interface to anything -that can accept output or provide input, such as a file descriptor, a -stdio stream, a chunk of memory, a Lisp buffer, a Lisp string, etc.; -it's a Lisp object to make its memory management more convenient. -@item char-table-entry -Subsidiary objects in the internal char-table representation. -@item extent-auxiliary -@itemx menubar-data -@itemx toolbar-data -Various special-purpose objects that are basically just used to -encapsulate memory for particular subsystems, similar to the more -general ``opaque'' object. -@item symbol-value-forward -@itemx symbol-value-buffer-local -@itemx symbol-value-varalias -@itemx symbol-value-lisp-magic -Special internal-only objects that are placed in the value cell of a -symbol to indicate that there is something special with this variable -- -e.g. it has no value, it mirrors another variable, or it mirrors some C -variable; there is really only one kind of object, called a -@dfn{symbol-value-magic}, but it is sort-of halfway kludged into -semi-different object types. -@end table +@file{emacs.c} contains @code{main()} and other code that performs the most +basic environment initializations and handles shutting down the XEmacs +process (this includes @code{kill-emacs}, the normal way that XEmacs is +exited; @code{dump-emacs}, which is used during the build process to +write out the XEmacs executable; @code{run-emacs-from-temacs}, which can +be used to start XEmacs directly when temacs has finished loading all +the Lisp code; and emergency code to handle crashes [XEmacs tries to +auto-save all files before it crashes]). -@cindex permanent objects -@cindex temporary objects - Some types of objects are @dfn{permanent}, meaning that once created, -they do not disappear until explicitly destroyed, using a function such -as @code{delete-buffer}, @code{delete-window}, @code{delete-frame}, etc. -Others will disappear once they are not longer used, through the garbage -collection mechanism. Buffers, frames, windows, devices, and processes -are among the objects that are permanent. Note that some objects can go -both ways: Faces can be created either way; extents are normally -permanent, but detached extents (extents not referring to any text, as -happens to some extents when the text they are referring to is deleted) -are temporary. Note that some permanent objects, such as faces and -coding systems, cannot be deleted. Note also that windows are unique in -that they can be @emph{undeleted} after having previously been -deleted. (This happens as a result of restoring a window configuration.) +Low-level code that directly interacts with the Unix signal mechanism, +however, is in @file{signal.c}. Note that this code does not handle system +dependencies in interfacing to signals; that is handled using the +@file{syssignal.h} header file, described in section J below. -@cindex read syntax - Many types of objects have a @dfn{read syntax}, i.e. a way of -specifying an object of that type in Lisp code. When you load a Lisp -file, or type in code to be evaluated, what really happens is that the -function @code{read} is called, which reads some text and creates an object -based on the syntax of that text; then @code{eval} is called, which -possibly does something special; then this loop repeats until there's -no more text to read. (@code{eval} only actually does something special -with symbols, which causes the symbol's value to be returned, -similar to referencing a variable; and with conses [i.e. lists], -which cause a function invocation. All other values are returned -unchanged.) - The read syntax @example -17297 +@file{unexaix.c} +@file{unexalpha.c} +@file{unexapollo.c} +@file{unexconvex.c} +@file{unexec.c} +@file{unexelf.c} +@file{unexelfsgi.c} +@file{unexencap.c} +@file{unexenix.c} +@file{unexfreebsd.c} +@file{unexfx2800.c} +@file{unexhp9k3.c} +@file{unexhp9k800.c} +@file{unexmips.c} +@file{unexnext.c} +@file{unexsol2.c} +@file{unexsunos4.c} @end example -converts to an integer whose value is 17297. +These modules contain code dumping out the XEmacs executable on various +different systems. (This process is highly machine-specific and +requires intimate knowledge of the executable format and the memory map +of the process.) Only one of these modules is actually used; this is +chosen by @file{configure}. -@example -355/113 -@end example -converts to a ratio commonly used to approximate @emph{pi} when ratios -are configured, and otherwise to a symbol whose name is ``355/113'' (for -backward compatibility). @example -1.983e-4 +@file{ecrt0.c} +@file{lastfile.c} +@file{pre-crt0.c} @end example -converts to a float whose value is 1.983e-4, or .0001983. +These modules are used in conjunction with the dump mechanism. On some +systems, an alternative version of the C startup code (the actual code +that receives control from the operating system when the process is +started, and which calls @code{main()}) is required so that the dumping +process works properly; @file{crt0.c} provides this. -@example -?b -@end example +@file{pre-crt0.c} and @file{lastfile.c} should be the very first and +very last file linked, respectively. (Actually, this is not really true. +@file{lastfile.c} should be after all Emacs modules whose initialized +data should be made constant, and before all other Emacs files and all +libraries. In particular, the allocation modules @file{gmalloc.c}, +@file{alloca.c}, etc. are normally placed past @file{lastfile.c}, and +all of the files that implement Xt widget classes @emph{must} be placed +after @file{lastfile.c} because they contain various structures that +must be statically initialized and into which Xt writes at various +times.) @file{pre-crt0.c} and @file{lastfile.c} contain exported symbols +that are used to determine the start and end of XEmacs' initialized +data space when dumping. -converts to a char that represents the lowercase letter b. @example -?^[$(B#&^[(B +@file{inline.c} @end example -(where @samp{^[} actually is an @samp{ESC} character) converts to a -particular Kanji character when using an ISO2022-based coding system for -input. (To decode this goo: @samp{ESC} begins an escape sequence; -@samp{ESC $ (} is a class of escape sequences meaning ``switch to a -94x94 character set''; @samp{ESC $ ( B} means ``switch to Japanese -Kanji''; @samp{#} and @samp{&} collectively index into a 94-by-94 array -of characters [subtract 33 from the ASCII value of each character to get -the corresponding index]; @samp{ESC (} is a class of escape sequences -meaning ``switch to a 94 character set''; @samp{ESC (B} means ``switch -to US ASCII''. It is a coincidence that the letter @samp{B} is used to -denote both Japanese Kanji and US ASCII. If the first @samp{B} were -replaced with an @samp{A}, you'd be requesting a Chinese Hanzi character -from the GB2312 character set.) +This module is used in connection with inline functions (available in +some compilers). Often, inline functions need to have a corresponding +non-inline function that does the same thing. This module is where they +reside. It contains no actual code, but defines some special flags that +cause inline functions defined in header files to be rendered as actual +functions. It then includes all header files that contain any inline +function definitions, so that each one gets a real function equivalent. -@example -"foobar" -@end example -converts to a string. @example -foobar +@file{debug.c} +@file{debug.h} @end example -converts to a symbol whose name is @code{"foobar"}. This is done by -looking up the string equivalent in the global variable -@code{obarray}, whose contents should be an obarray. If no symbol -is found, a new symbol with the name @code{"foobar"} is automatically -created and added to @code{obarray}; this process is called -@dfn{interning} the symbol. -@cindex interning +These functions provide a system for doing internal consistency checks +during code development. This system is not currently used; instead the +simpler @code{assert()} macro is used along with the various checks +provided by the @samp{--error-check-*} configuration options. -@example -(foo . bar) -@end example -converts to a cons cell containing the symbols @code{foo} and @code{bar}. @example -(1 a 2.5) +@file{universe.h} @end example -converts to a three-element list containing the specified objects -(note that a list is actually a set of nested conses; see the -XEmacs Lisp Reference). +This is not currently used. -@example -[1 a 2.5] -@end example -converts to a three-element vector containing the specified objects. + +@node Basic Lisp Modules, Modules for Standard Editing Operations, Low-Level Modules, The Modules of XEmacs +@section Basic Lisp Modules +@cindex Lisp modules, basic +@cindex modules, basic Lisp @example -#[... ... ... ...] +@file{lisp-disunion.h} +@file{lisp-union.h} +@file{lisp.h} +@file{lrecord.h} +@file{symsinit.h} @end example -converts to a compiled-function object (the actual contents are not -shown since they are not relevant here; look at a file that ends with -@file{.elc} for examples). +These are the basic header files for all XEmacs modules. Each module +includes @file{lisp.h}, which brings the other header files in. +@file{lisp.h} contains the definitions of the structures and extractor +and constructor macros for the basic Lisp objects and various other +basic definitions for the Lisp environment, as well as some +general-purpose definitions (e.g. @code{min()} and @code{max()}). +@file{lisp.h} includes either @file{lisp-disunion.h} or +@file{lisp-union.h}, depending on whether @code{USE_UNION_TYPE} is +defined. These files define the typedef of the Lisp object itself (as +described above) and the low-level macros that hide the actual +implementation of the Lisp object. All extractor and constructor macros +for particular types of Lisp objects are defined in terms of these +low-level macros. -@example -#*01110110 -@end example +As a general rule, all typedefs should go into the typedefs section of +@file{lisp.h} rather than into a module-specific header file even if the +structure is defined elsewhere. This allows function prototypes that +use the typedef to be placed into other header files. Forward structure +declarations (i.e. a simple declaration like @code{struct foo;} where +the structure itself is defined elsewhere) should be placed into the +typedefs section as necessary. -converts to a bit-vector. +@file{lrecord.h} contains the basic structures and macros that implement +all record-type Lisp objects---i.e. all objects whose type is a field +in their C structure, which includes all objects except the few most +basic ones. + +@file{lisp.h} contains prototypes for most of the exported functions in +the various modules. Lisp primitives defined using @code{DEFUN} that +need to be called by C code should be declared using @code{EXFUN}. +Other function prototypes should be placed either into the appropriate +section of @code{lisp.h}, or into a module-specific header file, +depending on how general-purpose the function is and whether it has +special-purpose argument types requiring definitions not in +@file{lisp.h}.) All initialization functions are prototyped in +@file{symsinit.h}. -@example -#s(hash-table ... ...) -@end example -converts to a hash table (the actual contents are not shown). @example -#s(range-table ... ...) +@file{alloc.c} @end example -converts to a range table (the actual contents are not shown). +The large module @file{alloc.c} implements all of the basic allocation and +garbage collection for Lisp objects. The most commonly used Lisp +objects are allocated in chunks, similar to the Blocktype data type +described above; others are allocated in individually @code{malloc()}ed +blocks. This module provides the foundation on which all other aspects +of the Lisp environment sit, and is the first module initialized at +startup. + +Note that @file{alloc.c} provides a series of generic functions that are +not dependent on any particular object type, and interfaces to +particular types of objects using a standardized interface of +type-specific methods. This scheme is a fundamental principle of +object-oriented programming and is heavily used throughout XEmacs. The +great advantage of this is that it allows for a clean separation of +functionality into different modules---new classes of Lisp objects, new +event interfaces, new device types, new stream interfaces, etc. can be +added transparently without affecting code anywhere else in XEmacs. +Because the different subsystems are divided into general and specific +code, adding a new subtype within a subsystem will in general not +require changes to the generic subsystem code or affect any of the other +subtypes in the subsystem; this provides a great deal of robustness to +the XEmacs code. + @example -#s(char-table ... ...) +@file{eval.c} +@file{backtrace.h} @end example -converts to a char table (the actual contents are not shown). +This module contains all of the functions to handle the flow of control. +This includes the mechanisms of defining functions, calling functions, +traversing stack frames, and binding variables; the control primitives +and other special forms such as @code{while}, @code{if}, @code{eval}, +@code{let}, @code{and}, @code{or}, @code{progn}, etc.; handling of +non-local exits, unwind-protects, and exception handlers; entering the +debugger; methods for the subr Lisp object type; etc. It does +@emph{not} include the @code{read} function, the @code{print} function, +or the handling of symbols and obarrays. -Note that the @code{#s()} syntax is the general syntax for structures, -which are not really implemented in XEmacs Lisp but should be. +@file{backtrace.h} contains some structures related to stack frames and the +flow of control. -When an object is printed out (using @code{print} or a related -function), the read syntax is used, so that the same object can be read -in again. -The other objects do not have read syntaxes, usually because it does not -really make sense to create them in this fashion (i.e. processes, where -it doesn't make sense to have a subprocess created as a side effect of -reading some Lisp code), or because they can't be created at all -(e.g. subrs). Permanent objects, as a rule, do not have a read syntax; -nor do most complex objects, which contain too much state to be easily -initialized through a read syntax. -@node How Lisp Objects Are Represented in C, Major Textual Changes, The XEmacs Object System (Abstractly Speaking), Top -@chapter How Lisp Objects Are Represented in C -@cindex Lisp objects are represented in C, how -@cindex objects are represented in C, how Lisp -@cindex represented in C, how Lisp objects are +@example +@file{lread.c} +@end example + +This module implements the Lisp reader and the @code{read} function, +which converts text into Lisp objects, according to the read syntax of +the objects, as described above. This is similar to the parser that is +a part of all compilers. + -Lisp objects are represented in C using a 32-bit or 64-bit machine word -(depending on the processor; i.e. DEC Alphas use 64-bit Lisp objects and -most other processors use 32-bit Lisp objects). The representation -stuffs a pointer together with a tag, as follows: @example - [ 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 ] - [ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ] +@file{print.c} +@end example - <---------------------------------------------------------> <-> - a pointer to a structure, or an integer tag +This module implements the Lisp print mechanism and the @code{print} +function and related functions. This is the inverse of the Lisp reader +-- it converts Lisp objects to a printed, textual representation. +(Hopefully something that can be read back in using @code{read} to get +an equivalent object.) + + + +@example +@file{general.c} +@file{symbols.c} +@file{symeval.h} @end example -A tag of 00 is used for all pointer object types, a tag of 10 is used -for characters, and the other two tags 01 and 11 are joined together to -form the integer object type. This representation gives us 31 bit -integers and 30 bit characters, while pointers are represented directly -without any bit masking or shifting. This representation, though, -assumes that pointers to structs are always aligned to multiples of 4, -so the lower 2 bits are always zero. +@file{symbols.c} implements the handling of symbols, obarrays, and +retrieving the values of symbols. Much of the code is devoted to +handling the special @dfn{symbol-value-magic} objects that define +special types of variables---this includes buffer-local variables, +variable aliases, variables that forward into C variables, etc. This +module is initialized extremely early (right after @file{alloc.c}), +because it is here that the basic symbols @code{t} and @code{nil} are +created, and those symbols are used everywhere throughout XEmacs. -Lisp objects use the typedef @code{Lisp_Object}, but the actual C type -used for the Lisp object can vary. It can be either a simple type -(@code{long} on the DEC Alpha, @code{int} on other machines) or a -structure whose fields are bit fields that line up properly (actually, a -union of structures is used). Generally the simple integral type is -preferable because it ensures that the compiler will actually use a -machine word to represent the object (some compilers will use more -general and less efficient code for unions and structs even if they can -fit in a machine word). The union type, however, has the advantage of -stricter type checking. If you accidentally pass an integer where a Lisp -object is desired, you get a compile error. The choice of which type -to use is determined by the preprocessor constant @code{USE_UNION_TYPE} -which is defined via the @code{--use-union-type} option to -@code{configure}. +@file{symeval.h} contains the definitions of symbol structures and the +@code{DEFVAR_LISP()} and related macros for declaring variables. -Various macros are used to convert between Lisp_Objects and the -corresponding C type. Macros of the form @code{XINT()}, @code{XCHAR()}, -@code{XSTRING()}, @code{XSYMBOL()}, do any required bit shifting and/or -masking and cast it to the appropriate type. @code{XINT()} needs to be -a bit tricky so that negative numbers are properly sign-extended. Since -integers are stored left-shifted, if the right-shift operator does an -arithmetic shift (i.e. it leaves the most-significant bit as-is rather -than shifting in a zero, so that it mimics a divide-by-two even for -negative numbers) the shift to remove the tag bit is enough. This is -the case on all the systems we support. -Note that when @code{ERROR_CHECK_TYPECHECK} is defined, the converter -macros become more complicated---they check the tag bits and/or the -type field in the first four bytes of a record type to ensure that the -object is really of the correct type. This is great for catching places -where an incorrect type is being dereferenced---this typically results -in a pointer being dereferenced as the wrong type of structure, with -unpredictable (and sometimes not easily traceable) results. -There are similar @code{XSET@var{TYPE}()} macros that construct a Lisp -object. These macros are of the form @code{XSET@var{TYPE} -(@var{lvalue}, @var{result})}, i.e. they have to be a statement rather -than just used in an expression. The reason for this is that standard C -doesn't let you ``construct'' a structure (but GCC does). Granted, this -sometimes isn't too convenient; for the case of integers, at least, you -can use the function @code{make_int()}, which constructs and -@emph{returns} an integer Lisp object. Note that the -@code{XSET@var{TYPE}()} macros are also affected by -@code{ERROR_CHECK_TYPECHECK} and make sure that the structure is of the -right type in the case of record types, where the type is contained in -the structure. +@example +@file{data.c} +@file{floatfns.c} +@file{fns.c} +@end example -The C programmer is responsible for @strong{guaranteeing} that a -Lisp_Object is the correct type before using the @code{X@var{TYPE}} -macros. This is especially important in the case of lists. Use -@code{XCAR} and @code{XCDR} if a Lisp_Object is certainly a cons cell, -else use @code{Fcar()} and @code{Fcdr()}. Trust other C code, but not -Lisp code. On the other hand, if XEmacs has an internal logic error, -it's better to crash immediately, so sprinkle @code{assert()}s and -``unreachable'' @code{abort()}s liberally about the source code. Where -performance is an issue, use @code{type_checking_assert}, -@code{bufpos_checking_assert}, and @code{gc_checking_assert}, which do -nothing unless the corresponding configure error checking flag was -specified. +These modules implement the methods and standard Lisp primitives for all +the basic Lisp object types other than symbols (which are described +above). @file{data.c} contains all the predicates (primitives that return +whether an object is of a particular type); the integer arithmetic +functions; and the basic accessor and mutator primitives for the various +object types. @file{fns.c} contains all the standard predicates for working +with sequences (where, abstractly speaking, a sequence is an ordered set +of objects, and can be represented by a list, string, vector, or +bit-vector); it also contains @code{equal}, perhaps on the grounds that +bulk of the operation of @code{equal} is comparing sequences. +@file{floatfns.c} contains methods and primitives for floats and floating-point +arithmetic. -@node Major Textual Changes, Rules When Writing New C Code, How Lisp Objects Are Represented in C, Top -@chapter Major Textual Changes -@cindex textual changes, major -@cindex major textual changes -Sometimes major textual changes are made to the source. This means that -a search-and-replace is done to change type names and such. Some people -disagree with such changes, and certainly if done without good reason -will just lead to headaches. But it's important to keep the code clean -and understable, and consistent naming goes a long way towards this. -An example of the right way to do this was the so-called "great integral -type renaming". +@example +@file{bytecode.c} +@file{bytecode.h} +@end example -@menu -* Great Integral Type Renaming:: -* Text/Char Type Renaming:: -@end menu +@file{bytecode.c} implements the byte-code interpreter and +compiled-function objects, and @file{bytecode.h} contains associated +structures. Note that the byte-code @emph{compiler} is written in Lisp. -@node Great Integral Type Renaming -@section Great Integral Type Renaming -@cindex Great Integral Type Renaming -@cindex integral type renaming, great -@cindex type renaming, integral -@cindex renaming, integral types -The purpose of this is to rationalize the names used for various -integral types, so that they match their intended uses and follow -consist conventions, and eliminate types that were not semantically -different from each other. -The conventions are: -@itemize @bullet -@item -All integral types that measure quantities of anything are signed. Some -people disagree vociferously with this, but their arguments are mostly -theoretical, and are vastly outweighed by the practical headaches of -mixing signed and unsigned values, and more importantly by the far -increased likelihood of inadvertent bugs: Because of the broken "viral" -nature of unsigned quantities in C (operations involving mixed -signed/unsigned are done unsigned, when exactly the opposite is nearly -always wanted), even a single error in declaring a quantity unsigned -that should be signed, or even the even more subtle error of comparing -signed and unsigned values and forgetting the necessary cast, can be -catastrophic, as comparisons will yield wrong results. -Wsign-compare -is turned on specifically to catch this, but this tends to result in a -great number of warnings when mixing signed and unsigned, and the casts -are annoying. More has been written on this elsewhere. +@node Modules for Standard Editing Operations, Modules for Interfacing with the File System, Basic Lisp Modules, The Modules of XEmacs +@section Modules for Standard Editing Operations +@cindex modules for standard editing operations +@cindex editing operations, modules for standard -@item -All such quantity types just mentioned boil down to EMACS_INT, which is -32 bits on 32-bit machines and 64 bits on 64-bit machines. This is -guaranteed to be the same size as Lisp objects of type `int', and (as -far as I can tell) of size_t (unsigned!) and ssize_t. The only type -below that is not an EMACS_INT is Hashcode, which is an unsigned value -of the same size as EMACS_INT. +@example +@file{buffer.c} +@file{buffer.h} +@file{bufslots.h} +@end example -@item -Type names should be relatively short (no more than 10 characters or -so), with the first letter capitalized and no underscores if they can at -all be avoided. +@file{buffer.c} implements the @dfn{buffer} Lisp object type. This +includes functions that create and destroy buffers; retrieve buffers by +name or by other properties; manipulate lists of buffers (remember that +buffers are permanent objects and stored in various ordered lists); +retrieve or change buffer properties; etc. It also contains the +definitions of all the built-in buffer-local variables (which can be +viewed as buffer properties). It does @emph{not} contain code to +manipulate buffer-local variables (that's in @file{symbols.c}, described +above); or code to manipulate the text in a buffer. -@item -"count" == a zero-based measurement of some quantity. Includes sizes, -offsets, and indexes. +@file{buffer.h} defines the structures associated with a buffer and the various +macros for retrieving text from a buffer and special buffer positions +(e.g. @code{point}, the default location for text insertion). It also +contains macros for working with buffer positions and converting between +their representations as character offsets and as byte offsets (under +MULE, they are different, because characters can be multi-byte). It is +one of the largest header files. -@item -"bpos" == a one-based measurement of a position in a buffer. "Charbpos" -and "Bytebpos" count text in the buffer, rather than bytes in memory; -thus Bytebpos does not directly correspond to the memory representation. -Use "Membpos" for this. +@file{bufslots.h} defines the fields in the buffer structure that correspond to +the built-in buffer-local variables. It is its own header file because +it is included many times in @file{buffer.c}, as a way of iterating over all +the built-in buffer-local variables. -@item -"Char" refers to internal-format characters, not to the C type "char", -which is really a byte. -@end itemize -For the actual name changes, see the script below. -I ran the following script to do the conversion. (NOTE: This script is -idempotent. You can safely run it multiple times and it will not screw -up previous results -- in fact, it will do nothing if nothing has -changed. Thus, it can be run repeatedly as necessary to handle patches -coming in from old workspaces, or old branches.) There are two tags, -just before and just after the change: @samp{pre-integral-type-rename} -and @samp{post-integral-type-rename}. When merging code from the main -trunk into a branch, the best thing to do is first merge up to -@samp{pre-integral-type-rename}, then apply the script and associated -changes, then merge from @samp{post-integral-type-change} to the -present. (Alternatively, just do the merging in one operation; but you -may then have a lot of conflicts needing to be resolved by hand.) +@example +@file{insdel.c} +@file{insdel.h} +@end example + +@file{insdel.c} contains low-level functions for inserting and deleting text in +a buffer, keeping track of changed regions for use by redisplay, and +calling any before-change and after-change functions that may have been +registered for the buffer. It also contains the actual functions that +convert between byte offsets and character offsets. + +@file{insdel.h} contains associated headers. + -Script @samp{fixtypes.sh} follows: @example ------------------------------------ cut ------------------------------------ -files="*.[ch] s/*.h m/*.h config.h.in ../configure.in Makefile.in.in ../lib-src/*.[ch] ../lwlib/*.[ch]" -gr Memory_Count Bytecount $files -gr Lstream_Data_Count Bytecount $files -gr Element_Count Elemcount $files -gr Hash_Code Hashcode $files -gr extcount bytecount $files -gr bufpos charbpos $files -gr bytind bytebpos $files -gr memind membpos $files -gr bufbyte intbyte $files -gr Extcount Bytecount $files -gr Bufpos Charbpos $files -gr Bytind Bytebpos $files -gr Memind Membpos $files -gr Bufbyte Intbyte $files -gr EXTCOUNT BYTECOUNT $files -gr BUFPOS CHARBPOS $files -gr BYTIND BYTEBPOS $files -gr MEMIND MEMBPOS $files -gr BUFBYTE INTBYTE $files -gr MEMORY_COUNT BYTECOUNT $files -gr LSTREAM_DATA_COUNT BYTECOUNT $files -gr ELEMENT_COUNT ELEMCOUNT $files -gr HASH_CODE HASHCODE $files ------------------------------------ cut ------------------------------------ +@file{marker.c} @end example -The @samp{gr} script, and the scripts it uses, are documented in -@file{README.global-renaming}, because if placed in this file they would -need to have their @@ characters doubled, meaning you couldn't easily -cut and paste from the source. +This module implements the @dfn{marker} Lisp object type, which +conceptually is a pointer to a text position in a buffer that moves +around as text is inserted and deleted, so as to remain in the same +relative position. This module doesn't actually move the markers around +-- that's handled in @file{insdel.c}. This module just creates them and +implements the primitives for working with them. As markers are simple +objects, this does not entail much. + +Note that the standard arithmetic primitives (e.g. @code{+}) accept +markers in place of integers and automatically substitute the value of +@code{marker-position} for the marker, i.e. an integer describing the +current buffer position of the marker. -In addition to those programs, I needed to fix up a few other -things, particularly relating to the duplicate definitions of -types, now that some types merged with others. Specifically: -@enumerate -@item -in lisp.h, removed duplicate declarations of Bytecount. The changed -code should now look like this: (In each code snippet below, the first -and last lines are the same as the original, as are all lines outside of -those lines. That allows you to locate the section to be replaced, and -replace the stuff in that section, verifying that there isn't anything -new added that would need to be kept.) @example ---------------------------------- snip ------------------------------------- -/* Counts of bytes or chars */ -typedef EMACS_INT Bytecount; -typedef EMACS_INT Charcount; +@file{extents.c} +@file{extents.h} +@end example -/* Counts of elements */ -typedef EMACS_INT Elemcount; +This module implements the @dfn{extent} Lisp object type, which is like +a marker that works over a range of text rather than a single position. +Extents are also much more complex and powerful than markers and have a +more efficient (and more algorithmically complex) implementation. The +implementation is described in detail in comments in @file{extents.c}. -/* Hash codes */ -typedef unsigned long Hashcode; +The code in @file{extents.c} works closely with @file{insdel.c} so that +extents are properly moved around as text is inserted and deleted. +There is also code in @file{extents.c} that provides information needed +by the redisplay mechanism for efficient operation. (Remember that +extents can have display properties that affect [sometimes drastically, +as in the @code{invisible} property] the display of the text they +cover.) -/* ------------------------ dynamic arrays ------------------- */ ---------------------------------- snip ------------------------------------- -@end example -@item -in lstream.h, removed duplicate declaration of Bytecount. Rewrote the -comment about this type. The changed code should now look like this: @example ---------------------------------- snip ------------------------------------- -#endif +@file{editfns.c} +@end example -/* The have been some arguments over the what the type should be that - specifies a count of bytes in a data block to be written out or read in, - using Lstream_read(), Lstream_write(), and related functions. - Originally it was long, which worked fine; Martin "corrected" these to - size_t and ssize_t on the grounds that this is theoretically cleaner and - is in keeping with the C standards. Unfortunately, this practice is - horribly error-prone due to design flaws in the way that mixed - signed/unsigned arithmetic happens. In fact, by doing this change, - Martin introduced a subtle but fatal error that caused the operation of - sending large mail messages to the SMTP server under Windows to fail. - By putting all values back to be signed, avoiding any signed/unsigned - mixing, the bug immediately went away. The type then in use was - Lstream_Data_Count, so that it be reverted cleanly if a vote came to - that. Now it is Bytecount. +@file{editfns.c} contains the standard Lisp primitives for working with +a buffer's text, and calls the low-level functions in @file{insdel.c}. +It also contains primitives for working with @code{point} (the default +buffer insertion location). - Some earlier comments about why the type must be signed: This MUST BE - SIGNED, since it also is used in functions that return the number of - bytes actually read to or written from in an operation, and these - functions can return -1 to signal error. +@file{editfns.c} also contains functions for retrieving various +characteristics from the external environment: the current time, the +process ID of the running XEmacs process, the name of the user who ran +this XEmacs process, etc. It's not clear why this code is in +@file{editfns.c}. - Note that the standard Unix read() and write() functions define the - count going in as a size_t, which is UNSIGNED, and the count going - out as an ssize_t, which is SIGNED. This is a horrible design - flaw. Not only is it highly likely to lead to logic errors when a - -1 gets interpreted as a large positive number, but operations are - bound to fail in all sorts of horrible ways when a number in the - upper-half of the size_t range is passed in -- this number is - unrepresentable as an ssize_t, so code that checks to see how many - bytes are actually written (which is mandatory if you are dealing - with certain types of devices) will get completely screwed up. - --ben -*/ -typedef enum lstream_buffering ---------------------------------- snip ------------------------------------- +@example +@file{callint.c} +@file{cmds.c} +@file{commands.h} @end example -@item -in dumper.c, there are four places, all inside of switch() statements, -where XD_BYTECOUNT appears twice as a case tag. In each case, the two -case blocks contain identical code, and you should *REMOVE THE SECOND* -and leave the first. -@end enumerate +@cindex interactive +These modules implement the basic @dfn{interactive} commands, +i.e. user-callable functions. Commands, as opposed to other functions, +have special ways of getting their parameters interactively (by querying +the user), as opposed to having them passed in a normal function +invocation. Many commands are not really meant to be called from other +Lisp functions, because they modify global state in a way that's often +undesired as part of other Lisp functions. -@node Text/Char Type Renaming -@section Text/Char Type Renaming -@cindex Text/Char Type Renaming -@cindex type renaming, text/char -@cindex renaming, text/char types +@file{callint.c} implements the mechanism for querying the user for +parameters and calling interactive commands. The bulk of this module is +code that parses the interactive spec that is supplied with an +interactive command. -The purpose of this was +@file{cmds.c} implements the basic, most commonly used editing commands: +commands to move around the current buffer and insert and delete +characters. These commands are implemented using the Lisp primitives +defined in @file{editfns.c}. -@enumerate -@item -To distinguish between ``charptr'' when it refers to operations on -the pointer itself and when it refers to operations on text -@item -To use consistent naming for everything referring to internal format, i.e. -@end enumerate +@file{commands.h} contains associated structure definitions and prototypes. -@example - Itext == text in internal format - Ibyte == a byte in such text - Ichar == a char as represented in internal character format -@end example -Thus e.g. @example - set_charptr_emchar -> set_itext_ichar +@file{regex.c} +@file{regex.h} +@file{search.c} @end example - -This was done using a script like this: + +@file{search.c} implements the Lisp primitives for searching for text in +a buffer, and some of the low-level algorithms for doing this. In +particular, the fast fixed-string Boyer-Moore search algorithm is +implemented in @file{search.c}. The low-level algorithms for doing +regular-expression searching, however, are implemented in @file{regex.c} +and @file{regex.h}. These two modules are largely independent of +XEmacs, and are similar to (and based upon) the regular-expression +routines used in @file{grep} and other GNU utilities. + + @example -files="*.[ch] s/*.h m/*.h config.h.in ../configure.in Makefile.in.in ../lib-src/*.[ch] ../lwlib/*.[ch]" -gr Intbyte Ibyte $files -gr INTBYTE IBYTE $files -gr intbyte ibyte $files -gr EMCHAR ICHAR $files -gr emchar ichar $files -gr Emchar Ichar $files -gr INC_CHARPTR INC_IBYTEPTR $files -gr DEC_CHARPTR DEC_IBYTEPTR $files -gr VALIDATE_CHARPTR VALIDATE_IBYTEPTR $files -gr valid_charptr valid_ibyteptr $files -gr CHARPTR ITEXT $files -gr charptr itext $files -gr Charptr Itext $files +@file{doprnt.c} @end example -See above for the source to @samp{gr}. +@file{doprnt.c} implements formatted-string processing, similar to +@code{printf()} command in C. + -As in the integral-types change, there are pre and post tags before and -after the change: @example - pre-internal-format-textual-renaming - post-internal-format-textual-renaming +@file{undo.c} @end example -When merging a large branch, follow the same sort of procedure -documented above, using these tags -- essentially sync up to the pre -tag, then apply the script yourself, then sync from the post tag to the -present. You can probably do the same if you don't have a separate -workspace, but do have lots of outstanding changes and you'd rather not -just merge all the textual changes directly. Use something like this: +This module implements the undo mechanism for tracking buffer changes. +Most of this could be implemented in Lisp. -(WARNING: I'm not a CVS guru; before trying this, or any large operation -that might potentially mess things up, *DEFINITELY* make a backup of -your existing workspace.) + +@node Modules for Interfacing with the File System, Modules for Other Aspects of the Lisp Interpreter and Object System, Modules for Standard Editing Operations, The Modules of XEmacs +@section Modules for Interfacing with the File System +@cindex modules for interfacing with the file system +@cindex interfacing with the file system, modules for +@cindex file system, modules for interfacing with the @example -cup -r pre-internal-format-textual-renaming -<apply script> -cup -A -j post-internal-format-textual-renaming -j HEAD +@file{lstream.c} +@file{lstream.h} @end example -This might also work: +These modules implement the @dfn{stream} Lisp object type. This is an +internal-only Lisp object that implements a generic buffering stream. +The idea is to provide a uniform interface onto all sources and sinks of +data, including file descriptors, stdio streams, chunks of memory, Lisp +buffers, Lisp strings, etc. That way, I/O functions can be written to +the stream interface and can transparently handle all possible sources +and sinks. (For example, the @code{read} function can read data from a +file, a string, a buffer, or even a function that is called repeatedly +to return data, without worrying about where the data is coming from or +what-size chunks it is returned in.) + +@cindex lstream +Note that in the C code, streams are called @dfn{lstreams} (for ``Lisp +streams'') to distinguish them from other kinds of streams, e.g. stdio +streams and C++ I/O streams. + +Similar to other subsystems in XEmacs, lstreams are separated into +generic functions and a set of methods for the different types of +lstreams. @file{lstream.c} provides implementations of many different +types of streams; others are provided, e.g., in @file{file-coding.c}. + + @example -cup -j pre-internal-format-textual-renaming -<apply script> -cup -j post-internal-format-textual-renaming -j HEAD +@file{fileio.c} @end example -ben +This implements the basic primitives for interfacing with the file +system. This includes primitives for reading files into buffers, +writing buffers into files, checking for the presence or accessibility +of files, canonicalizing file names, etc. Note that these primitives +are usually not invoked directly by the user: There is a great deal of +higher-level Lisp code that implements the user commands such as +@code{find-file} and @code{save-buffer}. This is similar to the +distinction between the lower-level primitives in @file{editfns.c} and +the higher-level user commands in @file{commands.c} and +@file{simple.el}. -The following is a script to go in the opposite direction: -@example -files="*.[ch] s/*.h m/*.h config.h.in ../configure.in Makefile.in.in ../lib-src/*.[ch] ../lwlib/*.[ch]" -# Evidently Perl considers _ to be a word char ala \b, even though XEmacs -# doesn't. We need to be careful here with ibyte/ichar because of words -# like Richard, eicharlen(), multibyte, HIBYTE, etc. +@example +@file{filelock.c} +@end example -gr Ibyte Intbyte $files -gr '\bIBYTE' INTBYTE $files -gr '\bibyte' intbyte $files -gr '\bICHAR' EMCHAR $files -gr '\bichar' emchar $files -gr '\bIchar' Emchar $files -gr '\bIBYTEPTR' CHARPTR $files -gr '\bibyteptr' charptr $files -gr '\bITEXT' CHARPTR $files -gr '\bitext' charptr $files -gr '\bItext' CHARPTR $files - -gr '_IBYTE' _INTBYTE $files -gr '_ibyte' _intbyte $files -gr '_ICHAR' _EMCHAR $files -gr '_ichar' _emchar $files -gr '_Ichar' _Emchar $files -gr '_IBYTEPTR' _CHARPTR $files -gr '_ibyteptr' _charptr $files -gr '_ITEXT' _CHARPTR $files -gr '_itext' _charptr $files -gr '_Itext' _CHARPTR $files -@end example +This file provides functions for detecting clashes between different +processes (e.g. XEmacs and some external process, or two different +XEmacs processes) modifying the same file. (XEmacs can optionally use +the @file{lock/} subdirectory to provide a form of ``locking'' between +different XEmacs processes.) This module is also used by the low-level +functions in @file{insdel.c} to ensure that, if the first modification +is being made to a buffer whose corresponding file has been externally +modified, the user is made aware of this so that the buffer can be +synched up with the external changes if necessary. -@node Rules When Writing New C Code, Regression Testing XEmacs, Major Textual Changes, Top -@chapter Rules When Writing New C Code -@cindex writing new C code, rules when -@cindex C code, rules when writing new -@cindex code, rules when writing new C -The XEmacs C Code is extremely complex and intricate, and there are many -rules that are more or less consistently followed throughout the code. -Many of these rules are not obvious, so they are explained here. It is -of the utmost importance that you follow them. If you don't, you may -get something that appears to work, but which will crash in odd -situations, often in code far away from where the actual breakage is. +@example +@file{filemode.c} +@end example -@menu -* A Reader's Guide to XEmacs Coding Conventions:: -* General Coding Rules:: -* Object-Oriented Techniques for C:: -* Writing Lisp Primitives:: -* Writing Good Comments:: -* Adding Global Lisp Variables:: -* Proper Use of Unsigned Types:: -* Coding for Mule:: -* Techniques for XEmacs Developers:: -@end menu +This file provides some miscellaneous functions that construct a +@samp{rwxr-xr-x}-type permissions string (as might appear in an +@file{ls}-style directory listing) given the information returned by the +@code{stat()} system call. -@node A Reader's Guide to XEmacs Coding Conventions -@section A Reader's Guide to XEmacs Coding Conventions -@cindex coding conventions -@cindex reader's guide -@cindex coding rules, naming -Of course the low-level implementation language of XEmacs is C, but much -of that uses the Lisp engine to do its work. However, because the code -is ``inside'' of the protective containment shell around the ``reactor -core,'' you'll see lots of complex ``plumbing'' needed to do the work -and ``safety mechanisms,'' whose failure results in a meltdown. This -section provides a quick overview (or review) of the various components -of the implementation of Lisp objects. - Two typographic conventions help to identify C objects that implement -Lisp objects. The first is that capitalized identifiers, especially -beginning with the letters @samp{Q}, @samp{V}, @samp{F}, and @samp{S}, -for C variables and functions, and C macros with beginning with the -letter @samp{X}, are used to implement Lisp. The second is that where -Lisp uses the hyphen @samp{-} in symbol names, the corresponding C -identifiers use the underscore @samp{_}. Of course, since XEmacs Lisp -contains interfaces to many external libraries, those external names -will follow the coding conventions their authors chose, and may overlap -the ``XEmacs name space.'' However these cases are usually pretty -obvious. +@example +@file{dired.c} +@file{ndir.h} +@end example - All Lisp objects are handled indirectly. The @code{Lisp_Object} -type is usually a pointer to a structure, except for a very small number -of types with immediate representations (currently characters and -integers). However, these types cannot be directly operated on in C -code, either, so they can also be considered indirect. Types that do -not have an immediate representation always have a C typedef -@code{Lisp_@var{type}} for a corresponding structure. -@c #### mention l(c)records here? +These files implement the XEmacs interface to directory searching. This +includes a number of primitives for determining the files in a directory +and for doing filename completion. (Remember that generic completion is +handled by a different mechanism, in @file{minibuf.c}.) - In older code, it was common practice to pass around pointers to -@code{Lisp_@var{type}}, but this is now deprecated in favor of using -@code{Lisp_Object} for all function arguments and return values that are -Lisp objects. The @code{X@var{type}} macro is used to extract the -pointer and cast it to @code{(Lisp_@var{type} *)} for the desired type. +@file{ndir.h} is a header file used for the directory-searching +emulation functions provided in @file{sysdep.c} (see section J below), +for systems that don't provide any directory-searching functions. (On +those systems, directories can be read directly as files, and parsed.) - @strong{Convention}: macros whose names begin with @samp{X} operate on -@code{Lisp_Object}s and do no type-checking. Many such macros are type -extractors, but others implement Lisp operations in C (@emph{e.g.}, -@code{XCAR} implements the Lisp @code{car} function). These are unsafe, -and must only be used where types of all data have already been checked. -Such macros are only applied to @code{Lisp_Object}s. In internal -implementations where the pointer has already been converted, the -structure is operated on directly using the C @code{->} member access -operator. - The @code{@var{type}P}, @code{CHECK_@var{type}}, and -@code{CONCHECK_@var{type}} macros are used to test types. The first -returns a Boolean value, and the latter signal errors. (The -@samp{CONCHECK} variety allows execution to be CONtinued under some -circumstances, thus the name.) Functions which expect to be passed user -data invariably call @samp{CHECK} macros on arguments. - There are many types of specialized Lisp objects implemented in C, but -the most pervasive type is the @dfn{symbol}. Symbols are used as -identifiers, variables, and functions. +@example +@file{realpath.c} +@end example - @strong{Convention}: Global variables whose names begin with @samp{Q} -are constants whose value is a symbol. The name of the variable should -be derived from the name of the symbol using the same rules as for Lisp -primitives. Such variables allow the C code to check whether a -particular @code{Lisp_Object} is equal to a given symbol. Symbols are -Lisp objects, so these variables may be passed to Lisp primitives. (An -alternative to the use of @samp{Q...} variables is to call the -@code{intern} function at initialization in the -@code{vars_of_@var{module}} function, which is hardly less efficient.) +This file provides an implementation of the @code{realpath()} function +for expanding symbolic links, on systems that don't implement it or have +a broken implementation. - @strong{Convention}: Global variables whose names begin with @samp{V} -are variables that contain Lisp objects. The convention here is that -all global variables of type @code{Lisp_Object} begin with @samp{V}, and -no others do (not even integer and boolean variables that have Lisp -equivalents). Most of the time, these variables have equivalents in -Lisp, which are defined via the @samp{DEFVAR} family of macros, but some -don't. Since the variable's value is a @code{Lisp_Object}, it can be -passed to Lisp primitives. - The implementation of Lisp primitives is more complex. -@strong{Convention}: Global variables with names beginning with @samp{S} -contain a structure that allows the Lisp engine to identify and call a C -function. In modern versions of XEmacs, these identifiers are almost -always completely hidden in the @code{DEFUN} and @code{SUBR} macros, but -you will encounter them if you look at very old versions of XEmacs or at -GNU Emacs. @strong{Convention}: Functions with names beginning with -@samp{F} implement Lisp primitives. Of course all their arguments and -their return values must be Lisp_Objects. (This is hidden in the -@code{DEFUN} macro.) +@node Modules for Other Aspects of the Lisp Interpreter and Object System, Modules for Interfacing with the Operating System, Modules for Interfacing with the File System, The Modules of XEmacs +@section Modules for Other Aspects of the Lisp Interpreter and Object System +@cindex modules for other aspects of the Lisp interpreter and object system +@cindex Lisp interpreter and object system, modules for other aspects of the +@cindex interpreter and object system, modules for other aspects of the Lisp +@cindex object system, modules for other aspects of the Lisp interpreter and -@node General Coding Rules -@section General Coding Rules -@cindex coding rules, general +@example +@file{elhash.c} +@file{elhash.h} +@file{hash.c} +@file{hash.h} +@end example -The C code is actually written in a dialect of C called @dfn{Clean C}, -meaning that it can be compiled, mostly warning-free, with either a C or -C++ compiler. Coding in Clean C has several advantages over plain C. -C++ compilers are more nit-picking, and a number of coding errors have -been found by compiling with C++. The ability to use both C and C++ -tools means that a greater variety of development tools are available to -the developer. +These files provide two implementations of hash tables. Files +@file{hash.c} and @file{hash.h} provide a generic C implementation of +hash tables which can stand independently of XEmacs. Files +@file{elhash.c} and @file{elhash.h} provide a separate implementation of +hash tables that can store only Lisp objects, and knows about Lispy +things like garbage collection, and implement the @dfn{hash-table} Lisp +object type. -Every module includes @file{<config.h>} (angle brackets so that -@samp{--srcdir} works correctly; @file{config.h} may or may not be in -the same directory as the C sources) and @file{lisp.h}. @file{config.h} -must always be included before any other header files (including -system header files) to ensure that certain tricks played by various -@file{s/} and @file{m/} files work out correctly. -When including header files, always use angle brackets, not double -quotes, except when the file to be included is always in the same -directory as the including file. If either file is a generated file, -then that is not likely to be the case. In order to understand why we -have this rule, imagine what happens when you do a build in the source -directory using @samp{./configure} and another build in another -directory using @samp{../work/configure}. There will be two different -@file{config.h} files. Which one will be used if you @samp{#include -"config.h"}? +@example +@file{specifier.c} +@file{specifier.h} +@end example -Almost every module contains a @code{syms_of_*()} function and a -@code{vars_of_*()} function. The former declares any Lisp primitives -you have defined and defines any symbols you will be using. The latter -declares any global Lisp variables you have added and initializes global -C variables in the module. @strong{Important}: There are stringent -requirements on exactly what can go into these functions. See the -comment in @file{emacs.c}. The reason for this is to avoid obscure -unwanted interactions during initialization. If you don't follow these -rules, you'll be sorry! If you want to do anything that isn't allowed, -create a @code{complex_vars_of_*()} function for it. Doing this is -tricky, though: you have to make sure your function is called at the -right time so that all the initialization dependencies work out. +This module implements the @dfn{specifier} Lisp object type. This is +primarily used for displayable properties, and allows for values that +are specific to a particular buffer, window, frame, device, or device +class, as well as a default value existing. This is used, for example, +to control the height of the horizontal scrollbar or the appearance of +the @code{default}, @code{bold}, or other faces. The specifier object +consists of a number of specifications, each of which maps from a +buffer, window, etc. to a value. The function @code{specifier-instance} +looks up a value given a window (from which a buffer, frame, and device +can be derived). -Declare each function of these kinds in @file{symsinit.h}. Make sure -it's called in the appropriate place in @file{emacs.c}. You never need -to include @file{symsinit.h} directly, because it is included by -@file{lisp.h}. -@strong{All global and static variables that are to be modifiable must -be declared uninitialized.} This means that you may not use the -``declare with initializer'' form for these variables, such as @code{int -some_variable = 0;}. The reason for this has to do with some kludges -done during the dumping process: If possible, the initialized data -segment is re-mapped so that it becomes part of the (unmodifiable) code -segment in the dumped executable. This allows this memory to be shared -among multiple running XEmacs processes. XEmacs is careful to place as -much constant data as possible into initialized variables during the -@file{temacs} phase. +@example +@file{chartab.c} +@file{chartab.h} +@file{casetab.c} +@end example -@cindex copy-on-write -@strong{Please note:} This kludge only works on a few systems nowadays, -and is rapidly becoming irrelevant because most modern operating systems -provide @dfn{copy-on-write} semantics. All data is initially shared -between processes, and a private copy is automatically made (on a -page-by-page basis) when a process first attempts to write to a page of -memory. +@file{chartab.c} and @file{chartab.h} implement the @dfn{char table} +Lisp object type, which maps from characters or certain sorts of +character ranges to Lisp objects. The implementation of this object +type is optimized for the internal representation of characters. Char +tables come in different types, which affect the allowed object types to +which a character can be mapped and also dictate certain other +properties of the char table. -Formerly, there was a requirement that static variables not be declared -inside of functions. This had to do with another hack along the same -vein as what was just described: old USG systems put statically-declared -variables in the initialized data space, so those header files had a -@code{#define static} declaration. (That way, the data-segment remapping -described above could still work.) This fails badly on static variables -inside of functions, which suddenly become automatic variables; -therefore, you weren't supposed to have any of them. This awful kludge -has been removed in XEmacs because +@cindex case table +@file{casetab.c} implements one sort of char table, the @dfn{case +table}, which maps characters to other characters of possibly different +case. These are used by XEmacs to implement case-changing primitives +and to do case-insensitive searching. -@enumerate -@item -almost all of the systems that used this kludge ended up having -to disable the data-segment remapping anyway; -@item -the only systems that didn't were extremely outdated ones; -@item -this hack completely messed up inline functions. -@end enumerate -The C source code makes heavy use of C preprocessor macros. One popular -macro style is: @example -#define FOO(var, value) do @{ \ - Lisp_Object FOO_value = (value); \ - ... /* compute using FOO_value */ \ - (var) = bar; \ -@} while (0) +@file{syntax.c} +@file{syntax.h} @end example -The @code{do @{...@} while (0)} is a standard trick to allow FOO to have -statement semantics, so that it can safely be used within an @code{if} -statement in C, for example. Multiple evaluation is prevented by -copying a supplied argument into a local variable, so that -@code{FOO(var,fun(1))} only calls @code{fun} once. - -Lisp lists are popular data structures in the C code as well as in -Elisp. There are two sets of macros that iterate over lists. -@code{EXTERNAL_LIST_LOOP_@var{n}} should be used when the list has been -supplied by the user, and cannot be trusted to be acyclic and -@code{nil}-terminated. A @code{malformed-list} or @code{circular-list} error -will be generated if the list being iterated over is not entirely -kosher. @code{LIST_LOOP_@var{n}}, on the other hand, is faster and less -safe, and can be used only on trusted lists. +@cindex scanner +This module implements @dfn{syntax tables}, another sort of char table +that maps characters into syntax classes that define the syntax of these +characters (e.g. a parenthesis belongs to a class of @samp{open} +characters that have corresponding @samp{close} characters and can be +nested). This module also implements the Lisp @dfn{scanner}, a set of +primitives for scanning over text based on syntax tables. This is used, +for example, to find the matching parenthesis in a command such as +@code{forward-sexp}, and by @file{font-lock.c} to locate quoted strings, +comments, etc. -Related macros are @code{GET_EXTERNAL_LIST_LENGTH} and -@code{GET_LIST_LENGTH}, which calculate the length of a list, and in the -case of @code{GET_EXTERNAL_LIST_LENGTH}, validating the properness of -the list. The macros @code{EXTERNAL_LIST_LOOP_DELETE_IF} and -@code{LIST_LOOP_DELETE_IF} delete elements from a lisp list satisfying some -predicate. +@c #### Break this out into a separate node somewhere! +Syntax codes are implemented as bitfields in an int. Bits 0-6 contain +the syntax code itself, bit 7 is a special prefix flag used for Lisp, +and bits 16-23 contain comment syntax flags. From the Lisp programmer's +point of view, there are 11 flags: 2 styles X 2 characters X @{start, +end@} flags for two-character comment delimiters, 2 style flags for +one-character comment delimiters, and the prefix flag. -@node Object-Oriented Techniques for C -@section Object-Oriented Techniques for C -@cindex coding rules, object-oriented -@cindex object-oriented techniques +Internally, however, the characters used in multi-character delimiters +will have non-comment-character syntax classes (@emph{e.g.}, the +@samp{/} in C's @samp{/*} comment-start delimiter has ``punctuation'' +(here meaning ``operator-like'') class in C modes). Thus in a mixed +comment style, such as C++'s @samp{//} to end of line, is represented by +giving @samp{/} the ``punctuation'' class and the ``style b first +character of start sequence'' and ``style b second character of start +sequence'' flags. The fact that class is @emph{not} punctuation allows +the syntax scanner to recognize that this is a multi-character +delimiter. The @samp{newline} character is given (single-character) +``comment-end'' @emph{class} and the ``style b first character of end +sequence'' @emph{flag}. The ``comment-end'' class allows the scanner to +determine that no second character is needed to terminate the comment. -At the lowest levels, XEmacs makes heavy use of object-oriented -techniques to promote code-sharing and uniform interfaces for different -devices and platforms. Commonly, but not always, such objects are -``wrapped'' and exported to Lisp as Lisp objects. Usually they use -the internal structures developed for Lisp objects (the @samp{lrecord} -structure) in order to take advantage of Lisp memory management. -Unfortunately, XEmacs was originally written in C, so these techniques -are based on heavy use of C macros. +There used to be a syntax class @samp{Sextword}. A character of +@samp{Sextword} class is a word-constituent but a word boundary may +exist between two such characters. Ken'ichi HANDA <handa@@etl.go.jp> +explains the purpose of the Sextword syntax category: -@c You can't use @var{} for type below, because case is important. -A module defining a class is likely to use most of the following -declarations and macros. In the following, the notation @samp{<type>} -will stand for the full name of the class, and will be capitalized in -the way normal for its context. The notation @samp{<typ>} will stand -for the abbreviated form commonly used in macro names, while @samp{ty} -will be used as the typical name for instances of the class. (See the -entry for @samp{MAYBE_<TY>METH} below for an example using all three -notations.) +@quotation +Japanese words are not separated by spaces, which makes finding word +boundaries very difficult. Theoretically it's impossible without +using natural language processing techniques. But, by defining +pseudo-words as below (much simplified for letting you understand it +easily) for Japanese, we can have a convenient forward-word function +for Japanese. -In the interface (@file{.h} file), the following declarations are used -often. Others may be used in for particular modules. Since they're -quite short in most cases, the definitions are given as well. The -generic macros used are defined in @file{lisp.h} or @file{lrecord.h}. +@display +A Japanese word is a sequence of characters that consists of +zero or more Kanji characters followed by zero or more +Hiragana characters. +@end display -@c #### reorganize this table into stuff used in general code, and stuff -@c used only in declarations or initializations -@table @samp -@c #### declaration -@item typedef struct Lisp_<Type> Lisp_<Type> -This refers to the internal structure used by C code. The XEmacs coding -style now forbids passing pointers to @samp{Lisp_<Type>} structures into -or out of a function; instead, a @samp{Lisp_Object} should be passed or -returned (created using @samp{wrap_<type>}, if necessary). +Then, the problem is that now we can't say that a sequence of +word-constituents makes up a word. For instance, both Hiragana "A" +and Kanji "KAN" are word-constituents but the sequence of these two +letters can't be a single word. -@c #### declaration -@item DECLARE_LRECORD (<type>, Lisp_<Type>) -Declares an @samp{lrecord} for @samp{<Type>}, which is the unit of -allocation. +So, we introduced Sextword for Japanese letters. +@end quotation -@item #define X<TYPE>(x) XRECORD (x, <type>, Lisp_<Type>) -Turns a @code{Lisp_Object} into a pointer to @samp{struct Lisp_<Type>}. +There seems to have been some controversy about this category, as it has +been removed, readded, and removed again. Currently neither GNU Emacs +(21.3.99) nor XEmacs (21.5.17) seems to use it. -@item #define wrap_<type>(p) wrap_record (p, <type>) -Turns a pointer to @samp{struct Lisp_<Type>} into a @code{Lisp_Object}. -@item #define <TYPE>P(x) RECORDP (x, <type>) -Tests whether a given @code{Lisp_Object} is of type @samp{Lisp_<Type>}. -Returns a C int, not a Lisp Boolean value. +@example +@file{casefiddle.c} +@end example -@item #define CHECK_<TYPE>(x) CHECK_RECORD (x, <type>) -@itemx #define CONCHECK_<TYPE>(x) CONCHECK_RECORD (x, <type>) -Tests whether a given @code{Lisp_Object} is of type @samp{Lisp_<Type>}, -and signals a Lisp error if not. The @samp{CHECK} version of the macro -never returns if the type is wrong, while the @samp{CONCHECK} version -can return if the user catches it in the debugger and explicitly -requests a return. +This module implements various Lisp primitives for upcasing, downcasing +and capitalizing strings or regions of buffers. -@item #define RAW_<TYP>METH(ty, m) ((ty)->methods->m##_method) -Return a function pointer for the method for an object @var{TY} of class -@samp{Lisp_<Type>}, or @samp{NULL} if there is none for this type. -@item #define HAS_<TYP>METH_P(ty, m) (!!RAW_<TYP>METH (ty, m)) -Test whether the class that @var{TY} is an instance of has the method. -@item #define <TYP>METH(ty, m, args) ((RAW_<TYP>METH (ty, m)) args) -Call the method on @samp{args}. @samp{args} must be enclosed in -parentheses in the call. It is the programmer's responsibility to -ensure that the method is available. The standard convenience macro -@samp{MAYBE_<TYP>METH} is often provided for the common case where a -void-returning method of @samp{Type} is called. +@example +@file{rangetab.c} +@end example + +This module implements the @dfn{range table} Lisp object type, which +provides for a mapping from ranges of integers to arbitrary Lisp +objects. + -@item #define MAYBE_<TYP>METH(ty, m, args) do @{ ... @} while (0) -Call a void-returning @samp{<Type>} method, if it exists. Note the use -of the @samp{do ... while (0)} idiom to give the macro call C statement -semantics. The full definition is equally idiomatic: @example -#define MAYBE_<TYP>METH(ty, m, args) do @{ \ - Lisp_<Type> *maybe_<typ>meth_ty = (ty); \ - if (HAS_<TYP>METH_P (maybe_<typ>meth_ty, m)) \ - <TYP>METH (maybe_<typ>meth_ty, m, args); \ -@} while (0) +@file{opaque.c} +@file{opaque.h} @end example -@end table -The use of macros for invoking an object's methods makes life a bit -difficult for the student or maintainer when browsing the code. In -particular, calls are of the form @samp{<TYP>METH (ty, some_method, (x, -y))}, but definitions typically are for @samp{<subtype>_some_method}. -Thus, when you are trying to find calls, you need to grep for -@samp{some_method}, but this will also catch calls and definitions of -that method for instances of other subtypes of @samp{<Type>}, and there -may be a rather large number of them. +This module implements the @dfn{opaque} Lisp object type, an +internal-only Lisp object that encapsulates an arbitrary block of memory +so that it can be managed by the Lisp allocation system. To create an +opaque object, you call @code{make_opaque()}, passing a pointer to a +block of memory. An object is created that is big enough to hold the +memory, which is copied into the object's storage. The object will then +stick around as long as you keep pointers to it, after which it will be +automatically reclaimed. +@cindex mark method +Opaque objects can also have an arbitrary @dfn{mark method} associated +with them, in case the block of memory contains other Lisp objects that +need to be marked for garbage-collection purposes. (If you need other +object methods, such as a finalize method, you should just go ahead and +create a new Lisp object type---it's not hard.) -@node Writing Lisp Primitives -@section Writing Lisp Primitives -@cindex writing Lisp primitives -@cindex Lisp primitives, writing -@cindex primitives, writing Lisp -Lisp primitives are Lisp functions implemented in C. The details of -interfacing the C function so that Lisp can call it are handled by a few -C macros. The only way to really understand how to write new C code is -to read the source, but we can explain some things here. -An example of a special form is the definition of @code{prog1}, from -@file{eval.c}. (An ordinary function would have the same general -appearance.) +@example +@file{abbrev.c} +@end example -@cindex garbage collection protection -@smallexample -@group -DEFUN ("prog1", Fprog1, 1, UNEVALLED, 0, /* -Similar to `progn', but the value of the first form is returned. -\(prog1 FIRST BODY...): All the arguments are evaluated sequentially. -The value of FIRST is saved during evaluation of the remaining args, -whose values are discarded. -*/ - (args)) -@{ - /* This function can GC */ - REGISTER Lisp_Object val, form, tail; - struct gcpro gcpro1; +This function provides a few primitives for doing dynamic abbreviation +expansion. In XEmacs, most of the code for this has been moved into +Lisp. Some C code remains for speed and because the primitive +@code{self-insert-command} (which is executed for all self-inserting +characters) hooks into the abbrev mechanism. (@code{self-insert-command} +is itself in C only for speed.) - val = Feval (XCAR (args)); - GCPRO1 (val); - LIST_LOOP_3 (form, XCDR (args), tail) - Feval (form); +@example +@file{doc.c} +@end example + +This function provides primitives for retrieving the documentation +strings of functions and variables. These documentation strings contain +certain special markers that get dynamically expanded (e.g. a +reverse-lookup is performed on some named functions to retrieve their +current key bindings). Some documentation strings (in particular, for +the built-in primitives and pre-loaded Lisp functions) are stored +externally in a file @file{DOC} in the @file{lib-src/} directory and +need to be fetched from that file. (Part of the build stage involves +building this file, and another part involves constructing an index for +this file and embedding it into the executable, so that the functions in +@file{doc.c} do not have to search the entire @file{DOC} file to find +the appropriate documentation string.) - UNGCPRO; - return val; -@} -@end group -@end smallexample - Let's start with a precise explanation of the arguments to the -@code{DEFUN} macro. Here is a template for them: @example -@group -DEFUN (@var{lname}, @var{fname}, @var{min_args}, @var{max_args}, @var{interactive}, /* -@var{docstring} -*/ - (@var{arglist})) -@end group +@file{md5.c} @end example -@table @var -@item lname -This string is the name of the Lisp symbol to define as the function -name; in the example above, it is @code{"prog1"}. +This function provides a Lisp primitive that implements the MD5 secure +hashing scheme, used to create a large hash value of a string of data such that +the data cannot be derived from the hash value. This is used for +various security applications on the Internet. -@item fname -This is the C function name for this function. This is the name that is -used in C code for calling the function. The name is, by convention, -@samp{F} prepended to the Lisp name, with all dashes (@samp{-}) in the -Lisp name changed to underscores. Thus, to call this function from C -code, call @code{Fprog1}. Remember that the arguments are of type -@code{Lisp_Object}; various macros and functions for creating values of -type @code{Lisp_Object} are declared in the file @file{lisp.h}. -Primitives whose names are special characters (e.g. @code{+} or -@code{<}) are named by spelling out, in some fashion, the special -character: e.g. @code{Fplus()} or @code{Flss()}. Primitives whose names -begin with normal alphanumeric characters but also contain special -characters are spelled out in some creative way, e.g. @code{let*} -becomes @code{FletX()}. -Each function also has an associated structure that holds the data for -the subr object that represents the function in Lisp. This structure -conveys the Lisp symbol name to the initialization routine that will -create the symbol and store the subr object as its definition. The C -variable name of this structure is always @samp{S} prepended to the -@var{fname}. You hardly ever need to be aware of the existence of this -structure, since @code{DEFUN} plus @code{DEFSUBR} takes care of all the -details. -@item min_args -This is the minimum number of arguments that the function requires. The -function @code{prog1} allows a minimum of one argument. +@node Modules for Interfacing with the Operating System, , Modules for Other Aspects of the Lisp Interpreter and Object System, The Modules of XEmacs +@section Modules for Interfacing with the Operating System +@cindex modules for interfacing with the operating system +@cindex interfacing with the operating system, modules for +@cindex operating system, modules for interfacing with the -@item max_args -This is the maximum number of arguments that the function accepts, if -there is a fixed maximum. Alternatively, it can be @code{UNEVALLED}, -indicating a special form that receives unevaluated arguments, or -@code{MANY}, indicating an unlimited number of evaluated arguments (the -C equivalent of @code{&rest}). Both @code{UNEVALLED} and @code{MANY} -are macros. If @var{max_args} is a number, it may not be less than -@var{min_args} and it may not be greater than 8. (If you need to add a -function with more than 8 arguments, use the @code{MANY} form. Resist -the urge to edit the definition of @code{DEFUN} in @file{lisp.h}. If -you do it anyways, make sure to also add another clause to the switch -statement in @code{primitive_funcall().}) +@example +@file{process.el} +@file{process.c} +@file{process.h} +@end example -@item interactive -This is an interactive specification, a string such as might be used as -the argument of @code{interactive} in a Lisp function. In the case of -@code{prog1}, it is 0 (a null pointer), indicating that @code{prog1} -cannot be called interactively. A value of @code{""} indicates a -function that should receive no arguments when called interactively. +These modules allow XEmacs to spawn and communicate with subprocesses +and network connections. -@item docstring -This is the documentation string. It is written just like a -documentation string for a function defined in Lisp; in particular, the -first line should be a single sentence. Note how the documentation -string is enclosed in a comment, none of the documentation is placed on -the same lines as the comment-start and comment-end characters, and the -comment-start characters are on the same line as the interactive -specification. @file{make-docfile}, which scans the C files for -documentation strings, is very particular about what it looks for, and -will not properly extract the doc string if it's not in this exact format. +@cindex synchronous subprocesses +@cindex subprocesses, synchronous + @file{process.el} implements (through the @code{call-process} +primitive) what are called @dfn{synchronous subprocesses}. This means +that XEmacs runs a program, waits till it's done, and retrieves its +output. A typical example might be calling the @file{ls} program to get +a directory listing. -In order to make both @file{etags} and @file{make-docfile} happy, make -sure that the @code{DEFUN} line contains the @var{lname} and -@var{fname}, and that the comment-start characters for the doc string -are on the same line as the interactive specification, and put a newline -directly after them (and before the comment-end characters). +@cindex asynchronous subprocesses +@cindex subprocesses, asynchronous + @file{process.c} and @file{process.h} implement @dfn{asynchronous +subprocesses}. This means that XEmacs starts a program and then +continues normally, not waiting for the process to finish. Data can be +sent to the process or retrieved from it as it's running. This is used +for the @code{shell} command (which provides a front end onto a shell +program such as @file{csh}), the mail and news readers implemented in +XEmacs, etc. The result of calling @code{start-process} to start a +subprocess is a process object, a particular kind of object used to +communicate with the subprocess. You can send data to the process by +passing the process object and the data to @code{send-process}, and you +can specify what happens to data retrieved from the process by setting +properties of the process object. (When the process sends data, XEmacs +receives a process event, which says that there is data ready. When +@code{dispatch-event} is called on this event, it reads the data from +the process and does something with it, as specified by the process +object's properties. Typically, this means inserting the data into a +buffer or calling a function.) Another property of the process object is +called the @dfn{sentinel}, which is a function that is called when the +process terminates. -@item arglist -This is the comma-separated list of arguments to the C function. For a -function with a fixed maximum number of arguments, provide a C argument -for each Lisp argument. In this case, unlike regular C functions, the -types of the arguments are not declared; they are simply always of type -@code{Lisp_Object}. +@cindex network connections + Process objects are also used for network connections (connections to a +process running on another machine). Network connections are started +with @code{open-network-stream} but otherwise work just like +subprocesses. -The names of the C arguments will be used as the names of the arguments -to the Lisp primitive as displayed in its documentation, modulo the same -concerns described above for @code{F...} names (in particular, -underscores in the C arguments become dashes in the Lisp arguments). -There is one additional kludge: A trailing `_' on the C argument is -discarded when forming the Lisp argument. This allows C language -reserved words (like @code{default}) or global symbols (like -@code{dirname}) to be used as argument names without compiler warnings -or errors. -A Lisp function with @w{@var{max_args} = @code{UNEVALLED}} is a -@w{@dfn{special form}}; its arguments are not evaluated. Instead it -receives one argument of type @code{Lisp_Object}, a (Lisp) list of the -unevaluated arguments, conventionally named @code{(args)}. +@example +@file{sysdep.c} +@file{sysdep.h} +@end example -When a Lisp function has no upper limit on the number of arguments, -specify @w{@var{max_args} = @code{MANY}}. In this case its implementation in -C actually receives exactly two arguments: the number of Lisp arguments -(an @code{int}) and the address of a block containing their values (a -@w{@code{Lisp_Object *}}). In this case only are the C types specified -in the @var{arglist}: @w{@code{(int nargs, Lisp_Object *args)}}. + These modules implement most of the low-level, messy operating-system +interface code. This includes various device control (ioctl) operations +for file descriptors, TTY's, pseudo-terminals, etc. (usually this stuff +is fairly system-dependent; thus the name of this module), and emulation +of standard library functions and system calls on systems that don't +provide them or have broken versions. -@end table -Within the function @code{Fprog1} itself, note the use of the macros -@code{GCPRO1} and @code{UNGCPRO}. @code{GCPRO1} is used to ``protect'' -a variable from garbage collection---to inform the garbage collector -that it must look in that variable and regard the object pointed at by -its contents as an accessible object. This is necessary whenever you -call @code{Feval} or anything that can directly or indirectly call -@code{Feval} (this includes the @code{QUIT} macro!). At such a time, -any Lisp object that you intend to refer to again must be protected -somehow. @code{UNGCPRO} cancels the protection of the variables that -are protected in the current function. It is necessary to do this -explicitly. -The macro @code{GCPRO1} protects just one local variable. If you want -to protect two, use @code{GCPRO2} instead; repeating @code{GCPRO1} will -not work. Macros @code{GCPRO3} and @code{GCPRO4} also exist. +@example +@file{sysdir.h} +@file{sysfile.h} +@file{sysfloat.h} +@file{sysproc.h} +@file{syspwd.h} +@file{syssignal.h} +@file{systime.h} +@file{systty.h} +@file{syswait.h} +@end example -These macros implicitly use local variables such as @code{gcpro1}; you -must declare these explicitly, with type @code{struct gcpro}. Thus, if -you use @code{GCPRO2}, you must declare @code{gcpro1} and @code{gcpro2}. +These header files provide consistent interfaces onto system-dependent +header files and system calls. The idea is that, instead of including a +standard header file like @file{<sys/param.h>} (which may or may not +exist on various systems) or having to worry about whether all system +provide a particular preprocessor constant, or having to deal with the +four different paradigms for manipulating signals, you just include the +appropriate @file{sys*.h} header file, which includes all the right +system header files, defines and missing preprocessor constants, +provides a uniform interface onto system calls, etc. -@cindex caller-protects (@code{GCPRO} rule) -Note also that the general rule is @dfn{caller-protects}; i.e. you are -only responsible for protecting those Lisp objects that you create. Any -objects passed to you as arguments should have been protected by whoever -created them, so you don't in general have to protect them. +@file{sysdir.h} provides a uniform interface onto directory-querying +functions. (In some cases, this is in conjunction with emulation +functions in @file{sysdep.c}.) -In particular, the arguments to any Lisp primitive are always -automatically @code{GCPRO}ed, when called ``normally'' from Lisp code or -bytecode. So only a few Lisp primitives that are called frequently from -C code, such as @code{Fprogn} protect their arguments as a service to -their caller. You don't need to protect your arguments when writing a -new @code{DEFUN}. +@file{sysfile.h} includes all the necessary header files for standard +system calls (e.g. @code{read()}), ensures that all necessary +@code{open()} and @code{stat()} preprocessor constants are defined, and +possibly (usually) substitutes sugared versions of @code{read()}, +@code{write()}, etc. that automatically restart interrupted I/O +operations. -@code{GCPRO}ing is perhaps the trickiest and most error-prone part of -XEmacs coding. It is @strong{extremely} important that you get this -right and use a great deal of discipline when writing this code. -@xref{GCPROing, ,@code{GCPRO}ing}, for full details on how to do this. +@file{sysfloat.h} includes the necessary header files for floating-point +operations. -What @code{DEFUN} actually does is declare a global structure of type -@code{Lisp_Subr} whose name begins with capital @samp{SF} and which -contains information about the primitive (e.g. a pointer to the -function, its minimum and maximum allowed arguments, a string describing -its Lisp name); @code{DEFUN} then begins a normal C function declaration -using the @code{F...} name. The Lisp subr object that is the function -definition of a primitive (i.e. the object in the function slot of the -symbol that names the primitive) actually points to this @samp{SF} -structure; when @code{Feval} encounters a subr, it looks in the -structure to find out how to call the C function. +@file{sysproc.h} includes the necessary header files for calling +@code{select()}, @code{fork()}, @code{execve()}, socket operations, and +the like, and ensures that the @code{FD_*()} macros for descriptor-set +manipulations are available. -Defining the C function is not enough to make a Lisp primitive -available; you must also create the Lisp symbol for the primitive (the -symbol is @dfn{interned}; @pxref{Obarrays}) and store a suitable subr -object in its function cell. (If you don't do this, the primitive won't -be seen by Lisp code.) The code looks like this: +@file{syspwd.h} includes the necessary header files for obtaining +information from @file{/etc/passwd} (the functions are emulated under +VMS). -@example -DEFSUBR (@var{fname}); -@end example +@file{syssignal.h} includes the necessary header files for +signal-handling and provides a uniform interface onto the different +signal-handling and signal-blocking paradigms. -@noindent -Here @var{fname} is the same name you used as the second argument to -@code{DEFUN}. +@file{systime.h} includes the necessary header files and provides +uniform interfaces for retrieving the time of day, setting file +access/modification times, getting the amount of time used by the XEmacs +process, etc. -This call to @code{DEFSUBR} should go in the @code{syms_of_*()} function -at the end of the module. If no such function exists, create it and -make sure to also declare it in @file{symsinit.h} and call it from the -appropriate spot in @code{main()}. @xref{General Coding Rules}. +@file{systty.h} buffers against the infinitude of different ways of +controlling TTY's. -Note that C code cannot call functions by name unless they are defined -in C. The way to call a function written in Lisp from C is to use -@code{Ffuncall}, which embodies the Lisp function @code{funcall}. Since -the Lisp function @code{funcall} accepts an unlimited number of -arguments, in C it takes two: the number of Lisp-level arguments, and a -one-dimensional array containing their values. The first Lisp-level -argument is the Lisp function to call, and the rest are the arguments to -pass to it. Since @code{Ffuncall} can call the evaluator, you must -protect pointers from garbage collection around the call to -@code{Ffuncall}. (However, @code{Ffuncall} explicitly protects all of -its parameters, so you don't have to protect any pointers passed as -parameters to it.) +@file{syswait.h} provides a uniform way of retrieving the exit status +from a @code{wait()}ed-on process (some systems use a union, others use +an int). -The C functions @code{call0}, @code{call1}, @code{call2}, and so on, -provide handy ways to call a Lisp function conveniently with a fixed -number of arguments. They work by calling @code{Ffuncall}. -@file{eval.c} is a very good file to look through for examples; -@file{lisp.h} contains the definitions for important macros and -functions. -@node Writing Good Comments -@section Writing Good Comments -@cindex writing good comments -@cindex comments, writing good +@example +@file{hpplay.c} +@file{libsst.c} +@file{libsst.h} +@file{libst.h} +@file{linuxplay.c} +@file{nas.c} +@file{sgiplay.c} +@file{sound.c} +@file{sunplay.c} +@end example -Comments are a lifeline for programmers trying to understand tricky -code. In general, the less obvious it is what you are doing, the more -you need a comment, and the more detailed it needs to be. You should -always be on guard when you're writing code for stuff that's tricky, and -should constantly be putting yourself in someone else's shoes and asking -if that person could figure out without much difficulty what's going -on. (Assume they are a competent programmer who understands the -essentials of how the XEmacs code is structured but doesn't know much -about the module you're working on or any algorithms you're using.) If -you're not sure whether they would be able to, add a comment. Always -err on the side of more comments, rather than less. +These files implement the ability to play various sounds on some types +of computers. You have to configure your XEmacs with sound support in +order to get this capability. -Generally, when making comments, there is no need to attribute them with -your name or initials. This especially goes for small, -easy-to-understand, non-opinionated ones. Also, comments indicating -where, when, and by whom a file was changed are @emph{strongly} -discouraged, and in general will be removed as they are discovered. -This is exactly what @file{ChangeLogs} are there for. However, it can -occasionally be useful to mark exactly where (but not when or by whom) -changes are made, particularly when making small changes to a file -imported from elsewhere. These marks help when later on a newer version -of the file is imported and the changes need to be merged. (If -everything were always kept in CVS, there would be no need for this. -But in practice, this often doesn't happen, or the CVS repository is -later on lost or unavailable to the person doing the update.) +@file{sound.c} provides the generic interface. It implements various +Lisp primitives and variables that let you specify which sounds should +be played in certain conditions. (The conditions are identified by +symbols, which are passed to @code{ding} to make a sound. Various +standard functions call this function at certain times; if sound support +does not exist, a simple beep results. -When putting in an explicit opinion in a comment, you should -@emph{always} attribute it with your name and the date. This also goes -for long, complex comments explaining in detail the workings of -something -- by putting your name there, you make it possible for -someone who has questions about how that thing works to determine who -wrote the comment so they can write to them. Use your actual name or -your alias at xemacs.org, and not your initials or nickname, unless that -is generally recognized (e.g. @samp{jwz}). Even then, please consider -requesting a virtual user at xemacs.org (forwarding address; we can't -provide an actual mailbox). Otherwise, give first and last name. If -you're not a regular contributor, you might consider putting your email -address in -- it may be in the ChangeLog, but after awhile ChangeLogs -have a tendency of disappearing or getting muddled. (E.g. your comment -may get copied somewhere else or even into another program, and tracking -down the proper ChangeLog may be very difficult.) +@cindex native sound +@cindex sound, native +@file{sgiplay.c}, @file{sunplay.c}, @file{hpplay.c}, and +@file{linuxplay.c} interface to the machine's speaker for various +different kind of machines. This is called @dfn{native} sound. -If you come across an opinion that is not or is no longer valid, or you -come across any comment that no longer applies but you want to keep it -around, enclose it in @samp{[[ } and @samp{ ]]} marks and add a comment -afterwards explaining why the preceding comment is no longer valid. Put -your name on this comment, as explained above. +@cindex sound, network +@cindex network sound +@cindex NAS +@file{nas.c} interfaces to a computer somewhere else on the network +using the NAS (Network Audio Server) protocol, playing sounds on that +machine. This allows you to run XEmacs on a remote machine, with its +display set to your local machine, and have the sounds be made on your +local machine, provided that you have a NAS server running on your local +machine. -Just as comments are a lifeline to programmers, incorrect comments are -death. If you come across an incorrect comment, @strong{immediately} -correct it or flag it as incorrect, as described in the previous -paragraph. Whenever you work on a section of code, @emph{always} make -sure to update any comments to be correct -- or, at the very least, flag -them as incorrect. +@file{libsst.c}, @file{libsst.h}, and @file{libst.h} provide some +additional functions for playing sound on a Sun SPARC but are not +currently in use. -To indicate a "todo" or other problem, use four pound signs -- -i.e. @samp{####}. -@node Adding Global Lisp Variables -@section Adding Global Lisp Variables -@cindex global Lisp variables, adding -@cindex variables, adding global Lisp -Global variables whose names begin with @samp{Q} are constants whose -value is a symbol of a particular name. The name of the variable should -be derived from the name of the symbol using the same rules as for Lisp -primitives. These variables are initialized using a call to -@code{defsymbol()} in the @code{syms_of_*()} function. (This call -interns a symbol, sets the C variable to the resulting Lisp object, and -calls @code{staticpro()} on the C variable to tell the -garbage-collection mechanism about this variable. What -@code{staticpro()} does is add a pointer to the variable to a large -global array; when garbage-collection happens, all pointers listed in -the array are used as starting points for marking Lisp objects. This is -important because it's quite possible that the only current reference to -the object is the C variable. In the case of symbols, the -@code{staticpro()} doesn't matter all that much because the symbol is -contained in @code{obarray}, which is itself @code{staticpro()}ed. -However, it's possible that a naughty user could do something like -uninterning the symbol out of @code{obarray} or even setting -@code{obarray} to a different value [although this is likely to make -XEmacs crash!].) +@example +@file{tooltalk.c} +@file{tooltalk.h} +@end example - @strong{Please note:} It is potentially deadly if you declare a -@samp{Q...} variable in two different modules. The two calls to -@code{defsymbol()} are no problem, but some linkers will complain about -multiply-defined symbols. The most insidious aspect of this is that -often the link will succeed anyway, but then the resulting executable -will sometimes crash in obscure ways during certain operations! +These two modules implement an interface to the ToolTalk protocol, which +is an interprocess communication protocol implemented on some versions +of Unix. ToolTalk is a high-level protocol that allows processes to +register themselves as providers of particular services; other processes +can then request a service without knowing or caring exactly who is +providing the service. It is similar in spirit to the DDE protocol +provided under Microsoft Windows. ToolTalk is a part of the new CDE +(Common Desktop Environment) specification and is used to connect the +parts of the SPARCWorks development environment. -To avoid this problem, declare any symbols with common names (such as -@code{text}) that are not obviously associated with this particular -module in the file @file{general-slots.h}. The ``-slots'' suffix -indicates that this is a file that is included multiple times in -@file{general.c}. Redefinition of preprocessor macros allows the -effects to be different in each context, so this is actually more -convenient and less error-prone than doing it in your module. - Global variables whose names begin with @samp{V} are variables that -contain Lisp objects. The convention here is that all global variables -of type @code{Lisp_Object} begin with @samp{V}, and all others don't -(including integer and boolean variables that have Lisp -equivalents). Most of the time, these variables have equivalents in -Lisp, but some don't. Those that do are declared this way by a call to -@code{DEFVAR_LISP()} in the @code{vars_of_*()} initializer for the -module. What this does is create a special @dfn{symbol-value-forward} -Lisp object that contains a pointer to the C variable, intern a symbol -whose name is as specified in the call to @code{DEFVAR_LISP()}, and set -its value to the symbol-value-forward Lisp object; it also calls -@code{staticpro()} on the C variable to tell the garbage-collection -mechanism about the variable. When @code{eval} (or actually -@code{symbol-value}) encounters this special object in the process of -retrieving a variable's value, it follows the indirection to the C -variable and gets its value. @code{setq} does similar things so that -the C variable gets changed. - Whether or not you @code{DEFVAR_LISP()} a variable, you need to -initialize it in the @code{vars_of_*()} function; otherwise it will end -up as all zeroes, which is the integer 0 (@emph{not} @code{nil}), and -this is probably not what you want. Also, if the variable is not -@code{DEFVAR_LISP()}ed, @strong{you must call} @code{staticpro()} on the -C variable in the @code{vars_of_*()} function. Otherwise, the -garbage-collection mechanism won't know that the object in this variable -is in use, and will happily collect it and reuse its storage for another -Lisp object, and you will be the one who's unhappy when you can't figure -out how your variable got overwritten. +@example +@file{getloadavg.c} +@end example -@node Proper Use of Unsigned Types -@section Proper Use of Unsigned Types -@cindex unsigned types, proper use of -@cindex types, proper use of unsigned +This module provides the ability to retrieve the system's current load +average. (The way to do this is highly system-specific, unfortunately, +and requires a lot of special-case code.) -Avoid using @code{unsigned int} and @code{unsigned long} whenever -possible. Unsigned types are viral -- any arithmetic or comparisons -involving mixed signed and unsigned types are automatically converted to -unsigned, which is almost certainly not what you want. Many subtle and -hard-to-find bugs are created by careless use of unsigned types. In -general, you should almost @emph{never} use an unsigned type to hold a -regular quantity of any sort. The only exceptions are -@enumerate -@item -When there's a reasonable possibility you will actually need all 32 or -64 bits to store the quantity. -@item -When calling existing API's that require unsigned types. In this case, -you should still do all manipulation using signed types, and do the -conversion at the very threshold of the API call. -@item -In existing code that you don't want to modify because you don't -maintain it. -@item -In bit-field structures. -@end enumerate -Other reasonable uses of @code{unsigned int} and @code{unsigned long} -are representing non-quantities -- e.g. bit-oriented flags and such. +@example +@file{sunpro.c} +@end example -@node Coding for Mule -@section Coding for Mule -@cindex coding for Mule -@cindex Mule, coding for +This module provides a small amount of code used internally at Sun to +keep statistics on the usage of XEmacs. -Although Mule support is not compiled by default in XEmacs, many people -are using it, and we consider it crucial that new code works correctly -with multibyte characters. This is not hard; it is only a matter of -following several simple user-interface guidelines. Even if you never -compile with Mule, with a little practice you will find it quite easy -to code Mule-correctly. -Note that these guidelines are not necessarily tied to the current Mule -implementation; they are also a good idea to follow on the grounds of -code generalization for future I18N work. + +@example +@file{broken-sun.h} +@file{strcmp.c} +@file{strcpy.c} +@file{sunOS-fix.c} +@end example + +These files provide replacement functions and prototypes to fix numerous +bugs in early releases of SunOS 4.1. + + + +@example +@file{hftctl.c} +@end example + +This module provides some terminal-control code necessary on versions of +AIX prior to 4.1. + +@node Rules When Writing New C Code, Regression Testing XEmacs, The Modules of XEmacs, Top +@chapter Rules When Writing New C Code +@cindex writing new C code, rules when +@cindex C code, rules when writing new +@cindex code, rules when writing new C + +The XEmacs C Code is extremely complex and intricate, and there are many +rules that are more or less consistently followed throughout the code. +Many of these rules are not obvious, so they are explained here. It is +of the utmost importance that you follow them. If you don't, you may +get something that appears to work, but which will crash in odd +situations, often in code far away from where the actual breakage is. @menu -* Character-Related Data Types:: -* Working With Character and Byte Positions:: -* Conversion to and from External Data:: -* General Guidelines for Writing Mule-Aware Code:: -* An Example of Mule-Aware Code:: -* Mule-izing Code:: +* Introduction to Writing C Code:: +* Writing New Modules:: +* Working with Lisp Objects:: +* Writing Lisp Primitives:: +* Writing Good Comments:: +* Adding Global Lisp Variables:: +* Writing Macros:: +* Proper Use of Unsigned Types:: +* Major Textual Changes:: +* Debugging and Testing:: @end menu -@node Character-Related Data Types -@subsection Character-Related Data Types -@cindex character-related data types -@cindex data types, character-related +See also @ref{Coding for Mule}. -First, let's review the basic character-related datatypes used by -XEmacs. Note that some of the separate @code{typedef}s are not -mandatory, but they improve clarity of code a great deal, because one -glance at the declaration can tell the intended use of the variable. +@node Introduction to Writing C Code, Writing New Modules, Rules When Writing New C Code, Rules When Writing New C Code +@section Introduction to Writing C Code +@cindex introduction to writing c code +@cindex coding conventions -@table @code -@item Ichar -@cindex Ichar -An @code{Ichar} holds a single Emacs character. +The C code is actually written in a dialect of C called @dfn{Clean C}, +meaning that it can be compiled, mostly warning-free, with either a C +or C++ compiler. Coding in Clean C has several advantages over plain +C. C++ compilers are more nit-picking, and a number of coding errors +have been found by compiling with C++. The ability to use both C and +C++ tools means that a greater variety of development tools are +available to the developer. In addition, the ability to overload +operators in C++ means it is possible, for error-checking purposes, to +redefine certain simple types (normally defined as aliases for simple +built-in types such as @code{unsigned char} or @code{long}) as +classes, strictly limiting the permissible operations and catching +illegal implicit casts and such. + +XEmacs follows the GNU coding standards, which are documented +separately in @xref{top,,, standards, GNU Coding Standards}. This +section mainly documents standards that are not included in that +document; typically this consists of standards that are specifically +relevant to the XEmacs code itself. -Obviously, the equality between characters and bytes is lost in the Mule -world. Characters can be represented by one or more bytes in the -buffer, and @code{Ichar} is a C type large enough to hold any -character. (This currently isn't quite true for ISO 10646, which -defines a character as a 31-bit non-negative quantity, while XEmacs -characters are only 30-bits. This is irrelevant, unless you are -considering using the ISO 10646 private groups to support really large -private character sets---in particular, the Mule character set!---in -a version of XEmacs using Unicode internally.) +First, a recap of the GNU standards: -Without Mule support, an @code{Ichar} is equivalent to an -@code{unsigned char}. [[This doesn't seem to be true; @file{lisp.h} -unconditionally @samp{typedef}s @code{Ichar} to @code{int}.]] +@itemize @bullet +@item +Put a space after every comma. +@item +Put a space before the parenthesis that begins a function call, +macro call, function declaration or definition, or control +statement (if, while, switch, for). (DO NOT do this for macro +definitions; this is invalid preprocessor syntax.) +@item +The brace that begins a control statement (if, while, for, switch, +do) or a function definition should go on a line by itself. +@item +In function definitions, put the return type and all other +qualifiers on a line before the function name. Thus, the function +name is always at the beginning of a line. +@item +Indentation level is two spaces. (However, the first and following +statements of a while/for/if/etc. block are indented four spaces +from the while/for/if keyword. The opening and closing braces are +indented two spaces.) +@item +Variable and function names should be all lowercase, with underscores +separating words, except for a prefixing tag, which may be in +uppercase. Do not use the mixed-case convention (e.g. +SetVariableToValue ()) and *especially* do not use Microsoft +Hungarian notation (char **rgszRedundantTag). +@item +preprocessor and enum constants should be all uppercase, and should +be prefixed with a tag that groups related constants together. +@end itemize -@item Ibyte -@cindex Ibyte -The data representing the text in a buffer or string is logically a set -of @code{Ibyte}s. +Now, the XEmacs coding standards: -XEmacs does not work with the same character formats all the time; when -reading characters from the outside, it decodes them to an internal -format, and likewise encodes them when writing. @code{Ibyte} (in fact -@code{unsigned char}) is the basic unit of XEmacs internal buffers and -strings format. An @code{Ibyte *} is the type that points at text -encoded in the variable-width internal encoding. +@subheading Specially-prefixed functions/variables: -One character can correspond to one or more @code{Ibyte}s. In the -current Mule implementation, an ASCII character is represented by the -same @code{Ibyte}, and other characters are represented by a sequence -of two or more @code{Ibyte}s. (This will also be true of an -implementation using UTF-8 as the internal encoding. In fact, only code -that implements character code conversions and a very few macros used to -implement motion by whole characters will notice the difference between -UTF-8 and the Mule encoding.) +@itemize @bullet +@item +All global C variables whose value is constant and is a symbol begin +with a capital Q, e.g. Qkey_press_event. (The type will always be +Lisp_Object.) +@item +All other global C variables whose value is a Lisp_Object (this +includes variables that forward into Lisp variables plus others like +Vselected_console) begin with a capital V. +@item +No C variables whose value is other than a Lisp_Object should begin +with a capital V. (This includes C variables that forward into +integer or boolean Lisp variables.) +@item +All global C variables whose value is a struct Lisp_Subr begin with a +capital S. (This only occurs in connection with DEFUN ()). +@item +All C functions that are Lisp primitives begin with a capital F, +and no others should begin this way. +@end itemize -Without Mule support, there are exactly 256 characters, implicitly -Latin-1, and each character is represented using one @code{Ibyte}, and -there is a one-to-one correspondence between @code{Ibyte}s and -@code{Ichar}s. - -@item Charxpos -@item Charbpos -@itemx Charcount -@cindex Charxpos -@cindex Charbpos -@cindex Charcount -A @code{Charbpos} represents a character position in a buffer. A -@code{Charcount} represents a number (count) of characters. Logically, -subtracting two @code{Charbpos} values yields a @code{Charcount} value. -When representing a character position in a string, we just use -@code{Charcount} directly. The reason for having a separate typedef for -buffer positions is that they are 1-based, whereas string positions are -0-based and hence string counts and positions can be freely intermixed (a -string position is equivalent to the count of characters from the -beginning). When representing a character position that could be either -in a buffer or string (for example, in the extent code), @code{Charxpos} -is used. Although all of these are @code{typedef}ed to -@code{EMACS_INT}, we use them in preference to @code{EMACS_INT} to make -it clear what sort of position is being used. +@subheading Functions for manipulating Lisp types: -@code{Charxpos}, @code{Charbpos} and @code{Charcount} values are the -only ones that are ever visible to Lisp. +@itemize @bullet +@item +Any function that creates an empty or mostly empty Lisp object +should begin allocate_(). (*Not* make_().) (Except, of course, +for Lisp primitives, which usually begin Fmake_()). +@item +Any function that converts a pointer into an equivalent Lisp_Object +should begin make_(). +@item +Any function that converts a Lisp_Object into its equivalent pointer +and checks the type and validity of the object (e.g. making sure +it's not dead) should begin decode_(). +@item +Any function that looks up a Lisp object (e.g. buffer, face) given +a symbol or string should begin get_(). (Except, of course, for +Lisp primitives, which usually begin Fget_()). +@end itemize -@item Bytexpos -@itemx Bytecount -@cindex Bytebpos -@cindex Bytecount -A @code{Bytebpos} represents a byte position in a buffer. A -@code{Bytecount} represents the distance between two positions, in -bytes. Byte positions in strings use @code{Bytecount}, and for byte -positions that can be either in a buffer or string, @code{Bytexpos} is -used. The relationship between @code{Bytexpos}, @code{Bytebpos} and -@code{Bytecount} is the same as the relationship between -@code{Charxpos}, @code{Charbpos} and @code{Charcount}. +@subheading Other: -@item Extbyte -@cindex Extbyte -When dealing with the outside world, XEmacs works with @code{Extbyte}s, -which are equivalent to @code{char}. The distance between two -@code{Extbyte}s is a @code{Bytecount}, since external text is a -byte-by-byte encoding. Extbytes occur mainly at the transition point -between internal text and external functions. XEmacs code should not, -if it can possibly avoid it, do any actual manipulation using external -text, since its format is completely unpredictable (it might not even be -ASCII-compatible). -@end table +@itemize @bullet +@item +Any header-file declarations of the sort -@node Working With Character and Byte Positions -@subsection Working With Character and Byte Positions -@cindex character and byte positions, working with -@cindex byte positions, working with character and -@cindex positions, working with character and byte +struct foobar; -Now that we have defined the basic character-related types, we can look -at the macros and functions designed for work with them and for -conversion between them. Most of these macros are defined in -@file{buffer.h}, and we don't discuss all of them here, but only the -most important ones. Examining the existing code is the best way to -learn about them. +go into the "types" section of lisp.h. +@end itemize -@table @code -@item MAX_ICHAR_LEN -@cindex MAX_ICHAR_LEN -This preprocessor constant is the maximum number of buffer bytes to -represent an Emacs character in the variable width internal encoding. -It is useful when allocating temporary strings to keep a known number of -characters. For instance: +@node Writing New Modules, Working with Lisp Objects, Introduction to Writing C Code, Rules When Writing New C Code +@section Writing New Modules +@cindex writing new modules -@example -@group -@{ - Charcount cclen; - ... - @{ - /* Allocate place for @var{cclen} characters. */ - Ibyte *buf = (Ibyte *) alloca (cclen * MAX_ICHAR_LEN); -... -@end group -@end example +Every module includes @file{<config.h>} (angle brackets so that +@samp{--srcdir} works correctly; @file{config.h} may or may not be in +the same directory as the C sources) and @file{lisp.h}. @file{config.h} +must always be included before any other header files (including +system header files) to ensure that certain tricks played by various +@file{s/} and @file{m/} files work out correctly. -If you followed the previous section, you can guess that, logically, -multiplying a @code{Charcount} value with @code{MAX_ICHAR_LEN} produces -a @code{Bytecount} value. +When including header files, always use angle brackets, not double +quotes, except when the file to be included is always in the same +directory as the including file. If either file is a generated file, +then that is not likely to be the case. In order to understand why we +have this rule, imagine what happens when you do a build in the source +directory using @samp{./configure} and another build in another +directory using @samp{../work/configure}. There will be two different +@file{config.h} files. Which one will be used if you @samp{#include +"config.h"}? -In the current Mule implementation, @code{MAX_ICHAR_LEN} equals 4. -Without Mule, it is 1. In a mature Unicode-based XEmacs, it will also -be 4 (since all Unicode characters can be encoded in UTF-8 in 4 bytes or -less), but some versions may use up to 6, in order to use the large -private space provided by ISO 10646 to ``mirror'' the Mule code space. +Almost every module contains a @code{syms_of_*()} function and a +@code{vars_of_*()} function. The former declares any Lisp primitives +you have defined and defines any symbols you will be using. The latter +declares any global Lisp variables you have added and initializes global +C variables in the module. @strong{Important}: There are stringent +requirements on exactly what can go into these functions. See the +comment in @file{emacs.c}. The reason for this is to avoid obscure +unwanted interactions during initialization. If you don't follow these +rules, you'll be sorry! If you want to do anything that isn't allowed, +create a @code{complex_vars_of_*()} function for it. Doing this is +tricky, though: you have to make sure your function is called at the +right time so that all the initialization dependencies work out. -@item itext_ichar -@itemx set_itext_ichar -@cindex itext_ichar -@cindex set_itext_ichar -The @code{itext_ichar} macro takes a @code{Ibyte} pointer and -returns the @code{Ichar} stored at that position. If it were a -function, its prototype would be: +Declare each function of these kinds in @file{symsinit.h}. Make sure +it's called in the appropriate place in @file{emacs.c}. You never need +to include @file{symsinit.h} directly, because it is included by +@file{lisp.h}. -@example -Ichar itext_ichar (Ibyte *p); -@end example +@strong{All global and static variables that are to be modifiable must +be declared uninitialized.} This means that you may not use the +``declare with initializer'' form for these variables, such as @code{int +some_variable = 0;}. The reason for this has to do with some kludges +done during the dumping process: If possible, the initialized data +segment is re-mapped so that it becomes part of the (unmodifiable) code +segment in the dumped executable. This allows this memory to be shared +among multiple running XEmacs processes. XEmacs is careful to place as +much constant data as possible into initialized variables during the +@file{temacs} phase. -@code{set_itext_ichar} stores an @code{Ichar} to the specified byte -position. It returns the number of bytes stored: +@cindex copy-on-write +@strong{Please note:} This kludge only works on a few systems nowadays, +and is rapidly becoming irrelevant because most modern operating systems +provide @dfn{copy-on-write} semantics. All data is initially shared +between processes, and a private copy is automatically made (on a +page-by-page basis) when a process first attempts to write to a page of +memory. -@example -Bytecount set_itext_ichar (Ibyte *p, Ichar c); -@end example +Formerly, there was a requirement that static variables not be declared +inside of functions. This had to do with another hack along the same +vein as what was just described: old USG systems put statically-declared +variables in the initialized data space, so those header files had a +@code{#define static} declaration. (That way, the data-segment remapping +described above could still work.) This fails badly on static variables +inside of functions, which suddenly become automatic variables; +therefore, you weren't supposed to have any of them. This awful kludge +has been removed in XEmacs because -It is important to note that @code{set_itext_ichar} is safe only for -appending a character at the end of a buffer, not for overwriting a -character in the middle. This is because the width of characters -varies, and @code{set_itext_ichar} cannot resize the string if it -writes, say, a two-byte character where a single-byte character used to -reside. +@enumerate +@item +almost all of the systems that used this kludge ended up having +to disable the data-segment remapping anyway; +@item +the only systems that didn't were extremely outdated ones; +@item +this hack completely messed up inline functions. +@end enumerate -A typical use of @code{set_itext_ichar} can be demonstrated by this -example, which copies characters from buffer @var{buf} to a temporary -string of Ibytes. +Here are things to know when you create a new source file: -@example -@group -@{ - Charbpos pos; - for (pos = beg; pos < end; pos++) - @{ - Ichar c = BUF_FETCH_CHAR (buf, pos); - p += set_itext_ichar (buf, c); - @} -@} -@end group -@end example +@itemize @bullet +@item +All @file{.c} files should @code{#include <config.h>} first. Almost all +@file{.c} files should @code{#include "lisp.h"} second. -Note how @code{set_itext_ichar} is used to store the @code{Ichar} -and increment the counter, at the same time. +@item +Generated header files should be included using the @samp{#include <...>} +syntax, not the @samp{#include "..."} syntax. The generated headers are: -@item INC_IBYTEPTR -@itemx DEC_IBYTEPTR -@cindex INC_IBYTEPTR -@cindex DEC_IBYTEPTR -These two macros increment and decrement an @code{Ibyte} pointer, -respectively. They will adjust the pointer by the appropriate number of -bytes according to the byte length of the character stored there. Both -macros assume that the memory address is located at the beginning of a -valid character. +@file{config.h sheap-adjust.h paths.h Emacs.ad.h} -Without Mule support, @code{INC_IBYTEPTR (p)} and @code{DEC_IBYTEPTR (p)} -simply expand to @code{p++} and @code{p--}, respectively. +The basic rule is that you should assume builds using @samp{--srcdir} +and the @samp{#include <...>} syntax needs to be used when the +to-be-included generated file is in a potentially different directory +@emph{at compile time}. The non-obvious C rule is that +@samp{#include "..."} means to search for the included file in the same +directory as the including file, @emph{not} in the current directory. +Normally this is not a problem but when building with @samp{--srcdir}, +@file{make} will search the @samp{VPATH} for you, while the C compiler +knows nothing about it. -@item bytecount_to_charcount -@cindex bytecount_to_charcount -Given a pointer to a text string and a length in bytes, return the -equivalent length in characters. +@item +Header files should @emph{not} include @samp{<config.h>} and +@samp{"lisp.h"}. It is the responsibility of the @file{.c} files that +use it to do so. -@example -Charcount bytecount_to_charcount (Ibyte *p, Bytecount bc); -@end example +@end itemize -@item charcount_to_bytecount -@cindex charcount_to_bytecount -Given a pointer to a text string and a length in characters, return the -equivalent length in bytes. +@node Working with Lisp Objects, Writing Lisp Primitives, Writing New Modules, Rules When Writing New C Code +@section Working with Lisp Objects +@cindex working with lisp objects -@example -Bytecount charcount_to_bytecount (Ibyte *p, Charcount cc); -@end example +@subheading Conventions involving Lisp objects -@item itext_n_addr -@cindex itext_n_addr -Return a pointer to the beginning of the character offset @var{cc} (in -characters) from @var{p}. +Of course the low-level implementation language of XEmacs is C, but much +of that uses the Lisp engine to do its work. However, because the code +is ``inside'' of the protective containment shell around the ``reactor +core,'' you'll see lots of complex ``plumbing'' needed to do the work +and ``safety mechanisms,'' whose failure results in a meltdown. This +section provides a quick overview (or review) of the various components +of the implementation of Lisp objects. -@example -Ibyte *itext_n_addr (Ibyte *p, Charcount cc); -@end example -@end table - -@node Conversion to and from External Data -@subsection Conversion to and from External Data -@cindex conversion to and from external data -@cindex external data, conversion to and from + Two typographic conventions help to identify C objects that implement +Lisp objects. The first is that capitalized identifiers, especially +beginning with the letters @samp{Q}, @samp{V}, @samp{F}, and @samp{S}, +for C variables and functions, and C macros with beginning with the +letter @samp{X}, are used to implement Lisp. The second is that where +Lisp uses the hyphen @samp{-} in symbol names, the corresponding C +identifiers use the underscore @samp{_}. Of course, since XEmacs Lisp +contains interfaces to many external libraries, those external names +will follow the coding conventions their authors chose, and may overlap +the ``XEmacs name space.'' However these cases are usually pretty +obvious. -When an external function, such as a C library function, returns a -@code{char} pointer, you should almost never treat it as @code{Ibyte}. -This is because these returned strings may contain 8bit characters which -can be misinterpreted by XEmacs, and cause a crash. Likewise, when -exporting a piece of internal text to the outside world, you should -always convert it to an appropriate external encoding, lest the internal -stuff (such as the infamous \201 characters) leak out. + All Lisp objects are handled indirectly. The @code{Lisp_Object} +type is usually a pointer to a structure, except for a very small number +of types with immediate representations (currently characters and +integers). However, these types cannot be directly operated on in C +code, either, so they can also be considered indirect. Types that do +not have an immediate representation always have a C typedef +@code{Lisp_@var{type}} for a corresponding structure. +@c #### mention l(c)records here? -The interface to conversion between the internal and external -representations of text are the numerous conversion macros defined in -@file{buffer.h}. There used to be a fixed set of external formats -supported by these macros, but now any coding system can be used with -them. The coding system alias mechanism is used to create the -following logical coding systems, which replace the fixed external -formats. The (dontusethis-set-symbol-value-handler) mechanism was -enhanced to make this possible (more work on that is needed). + In older code, it was common practice to pass around pointers to +@code{Lisp_@var{type}}, but this is now deprecated in favor of using +@code{Lisp_Object} for all function arguments and return values that are +Lisp objects. The @code{X@var{type}} macro is used to extract the +pointer and cast it to @code{(Lisp_@var{type} *)} for the desired type. -Often useful coding systems: + @strong{Convention}: macros whose names begin with @samp{X} operate on +@code{Lisp_Object}s and do no type-checking. Many such macros are type +extractors, but others implement Lisp operations in C (@emph{e.g.}, +@code{XCAR} implements the Lisp @code{car} function). These are unsafe, +and must only be used where types of all data have already been checked. +Such macros are only applied to @code{Lisp_Object}s. In internal +implementations where the pointer has already been converted, the +structure is operated on directly using the C @code{->} member access +operator. -@table @code -@item Qbinary -This is the simplest format and is what we use in the absence of a more -appropriate format. This converts according to the @code{binary} coding -system: + The @code{@var{type}P}, @code{CHECK_@var{type}}, and +@code{CONCHECK_@var{type}} macros are used to test types. The first +returns a Boolean value, and the latter signal errors. (The +@samp{CONCHECK} variety allows execution to be CONtinued under some +circumstances, thus the name.) Functions which expect to be passed user +data invariably call @samp{CHECK} macros on arguments. -@enumerate a -@item -On input, bytes 0--255 are converted into (implicitly Latin-1) -characters 0--255. A non-Mule xemacs doesn't really know about -different character sets and the fonts to display them, so the bytes can -be treated as text in different 1-byte encodings by simply setting the -appropriate fonts. So in a sense, non-Mule xemacs is a multi-lingual -editor if, for example, different fonts are used to display text in -different buffers, faces, or windows. The specifier mechanism gives the -user complete control over this kind of behavior. -@item -On output, characters 0--255 are converted into bytes 0--255 and other -characters are converted into `~'. -@end enumerate + There are many types of specialized Lisp objects implemented in C, but +the most pervasive type is the @dfn{symbol}. Symbols are used as +identifiers, variables, and functions. -@item Qnative -Format used for the external Unix environment---@code{argv[]}, stuff -from @code{getenv()}, stuff from the @file{/etc/passwd} file, etc. -This is encoded according to the encoding specified by the current locale. -[[This is dangerous; current locale is user preference, and the system -is probably going to be something else. Is there anything we can do -about it?]] + @strong{Convention}: Global variables whose names begin with @samp{Q} +are constants whose value is a symbol. The name of the variable should +be derived from the name of the symbol using the same rules as for Lisp +primitives. Such variables allow the C code to check whether a +particular @code{Lisp_Object} is equal to a given symbol. Symbols are +Lisp objects, so these variables may be passed to Lisp primitives. (An +alternative to the use of @samp{Q...} variables is to call the +@code{intern} function at initialization in the +@code{vars_of_@var{module}} function, which is hardly less efficient.) -@item Qfile_name -Format used for filenames. This is normally the same as @code{Qnative}, -but the two should be distinguished for clarity and possible future -separation -- and also because @code{Qfile_name} can be changed using either -the @code{file-name-coding-system} or @code{pathname-coding-system} (now -obsolete) variables. + @strong{Convention}: Global variables whose names begin with @samp{V} +are variables that contain Lisp objects. The convention here is that +all global variables of type @code{Lisp_Object} begin with @samp{V}, and +no others do (not even integer and boolean variables that have Lisp +equivalents). Most of the time, these variables have equivalents in +Lisp, which are defined via the @samp{DEFVAR} family of macros, but some +don't. Since the variable's value is a @code{Lisp_Object}, it can be +passed to Lisp primitives. -@item Qctext -Compound-text format. This is the standard X11 format used for data -stored in properties, selections, and the like. This is an 8-bit -no-lock-shift ISO2022 coding system. This is a real coding system, -unlike @code{Qfile_name}, which is user-definable. + The implementation of Lisp primitives is more complex. +@strong{Convention}: Global variables with names beginning with @samp{S} +contain a structure that allows the Lisp engine to identify and call a C +function. In modern versions of XEmacs, these identifiers are almost +always completely hidden in the @code{DEFUN} and @code{SUBR} macros, but +you will encounter them if you look at very old versions of XEmacs or at +GNU Emacs. @strong{Convention}: Functions with names beginning with +@samp{F} implement Lisp primitives. Of course all their arguments and +their return values must be Lisp_Objects. (This is hidden in the +@code{DEFUN} macro.) -@item Qmswindows_tstr -Used for external data in all MS Windows functions that are declared to -accept data of type @code{LPTSTR} or @code{LPCSTR}. This maps to either -@code{Qmswindows_multibyte} (a locale-specific encoding, same as -@code{Qnative}) or @code{Qmswindows_unicode}, depending on whether -XEmacs is being run under Windows 9X or Windows NT/2000/XP. -@end table +@subheading Working with Lisp lists -Many other coding systems are provided by default. +Lisp lists are popular data structures in the C code as well as in +Elisp. There are two sets of macros that iterate over lists. +@code{EXTERNAL_LIST_LOOP_@var{n}} should be used when the list has been +supplied by the user, and cannot be trusted to be acyclic and +@code{nil}-terminated. A @code{malformed-list} or @code{circular-list} error +will be generated if the list being iterated over is not entirely +kosher. @code{LIST_LOOP_@var{n}}, on the other hand, is faster and less +safe, and can be used only on trusted lists. -There are two fundamental macros to convert between external and -internal format, as well as various convenience macros to simplify the -most common operations. +Related macros are @code{GET_EXTERNAL_LIST_LENGTH} and +@code{GET_LIST_LENGTH}, which calculate the length of a list, and in the +case of @code{GET_EXTERNAL_LIST_LENGTH}, validating the properness of +the list. The macros @code{EXTERNAL_LIST_LOOP_DELETE_IF} and +@code{LIST_LOOP_DELETE_IF} delete elements from a lisp list satisfying some +predicate. -@code{TO_INTERNAL_FORMAT} converts external data to internal format, and -@code{TO_EXTERNAL_FORMAT} converts the other way around. The arguments -each of these receives are a source type, a source, a sink type, a sink, -and a coding system (or a symbol naming a coding system). +@subheading Implementation of Lisp objects -A typical call looks like -@example -TO_EXTERNAL_FORMAT (LISP_STRING, str, C_STRING_MALLOC, ptr, Qfile_name); -@end example +At the lowest levels, XEmacs makes heavy use of object-oriented +techniques to promote code-sharing and uniform interfaces for different +devices and platforms. Commonly, but not always, such objects are +``wrapped'' and exported to Lisp as Lisp objects. Usually they use +the internal structures developed for Lisp objects (the @samp{lrecord} +structure) in order to take advantage of Lisp memory management. +Unfortunately, XEmacs was originally written in C, so these techniques +are based on heavy use of C macros. -which means that the contents of the lisp string @code{str} are written -to a malloc'ed memory area which will be pointed to by @code{ptr}, after -the function returns. The conversion will be done using the -@code{file-name} coding system, which will be controlled by the user -indirectly by setting or binding the variable -@code{file-name-coding-system}. +@c You can't use @var{} for type below, because case is important. +A module defining a class is likely to use most of the following +declarations and macros. In the following, the notation @samp{<type>} +will stand for the full name of the class, and will be capitalized in +the way normal for its context. The notation @samp{<typ>} will stand +for the abbreviated form commonly used in macro names, while @samp{ty} +will be used as the typical name for instances of the class. (See the +entry for @samp{MAYBE_<TY>METH} below for an example using all three +notations.) -Some sources and sinks require two C variables to specify. We use some -preprocessor magic to allow different source and sink types, and even -different numbers of arguments to specify different types of sources and -sinks. +In the interface (@file{.h} file), the following declarations are used +often. Others may be used in for particular modules. Since they're +quite short in most cases, the definitions are given as well. The +generic macros used are defined in @file{lisp.h} or @file{lrecord.h}. -So we can have a call that looks like -@example -TO_INTERNAL_FORMAT (DATA, (ptr, len), - MALLOC, (ptr, len), - coding_system); -@end example +@c #### reorganize this table into stuff used in general code, and stuff +@c used only in declarations or initializations +@table @samp +@c #### declaration +@item typedef struct Lisp_<Type> Lisp_<Type> +This refers to the internal structure used by C code. The XEmacs coding +style now forbids passing pointers to @samp{Lisp_<Type>} structures into +or out of a function; instead, a @samp{Lisp_Object} should be passed or +returned (created using @samp{wrap_<type>}, if necessary). -The parenthesized argument pairs are required to make the preprocessor -magic work. +@c #### declaration +@item DECLARE_LRECORD (<type>, Lisp_<Type>) +Declares an @samp{lrecord} for @samp{<Type>}, which is the unit of +allocation. -Here are the different source and sink types: +@item #define X<TYPE>(x) XRECORD (x, <type>, Lisp_<Type>) +Turns a @code{Lisp_Object} into a pointer to @samp{struct Lisp_<Type>}. -@table @code -@item @code{DATA, (ptr, len),} -input data is a fixed buffer of size @var{len} at address @var{ptr} -@item @code{ALLOCA, (ptr, len),} -output data is placed in an alloca()ed buffer of size @var{len} pointed to by @var{ptr} -@item @code{MALLOC, (ptr, len),} -output data is in a malloc()ed buffer of size @var{len} pointed to by @var{ptr} -@item @code{C_STRING_ALLOCA, ptr,} -equivalent to @code{ALLOCA (ptr, len_ignored)} on output. -@item @code{C_STRING_MALLOC, ptr,} -equivalent to @code{MALLOC (ptr, len_ignored)} on output -@item @code{C_STRING, ptr,} -equivalent to @code{DATA, (ptr, strlen/wcslen (ptr))} on input -@item @code{LISP_STRING, string,} -input or output is a Lisp_Object of type string -@item @code{LISP_BUFFER, buffer,} -output is written to @code{(point)} in lisp buffer @var{buffer} -@item @code{LISP_LSTREAM, lstream,} -input or output is a Lisp_Object of type lstream -@item @code{LISP_OPAQUE, object,} -input or output is a Lisp_Object of type opaque -@end table +@item #define wrap_<type>(p) wrap_record (p, <type>) +Turns a pointer to @samp{struct Lisp_<Type>} into a @code{Lisp_Object}. -A source type of @code{C_STRING} or a sink type of -@code{C_STRING_ALLOCA} or @code{C_STRING_MALLOC} is appropriate where -the external API is not '\0'-byte-clean -- i.e. it expects strings to be -terminated with a null byte. For external API's that are in fact -'\0'-byte-clean, we should of course not use these. +@item #define <TYPE>P(x) RECORDP (x, <type>) +Tests whether a given @code{Lisp_Object} is of type @samp{Lisp_<Type>}. +Returns a C int, not a Lisp Boolean value. -The sinks to be specified must be lvalues, unless they are the lisp -object types @code{LISP_LSTREAM} or @code{LISP_BUFFER}. +@item #define CHECK_<TYPE>(x) CHECK_RECORD (x, <type>) +@itemx #define CONCHECK_<TYPE>(x) CONCHECK_RECORD (x, <type>) +Tests whether a given @code{Lisp_Object} is of type @samp{Lisp_<Type>}, +and signals a Lisp error if not. The @samp{CHECK} version of the macro +never returns if the type is wrong, while the @samp{CONCHECK} version +can return if the user catches it in the debugger and explicitly +requests a return. -There is no problem using the same lvalue for source and sink. +@item #define RAW_<TYP>METH(ty, m) ((ty)->methods->m##_method) +Return a function pointer for the method for an object @var{TY} of class +@samp{Lisp_<Type>}, or @samp{NULL} if there is none for this type. -Garbage collection is inhibited during these conversion operations, so -it is OK to pass in data from Lisp strings using @code{XSTRING_DATA}. - -For the sink types @code{ALLOCA} and @code{C_STRING_ALLOCA}, the -resulting text is stored in a stack-allocated buffer, which is -automatically freed on returning from the function. However, the sink -types @code{MALLOC} and @code{C_STRING_MALLOC} return @code{xmalloc()}ed -memory. The caller is responsible for freeing this memory using -@code{xfree()}. - -Note that it doesn't make sense for @code{LISP_STRING} to be a source -for @code{TO_INTERNAL_FORMAT} or a sink for @code{TO_EXTERNAL_FORMAT}. -You'll get an assertion failure if you try. - -99% of conversions involve raw data or Lisp strings as both source and -sink, and usually data is output as @code{alloca()}, or sometimes -@code{xmalloc()}. For this reason, convenience macros are defined for -many types of conversions involving raw data and/or Lisp strings, -especially when the output is an @code{alloca()}ed string. (When the -destination is a Lisp string, there are other functions that should be -used instead -- @code{build_ext_string()} and @code{make_ext_string()}, -for example.) The convenience macros are of two types -- the older kind -that store the result into a specified variable, and the newer kind that -return the result. The newer kind of macros don't exist when the output -is sized data, because that would have two return values. NOTE: All -convenience macros are ultimately defined in terms of -@code{TO_EXTERNAL_FORMAT} and @code{TO_INTERNAL_FORMAT}. Thus, any -comments above about the workings of these macros also apply to all -convenience macros. - -A typical old-style convenience macro is +@item #define HAS_<TYP>METH_P(ty, m) (!!RAW_<TYP>METH (ty, m)) +Test whether the class that @var{TY} is an instance of has the method. -@example - C_STRING_TO_EXTERNAL (in, out, codesys); -@end example +@item #define <TYP>METH(ty, m, args) ((RAW_<TYP>METH (ty, m)) args) +Call the method on @samp{args}. @samp{args} must be enclosed in +parentheses in the call. It is the programmer's responsibility to +ensure that the method is available. The standard convenience macro +@samp{MAYBE_<TYP>METH} is often provided for the common case where a +void-returning method of @samp{Type} is called. -This is equivalent to +@item #define MAYBE_<TYP>METH(ty, m, args) do @{ ... @} while (0) +Call a void-returning @samp{<Type>} method, if it exists. Note the use +of the @samp{do ... while (0)} idiom to give the macro call C statement +semantics. The full definition is equally idiomatic: @example - TO_EXTERNAL_FORMAT (C_STRING, in, C_STRING_ALLOCA, out, codesys); +#define MAYBE_<TYP>METH(ty, m, args) do @{ \ + Lisp_<Type> *maybe_<typ>meth_ty = (ty); \ + if (HAS_<TYP>METH_P (maybe_<typ>meth_ty, m)) \ + <TYP>METH (maybe_<typ>meth_ty, m, args); \ +@} while (0) @end example +@end table -but is easier to write and somewhat clearer, since it clearly identifies -the arguments without the clutter of having the preprocessor types mixed -in. +The use of macros for invoking an object's methods makes life a bit +difficult for the student or maintainer when browsing the code. In +particular, calls are of the form @samp{<TYP>METH (ty, some_method, (x, +y))}, but definitions typically are for @samp{<subtype>_some_method}. +Thus, when you are trying to find calls, you need to grep for +@samp{some_method}, but this will also catch calls and definitions of +that method for instances of other subtypes of @samp{<Type>}, and there +may be a rather large number of them. -The new-style equivalent is @code{NEW_C_STRING_TO_EXTERNAL (src, -codesys)}, which @emph{returns} the converted data (still in -@code{alloca()} space). This is far more convenient for most -operations. +@cindex Lisp object types, creating +@cindex creating Lisp object types +@cindex object types, creating Lisp +Here is a checklist of things to do when creating a new lisp object type +named @var{foo}: -@node General Guidelines for Writing Mule-Aware Code -@subsection General Guidelines for Writing Mule-Aware Code -@cindex writing Mule-aware code, general guidelines for -@cindex Mule-aware code, general guidelines for writing -@cindex code, general guidelines for writing Mule-aware +@enumerate +@item +create @var{foo}.h +@item +create @var{foo}.c +@item +add definitions of @code{syms_of_@var{foo}}, etc. to @file{@var{foo}.c} +@item +add declarations of @code{syms_of_@var{foo}}, etc. to @file{symsinit.h} +@item +add calls to @code{syms_of_@var{foo}}, etc. to @file{emacs.c} +@item +add definitions of macros like @code{CHECK_@var{FOO}} and +@code{@var{FOO}P} to @file{@var{foo}.h} +@item +add the new type index to @code{enum lrecord_type} +@item +add a DEFINE_LRECORD_IMPLEMENTATION call to @file{@var{foo}.c} +@item +add an INIT_LRECORD_IMPLEMENTATION call to @code{syms_of_@var{foo}.c} +@end enumerate -This section contains some general guidance on how to write Mule-aware -code, as well as some pitfalls you should avoid. -@table @emph -@item Never use @code{char} and @code{char *}. -In XEmacs, the use of @code{char} and @code{char *} is almost always a -mistake. If you want to manipulate an Emacs character from ``C'', use -@code{Ichar}. If you want to examine a specific octet in the internal -format, use @code{Ibyte}. If you want a Lisp-visible character, use a -@code{Lisp_Object} and @code{make_char}. If you want a pointer to move -through the internal text, use @code{Ibyte *}. Also note that you -almost certainly do not need @code{Ichar *}. Other typedefs to clarify -the use of @code{char} are @code{Char_ASCII}, @code{Char_Binary}, -@code{UChar_Binary}, and @code{CIbyte}. +@node Writing Lisp Primitives, Writing Good Comments, Working with Lisp Objects, Rules When Writing New C Code +@section Writing Lisp Primitives +@cindex writing Lisp primitives +@cindex Lisp primitives, writing +@cindex primitives, writing Lisp -@item Be careful not to confuse @code{Charcount}, @code{Bytecount}, @code{Charbpos} and @code{Bytebpos}. -The whole point of using different types is to avoid confusion about the -use of certain variables. Lest this effect be nullified, you need to be -careful about using the right types. +Lisp primitives are Lisp functions implemented in C. The details of +interfacing the C function so that Lisp can call it are handled by a few +C macros. The only way to really understand how to write new C code is +to read the source, but we can explain some things here. -@item Always convert external data -It is extremely important to always convert external data, because -XEmacs can crash if unexpected 8-bit sequences are copied to its internal -buffers literally. +An example of a special form is the definition of @code{prog1}, from +@file{eval.c}. (An ordinary function would have the same general +appearance.) -This means that when a system function, such as @code{readdir}, returns -a string, you normally need to convert it using one of the conversion macros -described in the previous chapter, before passing it further to Lisp. +@cindex garbage collection protection +@smallexample +@group +DEFUN ("prog1", Fprog1, 1, UNEVALLED, 0, /* +Similar to `progn', but the value of the first form is returned. +\(prog1 FIRST BODY...): All the arguments are evaluated sequentially. +The value of FIRST is saved during evaluation of the remaining args, +whose values are discarded. +*/ + (args)) +@{ + /* This function can GC */ + REGISTER Lisp_Object val, form, tail; + struct gcpro gcpro1; -Actually, most of the basic system functions that accept '\0'-terminated -string arguments, like @code{stat()} and @code{open()}, have -@strong{encapsulated} equivalents that do the internal to external -conversion themselves. The encapsulated equivalents have a @code{qxe_} -prefix and have string arguments of type @code{Ibyte *}, and you can -pass internally encoded data to them, often from a Lisp string using -@code{XSTRING_DATA}. (A better design might be to provide versions that -accept Lisp strings directly.) [[Really? Then they'd either take -@code{Lisp_Object}s and need to check type, or they'd take -@code{Lisp_String}s, and violate the rules about passing any of the -specific Lisp types.]] + val = Feval (XCAR (args)); -Also note that many internal functions, such as @code{make_string}, -accept Ibytes, which removes the need for them to convert the data they -receive. This increases efficiency because that way external data needs -to be decoded only once, when it is read. After that, it is passed -around in internal format. + GCPRO1 (val); -@item Do all work in internal format -External-formatted data is completely unpredictable in its format. It -may be fixed-width Unicode (not even ASCII compatible); it may be a -modal encoding, in -which case some occurrences of (e.g.) the slash character may be part of -two-byte Asian-language characters, and a naive attempt to split apart a -pathname by slashes will fail; etc. Internal-format text should be -converted to external format only at the point where an external API is -actually called, and the first thing done after receiving -external-format text from an external API should be to convert it to -internal text. -@end table + LIST_LOOP_3 (form, XCDR (args), tail) + Feval (form); -@node An Example of Mule-Aware Code -@subsection An Example of Mule-Aware Code -@cindex code, an example of Mule-aware -@cindex Mule-aware code, an example of + UNGCPRO; + return val; +@} +@end group +@end smallexample -As an example of Mule-aware code, we will analyze the @code{string} -function, which conses up a Lisp string from the character arguments it -receives. Here is the definition, pasted from @code{alloc.c}: + Let's start with a precise explanation of the arguments to the +@code{DEFUN} macro. Here is a template for them: @example @group -DEFUN ("string", Fstring, 0, MANY, 0, /* -Concatenate all the argument characters and make the result a string. +DEFUN (@var{lname}, @var{fname}, @var{min_args}, @var{max_args}, @var{interactive}, /* +@var{docstring} */ - (int nargs, Lisp_Object *args)) -@{ - Ibyte *storage = alloca_array (Ibyte, nargs * MAX_ICHAR_LEN); - Ibyte *p = storage; - - for (; nargs; nargs--, args++) - @{ - Lisp_Object lisp_char = *args; - CHECK_CHAR_COERCE_INT (lisp_char); - p += set_itext_ichar (p, XCHAR (lisp_char)); - @} - return make_string (storage, p - storage); -@} + (@var{arglist})) @end group @end example -Now we can analyze the source line by line. +@table @var +@item lname +This string is the name of the Lisp symbol to define as the function +name; in the example above, it is @code{"prog1"}. -Obviously, string will be as long as there are arguments to the -function. This is why we allocate @code{MAX_ICHAR_LEN} * @var{nargs} -bytes on the stack, i.e. the worst-case number of bytes for @var{nargs} -@code{Ichar}s to fit in the string. +@item fname +This is the C function name for this function. This is the name that is +used in C code for calling the function. The name is, by convention, +@samp{F} prepended to the Lisp name, with all dashes (@samp{-}) in the +Lisp name changed to underscores. Thus, to call this function from C +code, call @code{Fprog1}. Remember that the arguments are of type +@code{Lisp_Object}; various macros and functions for creating values of +type @code{Lisp_Object} are declared in the file @file{lisp.h}. -Then, the loop checks that each element is a character, converting -integers in the process. Like many other functions in XEmacs, this -function silently accepts integers where characters are expected, for -historical and compatibility reasons. Unless you know what you are -doing, @code{CHECK_CHAR} will also suffice. @code{XCHAR (lisp_char)} -extracts the @code{Ichar} from the @code{Lisp_Object}, and -@code{set_itext_ichar} stores it to storage, increasing @code{p} in -the process. +Primitives whose names are special characters (e.g. @code{+} or +@code{<}) are named by spelling out, in some fashion, the special +character: e.g. @code{Fplus()} or @code{Flss()}. Primitives whose names +begin with normal alphanumeric characters but also contain special +characters are spelled out in some creative way, e.g. @code{let*} +becomes @code{FletX()}. -Other instructive examples of correct coding under Mule can be found all -over the XEmacs code. For starters, I recommend -@code{Fnormalize_menu_item_name} in @file{menubar.c}. After you have -understood this section of the manual and studied the examples, you can -proceed writing new Mule-aware code. +Each function also has an associated structure that holds the data for +the subr object that represents the function in Lisp. This structure +conveys the Lisp symbol name to the initialization routine that will +create the symbol and store the subr object as its definition. The C +variable name of this structure is always @samp{S} prepended to the +@var{fname}. You hardly ever need to be aware of the existence of this +structure, since @code{DEFUN} plus @code{DEFSUBR} takes care of all the +details. -@node Mule-izing Code -@subsection Mule-izing Code - -A lot of code is written without Mule in mind, and needs to be made -Mule-correct or "Mule-ized". There is really no substitute for -line-by-line analysis when doing this, but the following checklist can -help: +@item min_args +This is the minimum number of arguments that the function requires. The +function @code{prog1} allows a minimum of one argument. -@itemize @bullet -@item -Check all uses of @code{XSTRING_DATA}. -@item -Check all uses of @code{build_string} and @code{make_string}. -@item -Check all uses of @code{tolower} and @code{toupper}. -@item -Check object print methods. -@item -Check for use of functions such as @code{write_c_string}, -@code{write_fmt_string}, @code{stderr_out}, @code{stdout_out}. -@item -Check all occurrences of @code{char} and correct to one of the other -typedefs described above. -@item -Check all existing uses of @code{TO_EXTERNAL_FORMAT}, -@code{TO_INTERNAL_FORMAT}, and any convenience macros (grep for -@samp{EXTERNAL_TO}, @samp{TO_EXTERNAL}, and @samp{TO_SIZED_EXTERNAL}). -@item -In Windows code, string literals may need to be encapsulated with @code{XETEXT}. -@end itemize +@item max_args +This is the maximum number of arguments that the function accepts, if +there is a fixed maximum. Alternatively, it can be @code{UNEVALLED}, +indicating a special form that receives unevaluated arguments, or +@code{MANY}, indicating an unlimited number of evaluated arguments (the +C equivalent of @code{&rest}). Both @code{UNEVALLED} and @code{MANY} +are macros. If @var{max_args} is a number, it may not be less than +@var{min_args} and it may not be greater than 8. (If you need to add a +function with more than 8 arguments, use the @code{MANY} form. Resist +the urge to edit the definition of @code{DEFUN} in @file{lisp.h}. If +you do it anyways, make sure to also add another clause to the switch +statement in @code{primitive_funcall().}) -@node Techniques for XEmacs Developers -@section Techniques for XEmacs Developers -@cindex techniques for XEmacs developers -@cindex developers, techniques for XEmacs +@item interactive +This is an interactive specification, a string such as might be used as +the argument of @code{interactive} in a Lisp function. In the case of +@code{prog1}, it is 0 (a null pointer), indicating that @code{prog1} +cannot be called interactively. A value of @code{""} indicates a +function that should receive no arguments when called interactively. -@cindex Purify -@cindex Quantify -To make a purified XEmacs, do: @code{make puremacs}. -To make a quantified XEmacs, do: @code{make quantmacs}. +@item docstring +This is the documentation string. It is written just like a +documentation string for a function defined in Lisp; in particular, the +first line should be a single sentence. Note how the documentation +string is enclosed in a comment, none of the documentation is placed on +the same lines as the comment-start and comment-end characters, and the +comment-start characters are on the same line as the interactive +specification. @file{make-docfile}, which scans the C files for +documentation strings, is very particular about what it looks for, and +will not properly extract the doc string if it's not in this exact format. -You simply can't dump Quantified and Purified images (unless using the -portable dumper). Purify gets confused when xemacs frees memory in one -process that was allocated in a @emph{different} process on a different -machine! Run it like so: -@example -temacs -batch -l loadup.el run-temacs @var{xemacs-args...} -@end example +In order to make both @file{etags} and @file{make-docfile} happy, make +sure that the @code{DEFUN} line contains the @var{lname} and +@var{fname}, and that the comment-start characters for the doc string +are on the same line as the interactive specification, and put a newline +directly after them (and before the comment-end characters). -@cindex error checking -Before you go through the trouble, are you compiling with all -debugging and error-checking off? If not, try that first. Be warned -that while Quantify is directly responsible for quite a few -optimizations which have been made to XEmacs, doing a run which -generates results which can be acted upon is not necessarily a trivial -task. +@item arglist +This is the comma-separated list of arguments to the C function. For a +function with a fixed maximum number of arguments, provide a C argument +for each Lisp argument. In this case, unlike regular C functions, the +types of the arguments are not declared; they are simply always of type +@code{Lisp_Object}. -Also, if you're still willing to do some runs make sure you configure -with the @samp{--quantify} flag. That will keep Quantify from starting -to record data until after the loadup is completed and will shut off -recording right before it shuts down (which generates enough bogus data -to throw most results off). It also enables three additional elisp -commands: @code{quantify-start-recording-data}, -@code{quantify-stop-recording-data} and @code{quantify-clear-data}. +The names of the C arguments will be used as the names of the arguments +to the Lisp primitive as displayed in its documentation, modulo the same +concerns described above for @code{F...} names (in particular, +underscores in the C arguments become dashes in the Lisp arguments). -If you want to make XEmacs faster, target your favorite slow benchmark, -run a profiler like Quantify, @code{gprof}, or @code{tcov}, and figure -out where the cycles are going. In many cases you can localize the -problem (because a particular new feature or even a single patch -elicited it). Don't hesitate to use brute force techniques like a -global counter incremented at strategic places, especially in -combination with other performance indications (@emph{e.g.}, degree of -buffer fragmentation into extents). +There is one additional kludge: A trailing @samp{_} on the C argument is +discarded when forming the Lisp argument. This allows C language +reserved words (like @code{default}) or global symbols (like +@code{dirname}) to be used as argument names without compiler warnings +or errors. -Specific projects: +A Lisp function with @w{@var{max_args} = @code{UNEVALLED}} is a +@w{@dfn{special form}}; its arguments are not evaluated. Instead it +receives one argument of type @code{Lisp_Object}, a (Lisp) list of the +unevaluated arguments, conventionally named @code{(args)}. -@itemize @bullet -@item -Make the garbage collector faster. Figure out how to write an -incremental garbage collector. -@item -Write a compiler that takes bytecode and spits out C code. -Unfortunately, you will then need a C compiler and a more fully -developed module system. -@item -Speed up redisplay. -@item -Speed up syntax highlighting. It was suggested that ``maybe moving some -of the syntax highlighting capabilities into C would make a -difference.'' Wrong idea, I think. When processing one 400kB file a -particular low-level routine was being called 40 @emph{million} times -simply for @emph{one} call to @code{newline-and-indent}. Syntax -highlighting needs to be rewritten to use a reliable, fast parser, then -to trust the pre-parsed structure, and only do re-highlighting locally -to a text change. Modern machines are fast enough to implement such -parsers in Lisp; but no machine will ever be fast enough to deal with -quadratic (or worse) algorithms! -@item -Implement tail recursion in Emacs Lisp (hard!). -@end itemize +When a Lisp function has no upper limit on the number of arguments, +specify @w{@var{max_args} = @code{MANY}}. In this case its implementation in +C actually receives exactly two arguments: the number of Lisp arguments +(an @code{int}) and the address of a block containing their values (a +@w{@code{Lisp_Object *}}). In this case only are the C types specified +in the @var{arglist}: @w{@code{(int nargs, Lisp_Object *args)}}. -Unfortunately, Emacs Lisp is slow, and is going to stay slow. Function -calls in elisp are especially expensive. Iterating over a long list is -going to be 30 times faster implemented in C than in Elisp. +@end table -Heavily used small code fragments need to be fast. The traditional way -to implement such code fragments in C is with macros. But macros in C -are known to be broken. +Within the function @code{Fprog1} itself, note the use of the macros +@code{GCPRO1} and @code{UNGCPRO}. @code{GCPRO1} is used to ``protect'' +a variable from garbage collection---to inform the garbage collector +that it must look in that variable and regard the object pointed at by +its contents as an accessible object. This is necessary whenever you +call @code{Feval} or anything that can directly or indirectly call +@code{Feval} (this includes the @code{QUIT} macro!). At such a time, +any Lisp object that you intend to refer to again must be protected +somehow. @code{UNGCPRO} cancels the protection of the variables that +are protected in the current function. It is necessary to do this +explicitly. -@cindex macro hygiene -Macro arguments that are repeatedly evaluated may suffer from repeated -side effects or suboptimal performance. +The macro @code{GCPRO1} protects just one local variable. If you want +to protect two, use @code{GCPRO2} instead; repeating @code{GCPRO1} will +not work. Macros @code{GCPRO3} and @code{GCPRO4} also exist. -Variable names used in macros may collide with caller's variables, -causing (at least) unwanted compiler warnings. +These macros implicitly use local variables such as @code{gcpro1}; you +must declare these explicitly, with type @code{struct gcpro}. Thus, if +you use @code{GCPRO2}, you must declare @code{gcpro1} and @code{gcpro2}. -In order to solve these problems, and maintain statement semantics, one -should use the @code{do @{ ... @} while (0)} trick while trying to -reference macro arguments exactly once using local variables. +@cindex caller-protects (@code{GCPRO} rule) +Note also that the general rule is @dfn{caller-protects}; i.e. you are +only responsible for protecting those Lisp objects that you create. Any +objects passed to you as arguments should have been protected by whoever +created them, so you don't in general have to protect them. -Let's take a look at this poor macro definition: +In particular, the arguments to any Lisp primitive are always +automatically @code{GCPRO}ed, when called ``normally'' from Lisp code or +bytecode. So only a few Lisp primitives that are called frequently from +C code, such as @code{Fprogn} protect their arguments as a service to +their caller. You don't need to protect your arguments when writing a +new @code{DEFUN}. -@example -#define MARK_OBJECT(obj) \ - if (!marked_p (obj)) mark_object (obj), did_mark = 1 -@end example +@code{GCPRO}ing is perhaps the trickiest and most error-prone part of +XEmacs coding. It is @strong{extremely} important that you get this +right and use a great deal of discipline when writing this code. +@xref{GCPROing, ,@code{GCPRO}ing}, for full details on how to do this. -This macro evaluates its argument twice, and also fails if used like this: -@example - if (flag) MARK_OBJECT (obj); else do_something(); -@end example +What @code{DEFUN} actually does is declare a global structure of type +@code{Lisp_Subr} whose name begins with capital @samp{SF} and which +contains information about the primitive (e.g. a pointer to the +function, its minimum and maximum allowed arguments, a string describing +its Lisp name); @code{DEFUN} then begins a normal C function declaration +using the @code{F...} name. The Lisp subr object that is the function +definition of a primitive (i.e. the object in the function slot of the +symbol that names the primitive) actually points to this @samp{SF} +structure; when @code{Feval} encounters a subr, it looks in the +structure to find out how to call the C function. -A much better definition is +Defining the C function is not enough to make a Lisp primitive +available; you must also create the Lisp symbol for the primitive (the +symbol is @dfn{interned}; @pxref{Obarrays}) and store a suitable subr +object in its function cell. (If you don't do this, the primitive won't +be seen by Lisp code.) The code looks like this: @example -#define MARK_OBJECT(obj) do @{ \ - Lisp_Object mo_obj = (obj); \ - if (!marked_p (mo_obj)) \ - @{ \ - mark_object (mo_obj); \ - did_mark = 1; \ - @} \ -@} while (0) +DEFSUBR (@var{fname}); @end example -Notice the elimination of double evaluation by using the local variable -with the obscure name. Writing safe and efficient macros requires great -care. The one problem with macros that cannot be portably worked around -is, since a C block has no value, a macro used as an expression rather -than a statement cannot use the techniques just described to avoid -multiple evaluation. - -@cindex inline functions -In most cases where a macro has function semantics, an inline function -is a better implementation technique. Modern compiler optimizers tend -to inline functions even if they have no @code{inline} keyword, and -configure magic ensures that the @code{inline} keyword can be safely -used as an additional compiler hint. Inline functions used in a single -.c files are easy. The function must already be defined to be -@code{static}. Just add another @code{inline} keyword to the -definition. +@noindent +Here @var{fname} is the same name you used as the second argument to +@code{DEFUN}. -@example -inline static int -heavily_used_small_function (int arg) -@{ - ... -@} -@end example +This call to @code{DEFSUBR} should go in the @code{syms_of_*()} function +at the end of the module. If no such function exists, create it and +make sure to also declare it in @file{symsinit.h} and call it from the +appropriate spot in @code{main()}. @xref{Writing New Modules}. -Inline functions in header files are trickier, because we would like to -make the following optimization if the function is @emph{not} inlined -(for example, because we're compiling for debugging). We would like the -function to be defined externally exactly once, and each calling -translation unit would create an external reference to the function, +Note that C code cannot call functions by name unless they are defined +in C. The way to call a function written in Lisp from C is to use +@code{Ffuncall}, which embodies the Lisp function @code{funcall}. Since +the Lisp function @code{funcall} accepts an unlimited number of +arguments, in C it takes two: the number of Lisp-level arguments, and a +one-dimensional array containing their values. The first Lisp-level +argument is the Lisp function to call, and the rest are the arguments to +pass to it. Since @code{Ffuncall} can call the evaluator, you must +protect pointers from garbage collection around the call to +@code{Ffuncall}. (However, @code{Ffuncall} explicitly protects all of +its parameters, so you don't have to protect any pointers passed as +parameters to it.) + +The C functions @code{call0}, @code{call1}, @code{call2}, and so on, +provide handy ways to call a Lisp function conveniently with a fixed +number of arguments. They work by calling @code{Ffuncall}. + +@file{eval.c} is a very good file to look through for examples; +@file{lisp.h} contains the definitions for important macros and +functions. + +@node Writing Good Comments, Adding Global Lisp Variables, Writing Lisp Primitives, Rules When Writing New C Code +@section Writing Good Comments +@cindex writing good comments +@cindex comments, writing good + +Comments are a lifeline for programmers trying to understand tricky +code. In general, the less obvious it is what you are doing, the more +you need a comment, and the more detailed it needs to be. You should +always be on guard when you're writing code for stuff that's tricky, and +should constantly be putting yourself in someone else's shoes and asking +if that person could figure out without much difficulty what's going +on. (Assume they are a competent programmer who understands the +essentials of how the XEmacs code is structured but doesn't know much +about the module you're working on or any algorithms you're using.) If +you're not sure whether they would be able to, add a comment. Always +err on the side of more comments, rather than less. + +Generally, when making comments, there is no need to attribute them with +your name or initials. This especially goes for small, +easy-to-understand, non-opinionated ones. Also, comments indicating +where, when, and by whom a file was changed are @emph{strongly} +discouraged, and in general will be removed as they are discovered. +This is exactly what @file{ChangeLogs} are there for. However, it can +occasionally be useful to mark exactly where (but not when or by whom) +changes are made, particularly when making small changes to a file +imported from elsewhere. These marks help when later on a newer version +of the file is imported and the changes need to be merged. (If +everything were always kept in CVS, there would be no need for this. +But in practice, this often doesn't happen, or the CVS repository is +later on lost or unavailable to the person doing the update.) + +When putting in an explicit opinion in a comment, you should +@emph{always} attribute it with your name and the date. This also goes +for long, complex comments explaining in detail the workings of +something -- by putting your name there, you make it possible for +someone who has questions about how that thing works to determine who +wrote the comment so they can write to them. Use your actual name or +your alias at xemacs.org, and not your initials or nickname, unless that +is generally recognized (e.g. @samp{jwz}). Even then, please consider +requesting a virtual user at xemacs.org (forwarding address; we can't +provide an actual mailbox). Otherwise, give first and last name. If +you're not a regular contributor, you might consider putting your email +address in -- it may be in the ChangeLog, but after awhile ChangeLogs +have a tendency of disappearing or getting muddled. (E.g. your comment +may get copied somewhere else or even into another program, and tracking +down the proper ChangeLog may be very difficult.) + +If you come across an opinion that is not or is no longer valid, or you +come across any comment that no longer applies but you want to keep it +around, enclose it in @samp{[[ } and @samp{ ]]} marks and add a comment +afterwards explaining why the preceding comment is no longer valid. Put +your name on this comment, as explained above. + +Just as comments are a lifeline to programmers, incorrect comments are +death. If you come across an incorrect comment, @strong{immediately} +correct it or flag it as incorrect, as described in the previous +paragraph. Whenever you work on a section of code, @emph{always} make +sure to update any comments to be correct -- or, at the very least, flag +them as incorrect. + +To indicate a "todo" or other problem, use four pound signs -- +i.e. @samp{####}. + +@node Adding Global Lisp Variables, Writing Macros, Writing Good Comments, Rules When Writing New C Code +@section Adding Global Lisp Variables +@cindex global Lisp variables, adding +@cindex variables, adding global Lisp + +Global variables whose names begin with @samp{Q} are constants whose +value is a symbol of a particular name. The name of the variable should +be derived from the name of the symbol using the same rules as for Lisp +primitives. These variables are initialized using a call to +@code{defsymbol()} in the @code{syms_of_*()} function. (This call +interns a symbol, sets the C variable to the resulting Lisp object, and +calls @code{staticpro()} on the C variable to tell the +garbage-collection mechanism about this variable. What +@code{staticpro()} does is add a pointer to the variable to a large +global array; when garbage-collection happens, all pointers listed in +the array are used as starting points for marking Lisp objects. This is +important because it's quite possible that the only current reference to +the object is the C variable. In the case of symbols, the +@code{staticpro()} doesn't matter all that much because the symbol is +contained in @code{obarray}, which is itself @code{staticpro()}ed. +However, it's possible that a naughty user could do something like +uninterning the symbol out of @code{obarray} or even setting +@code{obarray} to a different value [although this is likely to make +XEmacs crash!].) + + @strong{Please note:} It is potentially deadly if you declare a +@samp{Q...} variable in two different modules. The two calls to +@code{defsymbol()} are no problem, but some linkers will complain about +multiply-defined symbols. The most insidious aspect of this is that +often the link will succeed anyway, but then the resulting executable +will sometimes crash in obscure ways during certain operations! + +To avoid this problem, declare any symbols with common names (such as +@code{text}) that are not obviously associated with this particular +module in the file @file{general-slots.h}. The ``-slots'' suffix +indicates that this is a file that is included multiple times in +@file{general.c}. Redefinition of preprocessor macros allows the +effects to be different in each context, so this is actually more +convenient and less error-prone than doing it in your module. + + Global variables whose names begin with @samp{V} are variables that +contain Lisp objects. The convention here is that all global variables +of type @code{Lisp_Object} begin with @samp{V}, and all others don't +(including integer and boolean variables that have Lisp +equivalents). Most of the time, these variables have equivalents in +Lisp, but some don't. Those that do are declared this way by a call to +@code{DEFVAR_LISP()} in the @code{vars_of_*()} initializer for the +module. What this does is create a special @dfn{symbol-value-forward} +Lisp object that contains a pointer to the C variable, intern a symbol +whose name is as specified in the call to @code{DEFVAR_LISP()}, and set +its value to the symbol-value-forward Lisp object; it also calls +@code{staticpro()} on the C variable to tell the garbage-collection +mechanism about the variable. When @code{eval} (or actually +@code{symbol-value}) encounters this special object in the process of +retrieving a variable's value, it follows the indirection to the C +variable and gets its value. @code{setq} does similar things so that +the C variable gets changed. + + Whether or not you @code{DEFVAR_LISP()} a variable, you need to +initialize it in the @code{vars_of_*()} function; otherwise it will end +up as all zeroes, which is the integer 0 (@emph{not} @code{nil}), and +this is probably not what you want. Also, if the variable is not +@code{DEFVAR_LISP()}ed, @strong{you must call} @code{staticpro()} on the +C variable in the @code{vars_of_*()} function. Otherwise, the +garbage-collection mechanism won't know that the object in this variable +is in use, and will happily collect it and reuse its storage for another +Lisp object, and you will be the one who's unhappy when you can't figure +out how your variable got overwritten. + +@node Writing Macros, Proper Use of Unsigned Types, Adding Global Lisp Variables, Rules When Writing New C Code +@section Writing Macros +@cindex writing macros +@cindex macros, writing + +Heavily used small code fragments need to be fast. The traditional way +to implement such code fragments in C is with macros. But macros in C +are known to be broken. + +@cindex macro hygiene +Macro arguments that are repeatedly evaluated may suffer from repeated +side effects or suboptimal performance. + +Variable names used in macros may collide with caller's variables, +causing (at least) unwanted compiler warnings. + +In order to solve these problems, and maintain statement semantics, +one should use the @code{do @{ ... @} while (0)} trick (which safely +works inside of if statements) while trying to reference macro +arguments exactly once using local variables. + +Let's take a look at this poor macro definition: + +@example +#define MARK_OBJECT(obj) \ + if (!marked_p (obj)) mark_object (obj), did_mark = 1 +@end example + +This macro evaluates its argument twice, and also fails if used like this: +@example + if (flag) MARK_OBJECT (obj); else @code{do_something()}; +@end example + +A much better definition is + +@example +#define MARK_OBJECT(obj) do @{ \ + Lisp_Object mo_obj = (obj); \ + if (!marked_p (mo_obj)) \ + @{ \ + mark_object (mo_obj); \ + did_mark = 1; \ + @} \ +@} while (0) +@end example + +Notice the elimination of double evaluation by using the local variable +with the obscure name. Writing safe and efficient macros requires great +care. The one problem with macros that cannot be portably worked around +is, since a C block has no value, a macro used as an expression rather +than a statement cannot use the techniques just described to avoid +multiple evaluation. + +@cindex inline functions +In most cases where a macro has function semantics, an inline function +is a better implementation technique. Modern compiler optimizers tend +to inline functions even if they have no @code{inline} keyword, and +configure magic ensures that the @code{inline} keyword can be safely +used as an additional compiler hint. Inline functions used in a single +.c files are easy. The function must already be defined to be +@code{static}. Just add another @code{inline} keyword to the +definition. + +@example +inline static int +heavily_used_small_function (int arg) +@{ + ... +@} +@end example + +Inline functions in header files are trickier, because we would like to +make the following optimization if the function is @emph{not} inlined +(for example, because we're compiling for debugging). We would like the +function to be defined externally exactly once, and each calling +translation unit would create an external reference to the function, instead of including a definition of the inline function in the object code of every translation unit that uses it. This optimization is currently only available for gcc. But you don't have to worry about the @@ -3766,7276 +5002,22339 @@ pattern: @example -INLINE_HEADER int -i_used_to_be_a_crufty_macro_but_look_at_me_now (int arg); -INLINE_HEADER int +DECLARE_INLINE_HEADER ( +int i_used_to_be_a_crufty_macro_but_look_at_me_now (int arg) +) @{ ... @} @end example -The declaration right before the definition is to prevent warnings when -compiling with @code{gcc -Wmissing-declarations}. I consider issuing -this warning for inline functions a gcc bug, but the gcc maintainers disagree. +We use @code{DECLARE_INLINE_HEADER} rather than just the modifier +@code{INLINE_HEADER} to prevent warnings when compiling with @code{gcc +-Wmissing-declarations}. I consider issuing this warning for inline +functions a gcc bug, but the gcc maintainers disagree. @cindex inline functions, headers @cindex header files, inline functions Every header which contains inline functions, either directly by using -@code{INLINE_HEADER} or indirectly by using @code{DECLARE_LRECORD} must +@code{DECLARE_INLINE_HEADER} or indirectly by using @code{DECLARE_LRECORD} must be added to @file{inline.c}'s includes to make the optimization described above work. (Optimization note: if all INLINE_HEADER functions are in fact inlined in all translation units, then the linker can just discard @code{inline.o}, since it contains only unreferenced code). -To get started debugging XEmacs, take a look at the @file{.gdbinit} and -@file{.dbxrc} files in the @file{src} directory. See the section in the -XEmacs FAQ on How to Debug an XEmacs problem with a debugger. - -After making source code changes, run @code{make check} to ensure that -you haven't introduced any regressions. If you want to make xemacs more -reliable, please improve the test suite in @file{tests/automated}. - -Did you make sure you didn't introduce any new compiler warnings? +The three golden rules of macros: -Before submitting a patch, please try compiling at least once with +@enumerate +@item +Anything that's an lvalue can be evaluated more than once. +@item +Macros where anything else can be evaluated more than once should +have the word "unsafe" in their name (exceptions may be made for +large sets of macros that evaluate arguments of certain types more +than once, e.g. struct buffer * arguments, when clearly indicated in +the macro documentation). These macros are generally meant to be +called only by other macros that have already stored the calling +values in temporary variables. +@item +Nothing else can be evaluated more than once. Use inline +functions, if necessary, to prevent multiple evaluation. +@end enumerate -@example -configure --with-mule --use-union-type --error-checking=all -@end example +NOTE: The functions and macros below are given full prototypes in their +docs, even when the implementation is a macro. In such cases, passing +an argument of a type other than expected will produce undefined +results. Also, given that macros can do things functions can't (in +particular, directly modify arguments as if they were passed by +reference), the declaration syntax has been extended to include the +call-by-reference syntax from C++, where an & after a type indicates +that the argument is an lvalue and is passed by reference, i.e. the +function can modify its value. (This is equivalent in C to passing a +pointer to the argument, but without the need to explicitly worry about +pointers.) -Here are things to know when you create a new source file: +When to capitalize macros: @itemize @bullet @item -All @file{.c} files should @code{#include <config.h>} first. Almost all -@file{.c} files should @code{#include "lisp.h"} second. - +Capitalize macros doing stuff obviously impossible with (C) +functions, e.g. directly modifying arguments as if they were passed by +reference. +@item +Capitalize macros that evaluate @strong{any} argument more than once regardless +of whether that's "allowed" (e.g. buffer arguments). +@item +Capitalize macros that directly access a field in a Lisp_Object or +its equivalent underlying structure. In such cases, access through the +Lisp_Object precedes the macro with an X, and access through the underlying +structure doesn't. @item -Generated header files should be included using the @samp{#include <...>} -syntax, not the @samp{#include "..."} syntax. The generated headers are: +Capitalize certain other basic macros relating to Lisp_Objects; e.g. +FRAMEP, CHECK_FRAME, etc. +@item +Try to avoid capitalizing any other macros. +@end itemize -@file{config.h sheap-adjust.h paths.h Emacs.ad.h} +@node Proper Use of Unsigned Types, Major Textual Changes, Writing Macros, Rules When Writing New C Code +@section Proper Use of Unsigned Types +@cindex unsigned types, proper use of +@cindex types, proper use of unsigned -The basic rule is that you should assume builds using @samp{--srcdir} -and the @samp{#include <...>} syntax needs to be used when the -to-be-included generated file is in a potentially different directory -@emph{at compile time}. The non-obvious C rule is that -@samp{#include "..."} means to search for the included file in the same -directory as the including file, @emph{not} in the current directory. -Normally this is not a problem but when building with @samp{--srcdir}, -@file{make} will search the @samp{VPATH} for you, while the C compiler -knows nothing about it. - -@item -Header files should @emph{not} include @samp{<config.h>} and -@samp{"lisp.h"}. It is the responsibility of the @file{.c} files that -use it to do so. - -@end itemize - -@cindex Lisp object types, creating -@cindex creating Lisp object types -@cindex object types, creating Lisp -Here is a checklist of things to do when creating a new lisp object type -named @var{foo}: +Avoid using @code{unsigned int} and @code{unsigned long} whenever +possible. Unsigned types are viral -- any arithmetic or comparisons +involving mixed signed and unsigned types are automatically converted to +unsigned, which is almost certainly not what you want. Many subtle and +hard-to-find bugs are created by careless use of unsigned types. In +general, you should almost @emph{never} use an unsigned type to hold a +regular quantity of any sort. The only exceptions are @enumerate @item -create @var{foo}.h +When there's a reasonable possibility you will actually need all 32 or +64 bits to store the quantity. @item -create @var{foo}.c +When calling existing API's that require unsigned types. In this case, +you should still do all manipulation using signed types, and do the +conversion at the very threshold of the API call. @item -add definitions of @code{syms_of_@var{foo}}, etc. to @file{@var{foo}.c} +In existing code that you don't want to modify because you don't +maintain it. @item -add declarations of @code{syms_of_@var{foo}}, etc. to @file{symsinit.h} +In bit-field structures. +@end enumerate + +Other reasonable uses of @code{unsigned int} and @code{unsigned long} +are representing non-quantities -- e.g. bit-oriented flags and such. + +@node Major Textual Changes, Debugging and Testing, Proper Use of Unsigned Types, Rules When Writing New C Code +@section Major Textual Changes +@cindex textual changes, major +@cindex major textual changes + +Sometimes major textual changes are made to the source. This means that +a search-and-replace is done to change type names and such. Some people +disagree with such changes, and certainly if done without good reason +will just lead to headaches. But it's important to keep the code clean +and understable, and consistent naming goes a long way towards this. + +An example of the right way to do this was the so-called "great integral +type renaming". + +@menu +* Great Integral Type Renaming:: +* Text/Char Type Renaming:: +@end menu + +@node Great Integral Type Renaming, Text/Char Type Renaming, Major Textual Changes, Major Textual Changes +@subsection Great Integral Type Renaming +@cindex Great Integral Type Renaming +@cindex integral type renaming, great +@cindex type renaming, integral +@cindex renaming, integral types + +The purpose of this is to rationalize the names used for various +integral types, so that they match their intended uses and follow +consist conventions, and eliminate types that were not semantically +different from each other. + +The conventions are: + +@itemize @bullet @item -add calls to @code{syms_of_@var{foo}}, etc. to @file{emacs.c} +All integral types that measure quantities of anything are signed. Some +people disagree vociferously with this, but their arguments are mostly +theoretical, and are vastly outweighed by the practical headaches of +mixing signed and unsigned values, and more importantly by the far +increased likelihood of inadvertent bugs: Because of the broken "viral" +nature of unsigned quantities in C (operations involving mixed +signed/unsigned are done unsigned, when exactly the opposite is nearly +always wanted), even a single error in declaring a quantity unsigned +that should be signed, or even the even more subtle error of comparing +signed and unsigned values and forgetting the necessary cast, can be +catastrophic, as comparisons will yield wrong results. -Wsign-compare +is turned on specifically to catch this, but this tends to result in a +great number of warnings when mixing signed and unsigned, and the casts +are annoying. More has been written on this elsewhere. + @item -add definitions of macros like @code{CHECK_@var{FOO}} and -@code{@var{FOO}P} to @file{@var{foo}.h} +All such quantity types just mentioned boil down to EMACS_INT, which is +32 bits on 32-bit machines and 64 bits on 64-bit machines. This is +guaranteed to be the same size as Lisp objects of type @code{int}, and (as +far as I can tell) of size_t (unsigned!) and ssize_t. The only type +below that is not an EMACS_INT is Hashcode, which is an unsigned value +of the same size as EMACS_INT. + @item -add the new type index to @code{enum lrecord_type} +Type names should be relatively short (no more than 10 characters or +so), with the first letter capitalized and no underscores if they can at +all be avoided. + @item -add a DEFINE_LRECORD_IMPLEMENTATION call to @file{@var{foo}.c} +"count" == a zero-based measurement of some quantity. Includes sizes, +offsets, and indexes. + @item -add an INIT_LRECORD_IMPLEMENTATION call to @code{syms_of_@var{foo}.c} -@end enumerate +"bpos" == a one-based measurement of a position in a buffer. "Charbpos" +and "Bytebpos" count text in the buffer, rather than bytes in memory; +thus Bytebpos does not directly correspond to the memory representation. +Use "Membpos" for this. -@node Regression Testing XEmacs, CVS Techniques, Rules When Writing New C Code, Top -@chapter Regression Testing XEmacs -@cindex testing, regression +@item +"Char" refers to internal-format characters, not to the C type "char", +which is really a byte. +@end itemize -The source directory @file{tests/automated} contains XEmacs' automated -test suite. The usual way of running all the tests is running -@code{make check} from the top-level build directory. +For the actual name changes, see the script below. -The test suite is unfinished and it's still lacking some essential -features. It is nevertheless recommended that you run the tests to -confirm that XEmacs behaves correctly. +I ran the following script to do the conversion. (NOTE: This script is +idempotent. You can safely run it multiple times and it will not screw +up previous results -- in fact, it will do nothing if nothing has +changed. Thus, it can be run repeatedly as necessary to handle patches +coming in from old workspaces, or old branches.) There are two tags, +just before and just after the change: @samp{pre-integral-type-rename} +and @samp{post-integral-type-rename}. When merging code from the main +trunk into a branch, the best thing to do is first merge up to +@samp{pre-integral-type-rename}, then apply the script and associated +changes, then merge from @samp{post-integral-type-change} to the +present. (Alternatively, just do the merging in one operation; but you +may then have a lot of conflicts needing to be resolved by hand.) -If you want to run a specific test case, you can do it from the -command-line like this: +Script @samp{fixtypes.sh} follows: @example -$ xemacs -batch -l test-harness.elc -f batch-test-emacs TEST-FILE +----------------------------------- cut ------------------------------------ +files="*.[ch] s/*.h m/*.h config.h.in ../configure.in Makefile.in.in ../lib-src/*.[ch] ../lwlib/*.[ch]" +gr Memory_Count Bytecount $files +gr Lstream_Data_Count Bytecount $files +gr Element_Count Elemcount $files +gr Hash_Code Hashcode $files +gr extcount bytecount $files +gr bufpos charbpos $files +gr bytind bytebpos $files +gr memind membpos $files +gr bufbyte intbyte $files +gr Extcount Bytecount $files +gr Bufpos Charbpos $files +gr Bytind Bytebpos $files +gr Memind Membpos $files +gr Bufbyte Intbyte $files +gr EXTCOUNT BYTECOUNT $files +gr BUFPOS CHARBPOS $files +gr BYTIND BYTEBPOS $files +gr MEMIND MEMBPOS $files +gr BUFBYTE INTBYTE $files +gr MEMORY_COUNT BYTECOUNT $files +gr LSTREAM_DATA_COUNT BYTECOUNT $files +gr ELEMENT_COUNT ELEMCOUNT $files +gr HASH_CODE HASHCODE $files +----------------------------------- cut ------------------------------------ @end example -If a test fails and you need more information, you can run the test -suite interactively by loading @file{test-harness.el} into a running -XEmacs and typing @kbd{M-x test-emacs-test-file RET <filename> RET}. -You will see a log of passed and failed tests, which should allow you to -investigate the source of the error and ultimately fix the bug. If you -are not capable of, or don't have time for, debugging it yourself, -please do report the failures using @kbd{M-x report-emacs-bug} or -@kbd{M-x build-report}. - -@deffn Command test-emacs-test-file file -Runs the tests in @var{file}. @file{test-harness.el} must be loaded. -Defines all the macros described in this node, and undefines them when -done. -@end deffn +The @samp{gr} script, and the scripts it uses, are documented in +@file{README.global-renaming}, because if placed in this file they would +need to have their @@ characters doubled, meaning you couldn't easily +cut and paste from the source. -Adding a new test file is trivial: just create a new file here and it -will be run. There is no need to byte-compile any of the files in -this directory---the test-harness will take care of any necessary -byte-compilation. +In addition to those programs, I needed to fix up a few other +things, particularly relating to the duplicate definitions of +types, now that some types merged with others. Specifically: -Look at the existing test cases for the examples of coding test cases. -It all boils down to your imagination and judicious use of the macros -@code{Assert}, @code{Check-Error}, @code{Check-Error-Message}, and -@code{Check-Message}. Note that all of these macros are defined only -for the duration of the test: they do not exist in the global -environment. +@enumerate +@item +in @file{lisp.h}, removed duplicate declarations of Bytecount. The changed +code should now look like this: (In each code snippet below, the first +and last lines are the same as the original, as are all lines outside of +those lines. That allows you to locate the section to be replaced, and +replace the stuff in that section, verifying that there isn't anything +new added that would need to be kept.) -@deffn Macro Assert expr -Check that @var{expr} is non-nil at this point in the test. -@end deffn +@example +--------------------------------- snip ------------------------------------- +/* Counts of bytes or chars */ +typedef EMACS_INT Bytecount; +typedef EMACS_INT Charcount; -@deffn Macro Check-Error expected-error body -Check that execution of @var{body} causes @var{expected-error} to be -signaled. @var{body} is a @code{progn}-like body, and may contain -several expressions. @var{expected-error} is a symbol defined as -an error by @code{define-error}. -@end deffn +/* Counts of elements */ +typedef EMACS_INT Elemcount; -@deffn Macro Check-Error-Message expected-error expected-error-regexp body -Check that execution of @var{body} causes @var{expected-error} to be -signaled, and generate a message matching @var{expected-error-regexp}. -@var{body} is a @code{progn}-like body, and may contain several -expressions. @var{expected-error} is a symbol defined as an error -by @code{define-error}. -@end deffn +/* Hash codes */ +typedef unsigned long Hashcode; -@deffn Macro Check-Message expected-message body -Check that execution of @var{body} causes @var{expected-message} to be -generated (using @code{message} or a similar function). @var{body} is a -@code{progn}-like body, and may contain several expressions. -@end deffn +/* ------------------------ dynamic arrays ------------------- */ +--------------------------------- snip ------------------------------------- +@end example -Here's a simple example checking case-sensitive and case-insensitive -comparisons from @file{case-tests.el}. +@item +in @file{lstream.h}, removed duplicate declaration of Bytecount. Rewrote the +comment about this type. The changed code should now look like this: @example -(with-temp-buffer - (insert "Test Buffer") - (let ((case-fold-search t)) - (goto-char (point-min)) - (Assert (eq (search-forward "test buffer" nil t) 12)) - (goto-char (point-min)) - (Assert (eq (search-forward "Test buffer" nil t) 12)) - (goto-char (point-min)) - (Assert (eq (search-forward "Test Buffer" nil t) 12)) +--------------------------------- snip ------------------------------------- +#endif - (setq case-fold-search nil) - (goto-char (point-min)) - (Assert (not (search-forward "test buffer" nil t))) - (goto-char (point-min)) - (Assert (not (search-forward "Test buffer" nil t))) - (goto-char (point-min)) - (Assert (eq (search-forward "Test Buffer" nil t) 12)))) -@end example - -This example could be saved in a file in @file{tests/automated}, and it -would constitute a complete test, automatically executed when you run -@kbd{make check} after building XEmacs. More complex tests may require -substantial temporary scaffolding to create the environment that elicits -the bugs, but the top-level @file{Makefile} and @file{test-harness.el} -handle the running and collection of results from the @code{Assert}, -@code{Check-Error}, @code{Check-Error-Message}, and @code{Check-Message} -macros. - -Don't suppress tests just because they're due to known bugs not yet -fixed---use the @code{Known-Bug-Expect-Failure} wrapper macro to mark -them. - -@deffn Macro Known-Bug-Expect-Failure body -Arrange for failing tests in @var{body} to generate messages prefixed -with "KNOWN BUG:" instead of "FAIL:". @var{body} is a @code{progn}-like -body, and may contain several tests. -@end deffn - -A lot of the tests we run push limits; suppress Ebola warning messages -with the @code{Ignore-Ebola} wrapper macro. - -@deffn Macro Ignore-Ebola body -Suppress Ebola warning messages while running tests in @var{body}. -@var{body} is a @code{progn}-like body, and may contain several tests. -@end deffn - -Both macros are defined temporarily within the test function. Simple -examples: - -@example -;; Apparently Ignore-Ebola is a solution with no problem to address. -;; There are no examples in 21.5, anyway. - -;; from regexp-tests.el -(Known-Bug-Expect-Failure - (Assert (not (string-match "\\b" ""))) - (Assert (not (string-match " \\b" " ")))) -@end example - -In general, you should avoid using functionality from packages in your -tests, because you can't be sure that everyone will have the required -package. However, if you've got a test that works, by all means add it. -Simply wrap the test in an appropriate test, add a notice that the test -was skipped, and update the @code{skipped-test-reasons} hashtable. The -wrapper macro @code{Skip-Test-Unless} is provided to handle common -cases. +/* The have been some arguments over the what the type should be that + specifies a count of bytes in a data block to be written out or read in, + using @code{Lstream_read()}, @code{Lstream_write()}, and related functions. + Originally it was long, which worked fine; Martin "corrected" these to + size_t and ssize_t on the grounds that this is theoretically cleaner and + is in keeping with the C standards. Unfortunately, this practice is + horribly error-prone due to design flaws in the way that mixed + signed/unsigned arithmetic happens. In fact, by doing this change, + Martin introduced a subtle but fatal error that caused the operation of + sending large mail messages to the SMTP server under Windows to fail. + By putting all values back to be signed, avoiding any signed/unsigned + mixing, the bug immediately went away. The type then in use was + Lstream_Data_Count, so that it be reverted cleanly if a vote came to + that. Now it is Bytecount. -@defvar skipped-test-reasons -Hash table counting the number of times a particular reason is given for -skipping tests. This is only defined within @code{test-emacs-test-file}. -@end defvar + Some earlier comments about why the type must be signed: This MUST BE + SIGNED, since it also is used in functions that return the number of + bytes actually read to or written from in an operation, and these + functions can return -1 to signal error. -@deffn Macro Skip-Test-Unless prerequisite reason description body -@var{prerequisite} is usually a feature test (@code{featurep}, -@code{boundp}, @code{fboundp}). @var{reason} is a string describing the -prerequisite; it must be unique because it is used as a hash key in a -table of reasons for skipping tests. @var{description} describes the -tests being skipped, for the test result summary. @var{body} is a -@code{progn}-like body, and may contain several tests. -@end deffn + Note that the standard Unix @code{read()} and @code{write()} functions define the + count going in as a size_t, which is UNSIGNED, and the count going + out as an ssize_t, which is SIGNED. This is a horrible design + flaw. Not only is it highly likely to lead to logic errors when a + -1 gets interpreted as a large positive number, but operations are + bound to fail in all sorts of horrible ways when a number in the + upper-half of the size_t range is passed in -- this number is + unrepresentable as an ssize_t, so code that checks to see how many + bytes are actually written (which is mandatory if you are dealing + with certain types of devices) will get completely screwed up. -@code{Skip-Test-Unless} is defined temporarily within the test function. -Here's an example of usage from @file{syntax-tests.el}: + --ben +*/ -@example -;; Test forward-comment at buffer boundaries -(with-temp-buffer - ;; try to use exactly what you need: featurep, boundp, fboundp - (Skip-Test-Unless (fboundp 'c-mode) - "c-mode unavailable" - "comment and parse-partial-sexp tests" - ;; and here's the test code - (c-mode) - (insert "// comment\n") - (forward-comment -2) - (Assert (eq (point) (point-min))) - (let ((point (point))) - (insert "/* comment */") - (goto-char point) - (forward-comment 2) - (Assert (eq (point) (point-max))) - (parse-partial-sexp point (point-max))))) +typedef enum lstream_buffering +--------------------------------- snip ------------------------------------- @end example -@code{Skip-Test-Unless} is intended for use with features that are normally -present in typical configurations. For truly optional features, or -tests that apply to one of several alternative implementations (eg, to -GTK widgets, but not Athena, Motif, MS Windows, or Carbon), simply -silently suppress the test if the feature is not available. - -Here are a few general hints for writing tests. - -@enumerate -@item -Include related successful cases. Fixes often break something. - -@item -Use the Known-Bug-Expect-Failure macro to mark the cases you know -are going to fail. We want to be able to distinguish between -regressions and other unexpected failures, and cases that have -been (partially) analyzed but not yet repaired. - @item -Mark the bug with the date of report. An ``Unfixed since yyyy-mm-dd'' -gloss for Known-Bug-Expect-Failure is planned to further increase -developer embarrassment (== incentive to fix the bug), but until then at -least put a comment about the date so we can easily see when it was -first reported. - -@item -It's a matter of your judgement, but you should often use generic tests -(@emph{e.g.}, @code{eq}) instead of more specific tests (@code{=} for -numbers) even though you know that arguments ``should'' be of correct -type. That is, if the functions used can return generic objects -(typically @code{nil}), as well as some more specific type that will be -returned on success. We don't want failures of those assertions -reported as ``other failures'' (a wrong-type-arg signal, rather than a -null return), we want them reported as ``assertion failures.'' - -One example is a test that tests @code{(= (string-match this that) 0)}, -expecting a successful match. Now suppose @code{string-match} is broken -such that the match fails. Then it will return @code{nil}, and @code{=} -will signal ``wrong-type-argument, number-char-or-marker-p, nil'', -generating an ``other failure'' in the report. But this should be -reported as an assertion failure (the test failed in a foreseeable way), -rather than something else (we don't know what happened because XEmacs -is broken in a way that we weren't trying to test!) +in @file{dumper.c}, there are four places, all inside of @code{switch()} statements, +where XD_BYTECOUNT appears twice as a case tag. In each case, the two +case blocks contain identical code, and you should *REMOVE THE SECOND* +and leave the first. @end enumerate +@node Text/Char Type Renaming, , Great Integral Type Renaming, Major Textual Changes +@subsection Text/Char Type Renaming +@cindex Text/Char Type Renaming +@cindex type renaming, text/char +@cindex renaming, text/char types -@node CVS Techniques, A Summary of the Various XEmacs Modules, Regression Testing XEmacs, Top -@chapter CVS Techniques -@cindex CVS techniques - -@menu -* Merging a Branch into the Trunk:: -@end menu - -@node Merging a Branch into the Trunk -@section Merging a Branch into the Trunk -@cindex merging a branch into the trunk +The purpose of this was @enumerate @item -If you haven't already done a merge, you will be merging from the branch -point; otherwise you'll be merging from the last merge point, which -should be marked by a tag, e.g. @samp{last-sync-ben-mule-21-5}. In the -former case, create the last-sync tag, e.g. +To distinguish between ``charptr'' when it refers to operations on +the pointer itself and when it refers to operations on text +@item +To use consistent naming for everything referring to internal format, i.e. +@end enumerate @example -crw rtag -r ben-mule-21-5-bp last-sync-ben-mule-21-5 xemacs + Itext == text in internal format + Ibyte == a byte in such text + Ichar == a char as represented in internal character format @end example -(You did create a branch point tag when you created the branch, didn't -you?) - -@item -Check everything in on your branch. +Thus e.g. -@item -Tag your branch with a pre-sync tag, e.g. +@example + set_charptr_emchar -> set_itext_ichar +@end example + +This was done using a script like this: @example -crw rtag -r ben-mule-21-5 ben-mule-21-5-pre-feb-20-2002-sync xemacs +files="*.[ch] s/*.h m/*.h config.h.in ../configure.in Makefile.in.in ../lib-src/*.[ch] ../lwlib/*.[ch]" +gr Intbyte Ibyte $files +gr INTBYTE IBYTE $files +gr intbyte ibyte $files +gr EMCHAR ICHAR $files +gr emchar ichar $files +gr Emchar Ichar $files +gr INC_CHARPTR INC_IBYTEPTR $files +gr DEC_CHARPTR DEC_IBYTEPTR $files +gr VALIDATE_CHARPTR VALIDATE_IBYTEPTR $files +gr valid_charptr valid_ibyteptr $files +gr CHARPTR ITEXT $files +gr charptr itext $files +gr Charptr Itext $files @end example -Note, you need to use rtag and specify a version with @samp{-r} (use -@samp{-r HEAD} if necessary) so that removed files are handled correctly -in some obscure cases. See section 4.8 of the CVS manual. +See above for the source to @samp{gr}. -@item -Tag the trunk so you have a stable place to merge up to in case people -are asynchronously committing to the trunk, e.g. +As in the integral-types change, there are pre and post tags before and +after the change: @example -crw rtag -r HEAD main-branch-ben-mule-21-5-syncpoint-feb-20-2002 xemacs -crw rtag -F -r main-branch-ben-mule-21-5-syncpoint-feb-20-2002 next-sync-ben-mule-21-5 xemacs + pre-internal-format-textual-renaming + post-internal-format-textual-renaming @end example -Use -F in the second case because the name might already exist, e.g. if -you've already done a merge. We make two tags because one is a -permanent mark indicating a syncpoint when merging, and the other is a -symbolic tag to make other operations easier. +When merging a large branch, follow the same sort of procedure +documented above, using these tags -- essentially sync up to the pre +tag, then apply the script yourself, then sync from the post tag to the +present. You can probably do the same if you don't have a separate +workspace, but do have lots of outstanding changes and you'd rather not +just merge all the textual changes directly. Use something like this: -@item -Make a backup of your source tree (not totally necessary but useful for -reference and peace of mind): Move one level up from the top directory -of your branch and do, e.g. +(WARNING: I'm not a CVS guru; before trying this, or any large operation +that might potentially mess things up, @strong{DEFINITELY} make a backup of +your existing workspace.) @example -cp -a mule mule-backup-2-23-02 +cup -r pre-internal-format-textual-renaming +<apply script> +cup -A -j post-internal-format-textual-renaming -j HEAD @end example -@item -Now, we're ready to merge! Make sure you're in the top directory of -your branch and do, e.g. +This might also work: @example -cvs update -j last-sync-ben-mule-21-5 -j next-sync-ben-mule-21-5 +cup -j pre-internal-format-textual-renaming +<apply script> +cup -j post-internal-format-textual-renaming -j HEAD @end example -@item -Fix all merge conflicts. Get the sucker to compile and run. +ben -@item -Tag your branch with a post-sync tag, e.g. +The following is a script to go in the opposite direction: @example -crw rtag -r ben-mule-21-5 ben-mule-21-5-post-feb-20-2002-sync xemacs -@end example +files="*.[ch] s/*.h m/*.h config.h.in ../configure.in Makefile.in.in ../lib-src/*.[ch] ../lwlib/*.[ch]" -@item -Update the last-sync tag, e.g. +# Evidently Perl considers _ to be a word char ala \b, even though XEmacs +# doesn't. We need to be careful here with ibyte/ichar because of words +# like Richard, @code{eicharlen()}, multibyte, HIBYTE, etc. -@example -crw rtag -F -r next-sync-ben-mule-21-5 last-sync-ben-mule-21-5 xemacs -@end example -@end enumerate +gr Ibyte Intbyte $files +gr '\bIBYTE' INTBYTE $files +gr '\bibyte' intbyte $files +gr '\bICHAR' EMCHAR $files +gr '\bichar' emchar $files +gr '\bIchar' Emchar $files +gr '\bIBYTEPTR' CHARPTR $files +gr '\bibyteptr' charptr $files +gr '\bITEXT' CHARPTR $files +gr '\bitext' charptr $files +gr '\bItext' CHARPTR $files +gr '_IBYTE' _INTBYTE $files +gr '_ibyte' _intbyte $files +gr '_ICHAR' _EMCHAR $files +gr '_ichar' _emchar $files +gr '_Ichar' _Emchar $files +gr '_IBYTEPTR' _CHARPTR $files +gr '_ibyteptr' _charptr $files +gr '_ITEXT' _CHARPTR $files +gr '_itext' _charptr $files +gr '_Itext' _CHARPTR $files +@end example -@node A Summary of the Various XEmacs Modules, Allocation of Objects in XEmacs Lisp, CVS Techniques, Top -@chapter A Summary of the Various XEmacs Modules -@cindex modules, a summary of the various XEmacs - - This is accurate as of XEmacs 20.0. - -@menu -* Low-Level Modules:: -* Basic Lisp Modules:: -* Modules for Standard Editing Operations:: -* Editor-Level Control Flow Modules:: -* Modules for the Basic Displayable Lisp Objects:: -* Modules for other Display-Related Lisp Objects:: -* Modules for the Redisplay Mechanism:: -* Modules for Interfacing with the File System:: -* Modules for Other Aspects of the Lisp Interpreter and Object System:: -* Modules for Interfacing with the Operating System:: -* Modules for Interfacing with X Windows:: -* Modules for Internationalization:: -* Modules for Regression Testing:: -@end menu +@node Debugging and Testing, , Major Textual Changes, Rules When Writing New C Code +@section Debugging and Testing +@cindex debugging and testing -@node Low-Level Modules -@section Low-Level Modules -@cindex low-level modules -@cindex modules, low-level +@cindex Purify +@cindex Quantify +To make a purified XEmacs, do: @code{make puremacs}. +To make a quantified XEmacs, do: @code{make quantmacs}. +You simply can't dump Quantified and Purified images (unless using the +portable dumper). Purify gets confused when xemacs frees memory in one +process that was allocated in a @emph{different} process on a different +machine! Run it like so: @example -config.h +temacs -batch -l loadup.el run-temacs @var{xemacs-args...} @end example -This is automatically generated from @file{config.h.in} based on the -results of configure tests and user-selected optional features and -contains preprocessor definitions specifying the nature of the -environment in which XEmacs is being compiled. +@cindex error checking +Before you go through the trouble, are you compiling with all +debugging and error-checking off? If not, try that first. Be warned +that while Quantify is directly responsible for quite a few +optimizations which have been made to XEmacs, doing a run which +generates results which can be acted upon is not necessarily a trivial +task. + +Also, if you're still willing to do some runs make sure you configure +with the @samp{--quantify} flag. That will keep Quantify from starting +to record data until after the loadup is completed and will shut off +recording right before it shuts down (which generates enough bogus data +to throw most results off). It also enables three additional elisp +commands: @code{quantify-start-recording-data}, +@code{quantify-stop-recording-data} and @code{quantify-clear-data}. +If you want to make XEmacs faster, target your favorite slow benchmark, +run a profiler like Quantify, @code{gprof}, or @code{tcov}, and figure +out where the cycles are going. In many cases you can localize the +problem (because a particular new feature or even a single patch +elicited it). Don't hesitate to use brute force techniques like a +global counter incremented at strategic places, especially in +combination with other performance indications (@emph{e.g.}, degree of +buffer fragmentation into extents). +Specific projects: -@example -paths.h -@end example +@itemize @bullet +@item +Make the garbage collector faster. Figure out how to write an +incremental garbage collector. +@item +Write a compiler that takes bytecode and spits out C code. +Unfortunately, you will then need a C compiler and a more fully +developed module system. +@item +Speed up redisplay. +@item +Speed up syntax highlighting. It was suggested that ``maybe moving some +of the syntax highlighting capabilities into C would make a +difference.'' Wrong idea, I think. When processing one 400kB file a +particular low-level routine was being called 40 @emph{million} times +simply for @emph{one} call to @code{newline-and-indent}. Syntax +highlighting needs to be rewritten to use a reliable, fast parser, then +to trust the pre-parsed structure, and only do re-highlighting locally +to a text change. Modern machines are fast enough to implement such +parsers in Lisp; but no machine will ever be fast enough to deal with +quadratic (or worse) algorithms! +@item +Implement tail recursion in Emacs Lisp (hard!). +@end itemize -This is automatically generated from @file{paths.h.in} based on supplied -configure values, and allows for non-standard installed configurations -of the XEmacs directories. It's currently broken, though. +Unfortunately, Emacs Lisp is slow, and is going to stay slow. Function +calls in elisp are especially expensive. Iterating over a long list is +going to be 30 times faster implemented in C than in Elisp. + +To get started debugging XEmacs, take a look at the @file{.gdbinit} and +@file{.dbxrc} files in the @file{src} directory. See the section in the +XEmacs FAQ on How to Debug an XEmacs problem with a debugger. + +After making source code changes, run @code{make check} to ensure that +you haven't introduced any regressions. If you want to make xemacs more +reliable, please improve the test suite in @file{tests/automated}. +Did you make sure you didn't introduce any new compiler warnings? +Before submitting a patch, please try compiling at least once with @example -emacs.c -signal.c +configure --with-mule --use-union-type --error-checking=all @end example -@file{emacs.c} contains @code{main()} and other code that performs the most -basic environment initializations and handles shutting down the XEmacs -process (this includes @code{kill-emacs}, the normal way that XEmacs is -exited; @code{dump-emacs}, which is used during the build process to -write out the XEmacs executable; @code{run-emacs-from-temacs}, which can -be used to start XEmacs directly when temacs has finished loading all -the Lisp code; and emergency code to handle crashes [XEmacs tries to -auto-save all files before it crashes]). +@node Regression Testing XEmacs, CVS Techniques, Rules When Writing New C Code, Top +@chapter Regression Testing XEmacs +@cindex testing, regression -Low-level code that directly interacts with the Unix signal mechanism, -however, is in @file{signal.c}. Note that this code does not handle system -dependencies in interfacing to signals; that is handled using the -@file{syssignal.h} header file, described in section J below. +@menu +* How to Regression-Test:: +* Modules for Regression Testing:: +@end menu + +@node How to Regression-Test, Modules for Regression Testing, Regression Testing XEmacs, Regression Testing XEmacs +@section How to Regression-Test +@cindex how to regression-test +@cindex regression-test, how to +@cindex testing, regression, how to + +The source directory @file{tests/automated} contains XEmacs' automated +test suite. The usual way of running all the tests is running +@code{make check} from the top-level build directory. +The test suite is unfinished and it's still lacking some essential +features. It is nevertheless recommended that you run the tests to +confirm that XEmacs behaves correctly. +If you want to run a specific test case, you can do it from the +command-line like this: @example -unexaix.c -unexalpha.c -unexapollo.c -unexconvex.c -unexec.c -unexelf.c -unexelfsgi.c -unexencap.c -unexenix.c -unexfreebsd.c -unexfx2800.c -unexhp9k3.c -unexhp9k800.c -unexmips.c -unexnext.c -unexsol2.c -unexsunos4.c +$ xemacs -batch -l test-harness.elc -f batch-test-emacs TEST-FILE @end example -These modules contain code dumping out the XEmacs executable on various -different systems. (This process is highly machine-specific and -requires intimate knowledge of the executable format and the memory map -of the process.) Only one of these modules is actually used; this is -chosen by @file{configure}. +If a test fails and you need more information, you can run the test +suite interactively by loading @file{test-harness.el} into a running +XEmacs and typing @kbd{M-x test-emacs-test-file RET <filename> RET}. +You will see a log of passed and failed tests, which should allow you to +investigate the source of the error and ultimately fix the bug. If you +are not capable of, or don't have time for, debugging it yourself, +please do report the failures using @kbd{M-x report-emacs-bug} or +@kbd{M-x build-report}. +@deffn Command test-emacs-test-file file +Runs the tests in @var{file}. @file{test-harness.el} must be loaded. +Defines all the macros described in this node, and undefines them when +done. +@end deffn +Adding a new test file is trivial: just create a new file here and it +will be run. There is no need to byte-compile any of the files in +this directory---the test-harness will take care of any necessary +byte-compilation. -@example -ecrt0.c -lastfile.c -pre-crt0.c -@end example +Look at the existing test cases for the examples of coding test cases. +It all boils down to your imagination and judicious use of the macros +@code{Assert}, @code{Check-Error}, @code{Check-Error-Message}, and +@code{Check-Message}. Note that all of these macros are defined only +for the duration of the test: they do not exist in the global +environment. -These modules are used in conjunction with the dump mechanism. On some -systems, an alternative version of the C startup code (the actual code -that receives control from the operating system when the process is -started, and which calls @code{main()}) is required so that the dumping -process works properly; @file{crt0.c} provides this. +@deffn Macro Assert expr +Check that @var{expr} is non-nil at this point in the test. +@end deffn -@file{pre-crt0.c} and @file{lastfile.c} should be the very first and -very last file linked, respectively. (Actually, this is not really true. -@file{lastfile.c} should be after all Emacs modules whose initialized -data should be made constant, and before all other Emacs files and all -libraries. In particular, the allocation modules @file{gmalloc.c}, -@file{alloca.c}, etc. are normally placed past @file{lastfile.c}, and -all of the files that implement Xt widget classes @emph{must} be placed -after @file{lastfile.c} because they contain various structures that -must be statically initialized and into which Xt writes at various -times.) @file{pre-crt0.c} and @file{lastfile.c} contain exported symbols -that are used to determine the start and end of XEmacs' initialized -data space when dumping. +@deffn Macro Check-Error expected-error body +Check that execution of @var{body} causes @var{expected-error} to be +signaled. @var{body} is a @code{progn}-like body, and may contain +several expressions. @var{expected-error} is a symbol defined as +an error by @code{define-error}. +@end deffn + +@deffn Macro Check-Error-Message expected-error expected-error-regexp body +Check that execution of @var{body} causes @var{expected-error} to be +signaled, and generate a message matching @var{expected-error-regexp}. +@var{body} is a @code{progn}-like body, and may contain several +expressions. @var{expected-error} is a symbol defined as an error +by @code{define-error}. +@end deffn +@deffn Macro Check-Message expected-message body +Check that execution of @var{body} causes @var{expected-message} to be +generated (using @code{message} or a similar function). @var{body} is a +@code{progn}-like body, and may contain several expressions. +@end deffn +Here's a simple example checking case-sensitive and case-insensitive +comparisons from @file{case-tests.el}. @example -alloca.c -free-hook.c -getpagesize.h -gmalloc.c -malloc.c -mem-limits.h -ralloc.c -vm-limit.c +(with-temp-buffer + (insert "Test Buffer") + (let ((case-fold-search t)) + (goto-char (point-min)) + (Assert (eq (search-forward "test buffer" nil t) 12)) + (goto-char (point-min)) + (Assert (eq (search-forward "Test buffer" nil t) 12)) + (goto-char (point-min)) + (Assert (eq (search-forward "Test Buffer" nil t) 12)) + + (setq case-fold-search nil) + (goto-char (point-min)) + (Assert (not (search-forward "test buffer" nil t))) + (goto-char (point-min)) + (Assert (not (search-forward "Test buffer" nil t))) + (goto-char (point-min)) + (Assert (eq (search-forward "Test Buffer" nil t) 12)))) @end example -These handle basic C allocation of memory. @file{alloca.c} is an emulation of -the stack allocation function @code{alloca()} on machines that lack -this. (XEmacs makes extensive use of @code{alloca()} in its code.) +This example could be saved in a file in @file{tests/automated}, and it +would constitute a complete test, automatically executed when you run +@kbd{make check} after building XEmacs. More complex tests may require +substantial temporary scaffolding to create the environment that elicits +the bugs, but the top-level @file{Makefile} and @file{test-harness.el} +handle the running and collection of results from the @code{Assert}, +@code{Check-Error}, @code{Check-Error-Message}, and @code{Check-Message} +macros. -@file{gmalloc.c} and @file{malloc.c} are two implementations of the standard C -functions @code{malloc()}, @code{realloc()} and @code{free()}. They are -often used in place of the standard system-provided @code{malloc()} -because they usually provide a much faster implementation, at the -expense of additional memory use. @file{gmalloc.c} is a newer implementation -that is much more memory-efficient for large allocations than @file{malloc.c}, -and should always be preferred if it works. (At one point, @file{gmalloc.c} -didn't work on some systems where @file{malloc.c} worked; but this should be -fixed now.) +Don't suppress tests just because they're due to known bugs not yet +fixed---use the @code{Known-Bug-Expect-Failure} wrapper macro to mark +them. -@cindex relocating allocator -@file{ralloc.c} is the @dfn{relocating allocator}. It provides -functions similar to @code{malloc()}, @code{realloc()} and @code{free()} -that allocate memory that can be dynamically relocated in memory. The -advantage of this is that allocated memory can be shuffled around to -place all the free memory at the end of the heap, and the heap can then -be shrunk, releasing the memory back to the operating system. The use -of this can be controlled with the configure option @code{--rel-alloc}; -if enabled, memory allocated for buffers will be relocatable, so that if -a very large file is visited and the buffer is later killed, the memory -can be released to the operating system. (The disadvantage of this -mechanism is that it can be very slow. On systems with the -@code{mmap()} system call, the XEmacs version of @file{ralloc.c} uses -this to move memory around without actually having to block-copy it, -which can speed things up; but it can still cause noticeable performance -degradation.) - -On Linux systems using @samp{glibc 2}, these strategies are built in to -the so-called ``Doug Lea malloc.'' See, for example, Doug Lea's home -page, especially @uref{http://gee.cs.oswego.edu/dl/html/malloc.html,``A -Memory Allocator''}. The source file, @file{malloc.c} (available at the -same place) is copiously (and usefully!) commented. -@uref{http://www.malloc.de/,Wolfram Gloger's home page} may also be -useful. - -@file{free-hook.c} contains some debugging functions for checking for invalid -arguments to @code{free()}. +@deffn Macro Known-Bug-Expect-Failure body +Arrange for failing tests in @var{body} to generate messages prefixed +with "KNOWN BUG:" instead of "FAIL:". @var{body} is a @code{progn}-like +body, and may contain several tests. +@end deffn -@file{vm-limit.c} contains some functions that warn the user when memory is -getting low. These are callback functions that are called by @file{gmalloc.c} -and @file{malloc.c} at appropriate times. +A lot of the tests we run push limits; suppress Ebola warning messages +with the @code{Ignore-Ebola} wrapper macro. -@file{getpagesize.h} provides a uniform interface for retrieving the size of a -page in virtual memory. @file{mem-limits.h} provides a uniform interface for -retrieving the total amount of available virtual memory. Both are -similar in spirit to the @file{sys*.h} files described in section J, below. +@deffn Macro Ignore-Ebola body +Suppress Ebola warning messages while running tests in @var{body}. +@var{body} is a @code{progn}-like body, and may contain several tests. +@end deffn +Both macros are defined temporarily within the test function. Simple +examples: @example -blocktype.c -blocktype.h -dynarr.c +;; Apparently Ignore-Ebola is a solution with no problem to address. +;; There are no examples in 21.5, anyway. + +;; from regexp-tests.el +(Known-Bug-Expect-Failure + (Assert (not (string-match "\\b" ""))) + (Assert (not (string-match " \\b" " ")))) @end example -These implement a couple of basic C data types to facilitate memory -allocation. The @code{Blocktype} type efficiently manages the -allocation of fixed-size blocks by minimizing the number of times that -@code{malloc()} and @code{free()} are called. It allocates memory in -large chunks, subdivides the chunks into blocks of the proper size, and -returns the blocks as requested. When blocks are freed, they are placed -onto a linked list, so they can be efficiently reused. This data type -is not much used in XEmacs currently, because it's a fairly new -addition. +In general, you should avoid using functionality from packages in your +tests, because you can't be sure that everyone will have the required +package. However, if you've got a test that works, by all means add it. +Simply wrap the test in an appropriate test, add a notice that the test +was skipped, and update the @code{skipped-test-reasons} hashtable. The +wrapper macro @code{Skip-Test-Unless} is provided to handle common +cases. -@cindex dynamic array -The @code{Dynarr} type implements a @dfn{dynamic array}, which is -similar to a standard C array but has no fixed limit on the number of -elements it can contain. Dynamic arrays can hold elements of any type, -and when you add a new element, the array automatically resizes itself -if it isn't big enough. Dynarrs are extensively used in the redisplay -mechanism. +@defvar skipped-test-reasons +Hash table counting the number of times a particular reason is given for +skipping tests. This is only defined within @code{test-emacs-test-file}. +@end defvar +@deffn Macro Skip-Test-Unless prerequisite reason description body +@var{prerequisite} is usually a feature test (@code{featurep}, +@code{boundp}, @code{fboundp}). @var{reason} is a string describing the +prerequisite; it must be unique because it is used as a hash key in a +table of reasons for skipping tests. @var{description} describes the +tests being skipped, for the test result summary. @var{body} is a +@code{progn}-like body, and may contain several tests. +@end deffn +@code{Skip-Test-Unless} is defined temporarily within the test function. +Here's an example of usage from @file{syntax-tests.el}: @example -inline.c +;; Test forward-comment at buffer boundaries +(with-temp-buffer + ;; try to use exactly what you need: featurep, boundp, fboundp + (Skip-Test-Unless (fboundp 'c-mode) + "c-mode unavailable" + "comment and parse-partial-sexp tests" + ;; and here's the test code + (c-mode) + (insert "// comment\n") + (forward-comment -2) + (Assert (eq (point) (point-min))) + (let ((point (point))) + (insert "/* comment */") + (goto-char point) + (forward-comment 2) + (Assert (eq (point) (point-max))) + (parse-partial-sexp point (point-max))))) @end example -This module is used in connection with inline functions (available in -some compilers). Often, inline functions need to have a corresponding -non-inline function that does the same thing. This module is where they -reside. It contains no actual code, but defines some special flags that -cause inline functions defined in header files to be rendered as actual -functions. It then includes all header files that contain any inline -function definitions, so that each one gets a real function equivalent. +@code{Skip-Test-Unless} is intended for use with features that are normally +present in typical configurations. For truly optional features, or +tests that apply to one of several alternative implementations (eg, to +GTK widgets, but not Athena, Motif, MS Windows, or Carbon), simply +silently suppress the test if the feature is not available. +Here are a few general hints for writing tests. +@enumerate +@item +Include related successful cases. Fixes often break something. -@example -debug.c -debug.h -@end example +@item +Use the Known-Bug-Expect-Failure macro to mark the cases you know +are going to fail. We want to be able to distinguish between +regressions and other unexpected failures, and cases that have +been (partially) analyzed but not yet repaired. -These functions provide a system for doing internal consistency checks -during code development. This system is not currently used; instead the -simpler @code{assert()} macro is used along with the various checks -provided by the @samp{--error-check-*} configuration options. +@item +Mark the bug with the date of report. An ``Unfixed since yyyy-mm-dd'' +gloss for Known-Bug-Expect-Failure is planned to further increase +developer embarrassment (== incentive to fix the bug), but until then at +least put a comment about the date so we can easily see when it was +first reported. + +@item +It's a matter of your judgement, but you should often use generic tests +(@emph{e.g.}, @code{eq}) instead of more specific tests (@code{=} for +numbers) even though you know that arguments ``should'' be of correct +type. That is, if the functions used can return generic objects +(typically @code{nil}), as well as some more specific type that will be +returned on success. We don't want failures of those assertions +reported as ``other failures'' (a wrong-type-arg signal, rather than a +null return), we want them reported as ``assertion failures.'' +One example is a test that tests @code{(= (string-match this that) 0)}, +expecting a successful match. Now suppose @code{string-match} is broken +such that the match fails. Then it will return @code{nil}, and @code{=} +will signal ``wrong-type-argument, number-char-or-marker-p, nil'', +generating an ``other failure'' in the report. But this should be +reported as an assertion failure (the test failed in a foreseeable way), +rather than something else (we don't know what happened because XEmacs +is broken in a way that we weren't trying to test!) +@end enumerate +@node Modules for Regression Testing, , How to Regression-Test, Regression Testing XEmacs +@section Modules for Regression Testing +@cindex modules for regression testing +@cindex regression testing, modules for @example -universe.h +@file{test-harness.el} +@file{base64-tests.el} +@file{byte-compiler-tests.el} +@file{case-tests.el} +@file{ccl-tests.el} +@file{c-tests.el} +@file{database-tests.el} +@file{extent-tests.el} +@file{hash-table-tests.el} +@file{lisp-tests.el} +@file{md5-tests.el} +@file{mule-tests.el} +@file{regexp-tests.el} +@file{symbol-tests.el} +@file{syntax-tests.el} +@file{tag-tests.el} +@file{weak-tests.el} @end example -This is not currently used. +@file{test-harness.el} defines the macros @code{Assert}, +@code{Check-Error}, @code{Check-Error-Message}, and +@code{Check-Message}. The other files are test files, testing various +XEmacs facilities. @xref{Regression Testing XEmacs}. + +@node CVS Techniques, XEmacs from the Inside, Regression Testing XEmacs, Top +@chapter CVS Techniques +@cindex CVS techniques +@menu +* Merging a Branch into the Trunk:: +@end menu +@node Merging a Branch into the Trunk, , CVS Techniques, CVS Techniques +@section Merging a Branch into the Trunk +@cindex merging a branch into the trunk -@node Basic Lisp Modules -@section Basic Lisp Modules -@cindex Lisp modules, basic -@cindex modules, basic Lisp +@enumerate +@item +If you haven't already done a merge, you will be merging from the branch +point; otherwise you'll be merging from the last merge point, which +should be marked by a tag, e.g. @samp{last-sync-ben-mule-21-5}. In the +former case, create the last-sync tag, e.g. @example -lisp-disunion.h -lisp-union.h -lisp.h -lrecord.h -symsinit.h +crw rtag -r ben-mule-21-5-bp last-sync-ben-mule-21-5 xemacs @end example -These are the basic header files for all XEmacs modules. Each module -includes @file{lisp.h}, which brings the other header files in. -@file{lisp.h} contains the definitions of the structures and extractor -and constructor macros for the basic Lisp objects and various other -basic definitions for the Lisp environment, as well as some -general-purpose definitions (e.g. @code{min()} and @code{max()}). -@file{lisp.h} includes either @file{lisp-disunion.h} or -@file{lisp-union.h}, depending on whether @code{USE_UNION_TYPE} is -defined. These files define the typedef of the Lisp object itself (as -described above) and the low-level macros that hide the actual -implementation of the Lisp object. All extractor and constructor macros -for particular types of Lisp objects are defined in terms of these -low-level macros. - -As a general rule, all typedefs should go into the typedefs section of -@file{lisp.h} rather than into a module-specific header file even if the -structure is defined elsewhere. This allows function prototypes that -use the typedef to be placed into other header files. Forward structure -declarations (i.e. a simple declaration like @code{struct foo;} where -the structure itself is defined elsewhere) should be placed into the -typedefs section as necessary. - -@file{lrecord.h} contains the basic structures and macros that implement -all record-type Lisp objects---i.e. all objects whose type is a field -in their C structure, which includes all objects except the few most -basic ones. - -@file{lisp.h} contains prototypes for most of the exported functions in -the various modules. Lisp primitives defined using @code{DEFUN} that -need to be called by C code should be declared using @code{EXFUN}. -Other function prototypes should be placed either into the appropriate -section of @code{lisp.h}, or into a module-specific header file, -depending on how general-purpose the function is and whether it has -special-purpose argument types requiring definitions not in -@file{lisp.h}.) All initialization functions are prototyped in -@file{symsinit.h}. +(You did create a branch point tag when you created the branch, didn't +you?) +@item +Check everything in on your branch. +@item +Tag your branch with a pre-sync tag, e.g. @example -alloc.c +crw rtag -r ben-mule-21-5 ben-mule-21-5-pre-feb-20-2002-sync xemacs @end example -The large module @file{alloc.c} implements all of the basic allocation and -garbage collection for Lisp objects. The most commonly used Lisp -objects are allocated in chunks, similar to the Blocktype data type -described above; others are allocated in individually @code{malloc()}ed -blocks. This module provides the foundation on which all other aspects -of the Lisp environment sit, and is the first module initialized at -startup. - -Note that @file{alloc.c} provides a series of generic functions that are -not dependent on any particular object type, and interfaces to -particular types of objects using a standardized interface of -type-specific methods. This scheme is a fundamental principle of -object-oriented programming and is heavily used throughout XEmacs. The -great advantage of this is that it allows for a clean separation of -functionality into different modules---new classes of Lisp objects, new -event interfaces, new device types, new stream interfaces, etc. can be -added transparently without affecting code anywhere else in XEmacs. -Because the different subsystems are divided into general and specific -code, adding a new subtype within a subsystem will in general not -require changes to the generic subsystem code or affect any of the other -subtypes in the subsystem; this provides a great deal of robustness to -the XEmacs code. +Note, you need to use rtag and specify a version with @samp{-r} (use +@samp{-r HEAD} if necessary) so that removed files are handled correctly +in some obscure cases. See section 4.8 of the CVS manual. +@item +Tag the trunk so you have a stable place to merge up to in case people +are asynchronously committing to the trunk, e.g. @example -eval.c -backtrace.h +crw rtag -r HEAD main-branch-ben-mule-21-5-syncpoint-feb-20-2002 xemacs +crw rtag -F -r main-branch-ben-mule-21-5-syncpoint-feb-20-2002 next-sync-ben-mule-21-5 xemacs @end example -This module contains all of the functions to handle the flow of control. -This includes the mechanisms of defining functions, calling functions, -traversing stack frames, and binding variables; the control primitives -and other special forms such as @code{while}, @code{if}, @code{eval}, -@code{let}, @code{and}, @code{or}, @code{progn}, etc.; handling of -non-local exits, unwind-protects, and exception handlers; entering the -debugger; methods for the subr Lisp object type; etc. It does -@emph{not} include the @code{read} function, the @code{print} function, -or the handling of symbols and obarrays. +Use -F in the second case because the name might already exist, e.g. if +you've already done a merge. We make two tags because one is a +permanent mark indicating a syncpoint when merging, and the other is a +symbolic tag to make other operations easier. -@file{backtrace.h} contains some structures related to stack frames and the -flow of control. +@item +Make a backup of your source tree (not totally necessary but useful for +reference and peace of mind): Move one level up from the top directory +of your branch and do, e.g. +@example +cp -a mule mule-backup-2-23-02 +@end example +@item +Now, we're ready to merge! Make sure you're in the top directory of +your branch and do, e.g. @example -lread.c +cvs update -j last-sync-ben-mule-21-5 -j next-sync-ben-mule-21-5 @end example -This module implements the Lisp reader and the @code{read} function, -which converts text into Lisp objects, according to the read syntax of -the objects, as described above. This is similar to the parser that is -a part of all compilers. +@item +Fix all merge conflicts. Get the sucker to compile and run. +@item +Tag your branch with a post-sync tag, e.g. + +@example +crw rtag -r ben-mule-21-5 ben-mule-21-5-post-feb-20-2002-sync xemacs +@end example +@item +Update the last-sync tag, e.g. @example -print.c +crw rtag -F -r next-sync-ben-mule-21-5 last-sync-ben-mule-21-5 xemacs @end example +@end enumerate -This module implements the Lisp print mechanism and the @code{print} -function and related functions. This is the inverse of the Lisp reader --- it converts Lisp objects to a printed, textual representation. -(Hopefully something that can be read back in using @code{read} to get -an equivalent object.) +@node XEmacs from the Inside, Basic Types, CVS Techniques, Top +@chapter XEmacs from the Inside +@cindex XEmacs from the inside +@cindex inside, XEmacs from the +Internally, XEmacs is quite complex, and can be very confusing. To +simplify things, it can be useful to think of XEmacs as containing an +event loop that ``drives'' everything, and a number of other subsystems, +such as a Lisp engine and a redisplay mechanism. Each of these other +subsystems exists simultaneously in XEmacs, and each has a certain +state. The flow of control continually passes in and out of these +different subsystems in the course of normal operation of the editor. -@example -general.c -symbols.c -symeval.h -@end example +It is important to keep in mind that, most of the time, the editor is +``driven'' by the event loop. Except during initialization and batch +mode, all subsystems are entered directly or indirectly through the +event loop, and ultimately, control exits out of all subsystems back up +to the event loop. This cycle of entering a subsystem, exiting back out +to the event loop, and starting another iteration of the event loop +occurs once each keystroke, mouse motion, etc. -@file{symbols.c} implements the handling of symbols, obarrays, and -retrieving the values of symbols. Much of the code is devoted to -handling the special @dfn{symbol-value-magic} objects that define -special types of variables---this includes buffer-local variables, -variable aliases, variables that forward into C variables, etc. This -module is initialized extremely early (right after @file{alloc.c}), -because it is here that the basic symbols @code{t} and @code{nil} are -created, and those symbols are used everywhere throughout XEmacs. +If you're trying to understand a particular subsystem (other than the +event loop), think of it as a ``daemon'' process or ``servant'' that is +responsible for one particular aspect of a larger system, and +periodically receives commands or environment changes that cause it to +do something. Ultimately, these commands and environment changes are +always triggered by the event loop. For example: -@file{symeval.h} contains the definitions of symbol structures and the -@code{DEFVAR_LISP()} and related macros for declaring variables. +@itemize @bullet +@item +The window and frame mechanism is responsible for keeping track of what +windows and frames exist, what buffers are in them, etc. It is +periodically given commands (usually from the user) to make a change to +the current window/frame state: i.e. create a new frame, delete a +window, etc. +@item +The buffer mechanism is responsible for keeping track of what buffers +exist and what text is in them. It is periodically given commands +(usually from the user) to insert or delete text, create a buffer, etc. +When it receives a text-change command, it notifies the redisplay +mechanism. +@item +The redisplay mechanism is responsible for making sure that windows and +frames are displayed correctly. It is periodically told (by the event +loop) to actually ``do its job'', i.e. snoop around and see what the +current state of the environment (mostly of the currently-existing +windows, frames, and buffers) is, and make sure that state matches +what's actually displayed. It keeps lots and lots of information around +(such as what is actually being displayed currently, and what the +environment was last time it checked) so that it can minimize the work +it has to do. It is also helped along in that whenever a relevant +change to the environment occurs, the redisplay mechanism is told about +this, so it has a pretty good idea of where it has to look to find +possible changes and doesn't have to look everywhere. -@example -data.c -floatfns.c -fns.c -@end example +@item +The Lisp engine is responsible for executing the Lisp code in which most +user commands are written. It is entered through a call to @code{eval} +or @code{funcall}, which occurs as a result of dispatching an event from +the event loop. The functions it calls issue commands to the buffer +mechanism, the window/frame subsystem, etc. -These modules implement the methods and standard Lisp primitives for all -the basic Lisp object types other than symbols (which are described -above). @file{data.c} contains all the predicates (primitives that return -whether an object is of a particular type); the integer arithmetic -functions; and the basic accessor and mutator primitives for the various -object types. @file{fns.c} contains all the standard predicates for working -with sequences (where, abstractly speaking, a sequence is an ordered set -of objects, and can be represented by a list, string, vector, or -bit-vector); it also contains @code{equal}, perhaps on the grounds that -bulk of the operation of @code{equal} is comparing sequences. -@file{floatfns.c} contains methods and primitives for floats and floating-point -arithmetic. +@item +The Lisp allocation subsystem is responsible for keeping track of Lisp +objects. It is given commands from the Lisp engine to allocate objects, +garbage collect, etc. +@end itemize +etc. + The important idea here is that there are a number of independent +subsystems each with its own responsibility and persistent state, just +like different employees in a company, and each subsystem is +periodically given commands from other subsystems. Commands can flow +from any one subsystem to any other, but there is usually some sort of +hierarchy, with all commands originating from the event subsystem. -@example -bytecode.c -bytecode.h -@end example + XEmacs is entered in @code{main()}, which is in @file{emacs.c}. When +this is called the first time (in a properly-invoked @file{temacs}), it +does the following: -@file{bytecode.c} implements the byte-code interpreter and -compiled-function objects, and @file{bytecode.h} contains associated -structures. Note that the byte-code @emph{compiler} is written in Lisp. +@enumerate +@item +It does some very basic environment initializations, such as determining +where it and its directories (e.g. @file{lisp/} and @file{etc/}) reside +and setting up signal handlers. +@item +It initializes the entire Lisp interpreter. +@item +It sets the initial values of many built-in variables (including many +variables that are visible to Lisp programs), such as the global keymap +object and the built-in faces (a face is an object that describes the +display characteristics of text). This involves creating Lisp objects +and thus is dependent on step (2). +@item +It performs various other initializations that are relevant to the +particular environment it is running in, such as retrieving environment +variables, determining the current date and the user who is running the +program, examining its standard input, creating any necessary file +descriptors, etc. +@item +At this point, the C initialization is complete. A Lisp program that +was specified on the command line (usually @file{loadup.el}) is called +(temacs is normally invoked as @code{temacs -batch -l loadup.el dump}). +@file{loadup.el} loads all of the other Lisp files that are needed for +the operation of the editor, calls the @code{dump-emacs} function to +write out @file{xemacs}, and then kills the temacs process. +@end enumerate + When @file{xemacs} is then run, it only redoes steps (1) and (4) +above; all variables already contain the values they were set to when +the executable was dumped, and all memory that was allocated with +@code{malloc()} is still around. (XEmacs knows whether it is being run +as @file{xemacs} or @file{temacs} because it sets the global variable +@code{initialized} to 1 after step (4) above.) At this point, +@file{xemacs} calls a Lisp function to do any further initialization, +which includes parsing the command-line (the C code can only do limited +command-line parsing, which includes looking for the @samp{-batch} and +@samp{-l} flags and a few other flags that it needs to know about before +initialization is complete), creating the first frame (or @dfn{window} +in standard window-system parlance), running the user's init file +(usually the file @file{.emacs} in the user's home directory), etc. The +function to do this is usually called @code{normal-top-level}; +@file{loadup.el} tells the C code about this function by setting its +name as the value of the Lisp variable @code{top-level}. + When the Lisp initialization code is done, the C code enters the event +loop, and stays there for the duration of the XEmacs process. The code +for the event loop is contained in @file{cmdloop.c}, and is called +@code{Fcommand_loop_1()}. Note that this event loop could very well be +written in Lisp, and in fact a Lisp version exists; but apparently, +doing this makes XEmacs run noticeably slower. + Notice how much of the initialization is done in Lisp, not in C. +In general, XEmacs tries to move as much code as is possible into +Lisp. Code that remains in C is code that implements the Lisp +interpreter itself, or code that needs to be very fast, or code that +needs to do system calls or other such stuff that needs to be done in +C, or code that needs to have access to ``forbidden'' structures. (One +conscious aspect of the design of Lisp under XEmacs is a clean +separation between the external interface to a Lisp object's +functionality and its internal implementation. Part of this design is +that Lisp programs are forbidden from accessing the contents of the +object other than through using a standard API. In this respect, +XEmacs Lisp is similar to modern Lisp dialects but differs from GNU +Emacs, which tends to expose the implementation and allow Lisp +programs to look at it directly. The major advantage of hiding the +implementation is that it allows the implementation to be redesigned +without affecting any Lisp programs, including those that might want +to be ``clever'' by looking directly at the object's contents and +possibly manipulating them.) -@node Modules for Standard Editing Operations -@section Modules for Standard Editing Operations -@cindex modules for standard editing operations -@cindex editing operations, modules for standard + Moving code into Lisp makes the code easier to debug and maintain and +makes it much easier for people who are not XEmacs developers to +customize XEmacs, because they can make a change with much less chance +of obscure and unwanted interactions occurring than if they were to +change the C code. -@example -buffer.c -buffer.h -bufslots.h -@end example +@node Basic Types, Low-Level Allocation, XEmacs from the Inside, Top +@chapter Basic Types +@cindex basic types +@cindex types, basic -@file{buffer.c} implements the @dfn{buffer} Lisp object type. This -includes functions that create and destroy buffers; retrieve buffers by -name or by other properties; manipulate lists of buffers (remember that -buffers are permanent objects and stored in various ordered lists); -retrieve or change buffer properties; etc. It also contains the -definitions of all the built-in buffer-local variables (which can be -viewed as buffer properties). It does @emph{not} contain code to -manipulate buffer-local variables (that's in @file{symbols.c}, described -above); or code to manipulate the text in a buffer. +Not yet documented. -@file{buffer.h} defines the structures associated with a buffer and the various -macros for retrieving text from a buffer and special buffer positions -(e.g. @code{point}, the default location for text insertion). It also -contains macros for working with buffer positions and converting between -their representations as character offsets and as byte offsets (under -MULE, they are different, because characters can be multi-byte). It is -one of the largest header files. +@node Low-Level Allocation, The XEmacs Object System (Abstractly Speaking), Basic Types, Top +@chapter Low-Level Allocation +@cindex low-level allocation +@cindex allocation, low-level -@file{bufslots.h} defines the fields in the buffer structure that correspond to -the built-in buffer-local variables. It is its own header file because -it is included many times in @file{buffer.c}, as a way of iterating over all -the built-in buffer-local variables. +@menu +* Basic Heap Allocation:: +* Stack Allocation:: +* Dynamic Arrays:: +* Allocation by Blocks:: +* Modules for Allocation:: +@end menu +@node Basic Heap Allocation, Stack Allocation, Low-Level Allocation, Low-Level Allocation +@section Basic Heap Allocation +@cindex basic heap allocation + +@node Stack Allocation, Dynamic Arrays, Basic Heap Allocation, Low-Level Allocation +@section Stack Allocation +@cindex stack allocation + +@node Dynamic Arrays, Allocation by Blocks, Stack Allocation, Low-Level Allocation +@section Dynamic Arrays +@cindex dynamic arrays +@cindex dynamic array +The @code{Dynarr} type implements a @dfn{dynamic array}, which is +similar to a standard C array but has no fixed limit on the number of +elements it can contain. Dynamic arrays can hold elements of any type, +and when you add a new element, the array automatically resizes itself +if it isn't big enough. Dynarrs are extensively used in the redisplay +mechanism. -@example -insdel.c -insdel.h -@end example -@file{insdel.c} contains low-level functions for inserting and deleting text in -a buffer, keeping track of changed regions for use by redisplay, and -calling any before-change and after-change functions that may have been -registered for the buffer. It also contains the actual functions that -convert between byte offsets and character offsets. +A "dynamic array" is a contiguous array of fixed-size elements where there +is no upper limit (except available memory) on the number of elements in the +array. Because the elements are maintained contiguously, space is used +efficiently (no per-element pointers necessary) and random access to a +particular element is in constant time. At any one point, the block of memory +that holds the array has an upper limit; if this limit is exceeded, the +memory is realloc()ed into a new array that is twice as big. Assuming that +the time to grow the array is on the order of the new size of the array +block, this scheme has a provably constant amortized time (i.e. average +time over all additions). + +When you add elements or retrieve elements, pointers are used. Note that +the element itself (of whatever size it is), and not the pointer to it, +is stored in the array; thus you do not have to allocate any heap memory +on your own. Also, returned pointers are only guaranteed to be valid +until the next operation that changes the length of the array. -@file{insdel.h} contains associated headers. +This is a container object. Declare a dynamic array of a specific type +as follows: + typedef struct + @{ + Dynarr_declare (mytype); + @} mytype_dynarr; +Use the following functions/macros: @example -marker.c -@end example +void *Dynarr_new(type) + [MACRO] Create a new dynamic-array object, with each element of the + specified type. The return value is cast to (type##_dynarr). + This requires following the convention that types are declared in + such a way that this type concatenation works. In particular, TYPE + must be a symbol, not an arbitrary C type. -This module implements the @dfn{marker} Lisp object type, which -conceptually is a pointer to a text position in a buffer that moves -around as text is inserted and deleted, so as to remain in the same -relative position. This module doesn't actually move the markers around --- that's handled in @file{insdel.c}. This module just creates them and -implements the primitives for working with them. As markers are simple -objects, this does not entail much. +Dynarr_add(d, el) + [MACRO] Add an element to the end of a dynamic array. EL is a pointer + to the element; the element itself is stored in the array, however. + No function call is performed unless the array needs to be resized. -Note that the standard arithmetic primitives (e.g. @code{+}) accept -markers in place of integers and automatically substitute the value of -@code{marker-position} for the marker, i.e. an integer describing the -current buffer position of the marker. +Dynarr_add_many(d, base, len) + [MACRO] Add LEN elements to the end of the dynamic array. The elements + should be contiguous in memory, starting at BASE. If BASE if NULL, + just make space for the elements; don't actually add them. +Dynarr_insert_many_at_start(d, base, len) + [MACRO] Append LEN elements to the beginning of the dynamic array. + The elements should be contiguous in memory, starting at BASE. + If BASE if NULL, just make space for the elements; don't actually + add them. +Dynarr_insert_many(d, base, len, start) + Insert LEN elements to the dynamic array starting at position + START. The elements should be contiguous in memory, starting at BASE. + If BASE if NULL, just make space for the elements; don't actually + add them. -@example -extents.c -extents.h -@end example - -This module implements the @dfn{extent} Lisp object type, which is like -a marker that works over a range of text rather than a single position. -Extents are also much more complex and powerful than markers and have a -more efficient (and more algorithmically complex) implementation. The -implementation is described in detail in comments in @file{extents.c}. - -The code in @file{extents.c} works closely with @file{insdel.c} so that -extents are properly moved around as text is inserted and deleted. -There is also code in @file{extents.c} that provides information needed -by the redisplay mechanism for efficient operation. (Remember that -extents can have display properties that affect [sometimes drastically, -as in the @code{invisible} property] the display of the text they -cover.) +Dynarr_delete(d, i) + [MACRO] Delete an element from the dynamic array at position I. +Dynarr_delete_many(d, start, len) + Delete LEN elements from the dynamic array starting at position + START. +Dynarr_delete_by_pointer(d, p) + [MACRO] Delete an element from the dynamic array at pointer P, + which must point within the block of memory that stores the data. + P should be obtained using Dynarr_atp(). -@example -editfns.c -@end example +int Dynarr_length(d) + [MACRO] Return the number of elements currently in a dynamic array. -@file{editfns.c} contains the standard Lisp primitives for working with -a buffer's text, and calls the low-level functions in @file{insdel.c}. -It also contains primitives for working with @code{point} (the default -buffer insertion location). +int Dynarr_largest(d) + [MACRO] Return the maximum value that Dynarr_length(d) would + ever have returned. -@file{editfns.c} also contains functions for retrieving various -characteristics from the external environment: the current time, the -process ID of the running XEmacs process, the name of the user who ran -this XEmacs process, etc. It's not clear why this code is in -@file{editfns.c}. +type Dynarr_at(d, i) + [MACRO] Return the element at the specified index (no bounds checking + done on the index). The element itself is returned, not a pointer + to it. +type *Dynarr_atp(d, i) + [MACRO] Return a pointer to the element at the specified index (no + bounds checking done on the index). The pointer may not be valid + after an element is added to or removed from the array. +Dynarr_reset(d) + [MACRO] Reset the length of a dynamic array to 0. -@example -callint.c -cmds.c -commands.h +Dynarr_free(d) + Destroy a dynamic array and the memory allocated to it. @end example -@cindex interactive -These modules implement the basic @dfn{interactive} commands, -i.e. user-callable functions. Commands, as opposed to other functions, -have special ways of getting their parameters interactively (by querying -the user), as opposed to having them passed in a normal function -invocation. Many commands are not really meant to be called from other -Lisp functions, because they modify global state in a way that's often -undesired as part of other Lisp functions. - -@file{callint.c} implements the mechanism for querying the user for -parameters and calling interactive commands. The bulk of this module is -code that parses the interactive spec that is supplied with an -interactive command. - -@file{cmds.c} implements the basic, most commonly used editing commands: -commands to move around the current buffer and insert and delete -characters. These commands are implemented using the Lisp primitives -defined in @file{editfns.c}. - -@file{commands.h} contains associated structure definitions and prototypes. - - +Use the following global variable: @example -regex.c -regex.h -search.c + Dynarr_min_size + Minimum allowable size for a dynamic array when it is resized. @end example -@file{search.c} implements the Lisp primitives for searching for text in -a buffer, and some of the low-level algorithms for doing this. In -particular, the fast fixed-string Boyer-Moore search algorithm is -implemented in @file{search.c}. The low-level algorithms for doing -regular-expression searching, however, are implemented in @file{regex.c} -and @file{regex.h}. These two modules are largely independent of -XEmacs, and are similar to (and based upon) the regular-expression -routines used in @file{grep} and other GNU utilities. +@node Allocation by Blocks, Modules for Allocation, Dynamic Arrays, Low-Level Allocation +@section Allocation by Blocks +@cindex allocation by blocks + The @code{Blocktype} type efficiently manages the +allocation of fixed-size blocks by minimizing the number of times that +@code{malloc()} and @code{free()} are called. It allocates memory in +large chunks, subdivides the chunks into blocks of the proper size, and +returns the blocks as requested. When blocks are freed, they are placed +onto a linked list, so they can be efficiently reused. This data type +is not much used in XEmacs currently, because it's a fairly new +addition. -@example -doprnt.c -@end example +A "block-type object" is used to efficiently allocate and free blocks +of a particular size. Freed blocks are remembered in a free list and +are reused as necessary to allocate new blocks, so as to avoid as +much as possible making calls to malloc() and free(). -@file{doprnt.c} implements formatted-string processing, similar to -@code{printf()} command in C. +This is a container object. Declare a block-type object of a specific type +as follows: +struct mytype_blocktype @{ + Blocktype_declare (mytype); +@}; +Use the following functions/macros: @example -undo.c +structype *Blocktype_new(structype) + [MACRO] Create a new block-type object of the specified type. + The argument to this call should be the type of object to be + created, e.g. foobar_blocktype. +type *Blocktype_alloc(b) + [MACRO] Allocate a block of the proper type for the specified + block-type object and return a pointer to it. +Blocktype_free(b, block) + Free a block of the type corresponding to the specified block-type + object. +Blocktype_delete(b) + Destroy a block-type object and the memory allocated to it. @end example -This module implements the undo mechanism for tracking buffer changes. -Most of this could be implemented in Lisp. - - - -@node Editor-Level Control Flow Modules -@section Editor-Level Control Flow Modules -@cindex control flow modules, editor-level -@cindex modules, editor-level control flow -@example -event-Xt.c -event-msw.c -event-stream.c -event-tty.c -events-mod.h -gpmevent.c -gpmevent.h -events.c -events.h +@node Modules for Allocation, , Allocation by Blocks, Low-Level Allocation +@section Modules for Allocation +@cindex modules for allocation + +@example +@file{alloca.c} +@file{free-hook.c} +@file{getpagesize.h} +@file{gmalloc.c} +@file{malloc.c} +@file{mem-limits.h} +@file{ralloc.c} +@file{vm-limit.c} @end example -These implement the handling of events (user input and other system -notifications). - -@file{events.c} and @file{events.h} define the @dfn{event} Lisp object -type and primitives for manipulating it. - -@file{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 -@code{next-event} and @code{dispatch-event}, as well as related -primitives such as @code{sit-for}, @code{sleep-for}, and -@code{accept-process-output}. (@file{event-stream.c} is one of the -hairiest and trickiest modules in XEmacs. Beware! You can easily mess -things up here.) - -@file{event-Xt.c} and @file{event-tty.c} implement the low-level -interfaces onto retrieving events from Xt (the X toolkit) and from TTY's -(using @code{read()} and @code{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; -@file{event-Xt.c} and @file{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. +These handle basic C allocation of memory. @file{alloca.c} is an emulation of +the stack allocation function @code{alloca()} on machines that lack +this. (XEmacs makes extensive use of @code{alloca()} in its code.) -Note that the choice of whether to use @file{event-Xt.c} or -@file{event-tty.c} is made at compile time! Or at the very latest, it -is made at startup time. @file{event-Xt.c} handles events for -@emph{both} X and TTY frames; @file{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. +@file{gmalloc.c} and @file{malloc.c} are two implementations of the standard C +functions @code{malloc()}, @code{realloc()} and @code{free()}. They are +often used in place of the standard system-provided @code{malloc()} +because they usually provide a much faster implementation, at the +expense of additional memory use. @file{gmalloc.c} is a newer implementation +that is much more memory-efficient for large allocations than @file{malloc.c}, +and should always be preferred if it works. (At one point, @file{gmalloc.c} +didn't work on some systems where @file{malloc.c} worked; but this should be +fixed now.) +@cindex relocating allocator +@file{ralloc.c} is the @dfn{relocating allocator}. It provides +functions similar to @code{malloc()}, @code{realloc()} and @code{free()} +that allocate memory that can be dynamically relocated in memory. The +advantage of this is that allocated memory can be shuffled around to +place all the free memory at the end of the heap, and the heap can then +be shrunk, releasing the memory back to the operating system. The use +of this can be controlled with the configure option @code{--rel-alloc}; +if enabled, memory allocated for buffers will be relocatable, so that if +a very large file is visited and the buffer is later killed, the memory +can be released to the operating system. (The disadvantage of this +mechanism is that it can be very slow. On systems with the +@code{mmap()} system call, the XEmacs version of @file{ralloc.c} uses +this to move memory around without actually having to block-copy it, +which can speed things up; but it can still cause noticeable performance +degradation.) +On Linux systems using @samp{glibc 2}, these strategies are built in to +the so-called ``Doug Lea malloc.'' See, for example, Doug Lea's home +page, especially @uref{http://gee.cs.oswego.edu/dl/html/malloc.html,``A +Memory Allocator''}. The source file, @file{malloc.c} (available at the +same place) is copiously (and usefully!) commented. +@uref{http://www.malloc.de/,Wolfram Gloger's home page} may also be +useful. -@example -keymap.c -keymap.h -@end example +@file{free-hook.c} contains some debugging functions for checking for invalid +arguments to @code{free()}. -@file{keymap.c} and @file{keymap.h} define the @dfn{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; @code{dispatch-event} looks up events in the -relevant keymaps.) +@file{vm-limit.c} contains some functions that warn the user when memory is +getting low. These are callback functions that are called by @file{gmalloc.c} +and @file{malloc.c} at appropriate times. +@file{getpagesize.h} provides a uniform interface for retrieving the size of a +page in virtual memory. @file{mem-limits.h} provides a uniform interface for +retrieving the total amount of available virtual memory. Both are +similar in spirit to the @file{sys*.h} files described in section J, below. @example -cmdloop.c +@file{blocktype.c} +@file{blocktype.h} +@file{dynarr.c} @end example -@file{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 -@file{event-stream.c}. +These implement a couple of basic C data types to facilitate memory +allocation. +@node The XEmacs Object System (Abstractly Speaking), How Lisp Objects Are Represented in C, Low-Level Allocation, Top +@chapter The XEmacs Object System (Abstractly Speaking) +@cindex XEmacs object system (abstractly speaking), the +@cindex object system (abstractly speaking), the XEmacs + At the heart of the Lisp interpreter is its management of objects. +XEmacs Lisp contains many built-in objects, some of which are +simple and others of which can be very complex; and some of which +are very common, and others of which are rarely used or are only +used internally. (Since the Lisp allocation system, with its +automatic reclamation of unused storage, is so much more convenient +than @code{malloc()} and @code{free()}, the C code makes extensive use of it +in its internal operations.) -@example -macros.c -macros.h -@end example + The basic Lisp objects are -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 @file{event-stream.c}. +@table @code +@item integer +31 bits of precision, or 63 bits on 64-bit machines; the +reason for this is described below when the internal Lisp object +representation is described. +@item char +An object representing a single character of text; chars behave like +integers in many ways but are logically considered text rather than +numbers and have a different read syntax. (the read syntax for a char +contains the char itself or some textual encoding of it---for example, +a Japanese Kanji character might be encoded as @samp{^[$(B#&^[(B} using the +ISO-2022 encoding standard---rather than the numerical representation +of the char; this way, if the mapping between chars and integers +changes, which is quite possible for Kanji characters and other extended +characters, the same character will still be created. Note that some +primitives confuse chars and integers. The worst culprit is @code{eq}, +which makes a special exception and considers a char to be @code{eq} to +its integer equivalent, even though in no other case are objects of two +different types @code{eq}. The reason for this monstrosity is +compatibility with existing code; the separation of char from integer +came fairly recently.) +@item float +Same precision as a double in C. +@item bignum +@itemx ratio +@itemx bigfloat +As build-time options, arbitrary-precision numbers are available. +Bignums are integers, and when available they remove the restriction on +buffer size. Ratios are non-integral rational numbers. Bigfloats are +arbitrary-precision floating point numbers, with precision specified at +runtime. +@item symbol +An object that contains Lisp objects and is referred to by name; +symbols are used to implement variables and named functions +and to provide the equivalent of preprocessor constants in C. +@item string +Self-explanatory; behaves much like a vector of chars +but has a different read syntax and is stored and manipulated +more compactly. +@item bit-vector +A vector of bits; similar to a string in spirit. +@item vector +A one-dimensional array of Lisp objects providing constant-time access +to any of the objects; access to an arbitrary object in a vector is +faster than for lists, but the operations that can be done on a vector +are more limited. +@item compiled-function +An object containing compiled Lisp code, known as @dfn{byte code}. +@item subr +A Lisp primitive, i.e. a Lisp-callable function implemented in C. +@item cons +A simple container for two Lisp objects, used to implement lists and +most other data structures in Lisp. +@end table +Objects which are not conses are called atoms. +@cindex closure +Note that there is no basic ``function'' type, as in more powerful +versions of Lisp (where it's called a @dfn{closure}). XEmacs Lisp does +not provide the closure semantics implemented by Common Lisp and Scheme. +The guts of a function in XEmacs Lisp are represented in one of four +ways: a symbol specifying another function (when one function is an +alias for another), a list (whose first element must be the symbol +@code{lambda}) containing the function's source code, a +compiled-function object, or a subr object. (In other words, given a +symbol specifying the name of a function, calling @code{symbol-function} +to retrieve the contents of the symbol's function cell will return one +of these types of objects.) -@example -minibuf.c -@end example +XEmacs Lisp also contains numerous specialized objects used to implement +the editor: -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 @file{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). +@table @code +@item buffer +Stores text like a string, but is optimized for insertion and deletion +and has certain other properties that can be set. +@item frame +An object with various properties whose displayable representation is a +@dfn{window} in window-system parlance. +@item window +A section of a frame that displays the contents of a buffer; +often called a @dfn{pane} in window-system parlance. +@item window-configuration +An object that represents a saved configuration of windows in a frame. +@item device +An object representing a screen on which frames can be displayed; +equivalent to a @dfn{display} in the X Window System and a @dfn{TTY} in +character mode. +@item face +An object specifying the appearance of text or graphics; it has +properties such as font, foreground color, and background color. +@item marker +An object that refers to a particular position in a buffer and moves +around as text is inserted and deleted to stay in the same relative +position to the text around it. +@item extent +Similar to a marker but covers a range of text in a buffer; can also +specify properties of the text, such as a face in which the text is to +be displayed, whether the text is invisible or unmodifiable, etc. +@item event +Generated by calling @code{next-event} and contains information +describing a particular event happening in the system, such as the user +pressing a key or a process terminating. +@item keymap +An object that maps from events (described using lists, vectors, and +symbols rather than with an event object because the mapping is for +classes of events, rather than individual events) to functions to +execute or other events to recursively look up; the functions are +described by name, using a symbol, or using lists to specify the +function's code. +@item glyph +An object that describes the appearance of an image (e.g. pixmap) on +the screen; glyphs can be attached to the beginning or end of extents +and in some future version of XEmacs will be able to be inserted +directly into a buffer. +@item process +An object that describes a connection to an externally-running process. +@end table + There are some other, less-commonly-encountered general objects: +@table @code +@item hash-table +An object that maps from an arbitrary Lisp object to another arbitrary +Lisp object, using hashing for fast lookup. +@item obarray +A limited form of hash-table that maps from strings to symbols; obarrays +are used to look up a symbol given its name and are not actually their +own object type but are kludgily represented using vectors with hidden +fields (this representation derives from GNU Emacs). +@item specifier +A complex object used to specify the value of a display property; a +default value is given and different values can be specified for +particular frames, buffers, windows, devices, or classes of device. +@item char-table +An object that maps from chars or classes of chars to arbitrary Lisp +objects; internally char tables use a complex nested-vector +representation that is optimized to the way characters are represented +as integers. +@item range-table +An object that maps from ranges of integers to arbitrary Lisp objects. +@end table -@node Modules for the Basic Displayable Lisp Objects -@section Modules for the Basic Displayable Lisp Objects -@cindex modules for the basic displayable Lisp objects -@cindex displayable Lisp objects, modules for the basic -@cindex Lisp objects, modules for the basic displayable -@cindex objects, modules for the basic displayable Lisp + And some strange special-purpose objects: -@example -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 -@end example +@table @code +@item charset +@itemx coding-system +Objects used when MULE, or multi-lingual/Asian-language, support is +enabled. +@item color-instance +@itemx font-instance +@itemx image-instance +An object that encapsulates a window-system resource; instances are +mostly used internally but are exposed on the Lisp level for cleanness +of the specifier model and because it's occasionally useful for Lisp +program to create or query the properties of instances. +@item subwindow +An object that encapsulate a @dfn{subwindow} resource, i.e. a +window-system child window that is drawn into by an external process; +this object should be integrated into the glyph system but isn't yet, +and may change form when this is done. +@item tooltalk-message +@itemx tooltalk-pattern +Objects that represent resources used in the ToolTalk interprocess +communication protocol. +@item toolbar-button +An object used in conjunction with the toolbar. +@end table -These modules implement the @dfn{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. + And objects that are only used internally: -Consoles are the top of a lisp object inclusion hierarchy. Consoles -contain devices, which contain frames, which contain windows. +@table @code +@item opaque +A generic object for encapsulating arbitrary memory; this allows you the +generality of @code{malloc()} and the convenience of the Lisp object +system. +@item lstream +A buffering I/O stream, used to provide a unified interface to anything +that can accept output or provide input, such as a file descriptor, a +stdio stream, a chunk of memory, a Lisp buffer, a Lisp string, etc.; +it's a Lisp object to make its memory management more convenient. +@item char-table-entry +Subsidiary objects in the internal char-table representation. +@item extent-auxiliary +@itemx menubar-data +@itemx toolbar-data +Various special-purpose objects that are basically just used to +encapsulate memory for particular subsystems, similar to the more +general ``opaque'' object. +@item symbol-value-forward +@itemx symbol-value-buffer-local +@itemx symbol-value-varalias +@itemx symbol-value-lisp-magic +Special internal-only objects that are placed in the value cell of a +symbol to indicate that there is something special with this variable -- +e.g. it has no value, it mirrors another variable, or it mirrors some C +variable; there is really only one kind of object, called a +@dfn{symbol-value-magic}, but it is sort-of halfway kludged into +semi-different object types. +@end table + +@cindex permanent objects +@cindex temporary objects + Some types of objects are @dfn{permanent}, meaning that once created, +they do not disappear until explicitly destroyed, using a function such +as @code{delete-buffer}, @code{delete-window}, @code{delete-frame}, etc. +Others will disappear once they are not longer used, through the garbage +collection mechanism. Buffers, frames, windows, devices, and processes +are among the objects that are permanent. Note that some objects can go +both ways: Faces can be created either way; extents are normally +permanent, but detached extents (extents not referring to any text, as +happens to some extents when the text they are referring to is deleted) +are temporary. Note that some permanent objects, such as faces and +coding systems, cannot be deleted. Note also that windows are unique in +that they can be @emph{undeleted} after having previously been +deleted. (This happens as a result of restoring a window configuration.) +@cindex read syntax + Many types of objects have a @dfn{read syntax}, i.e. a way of +specifying an object of that type in Lisp code. When you load a Lisp +file, or type in code to be evaluated, what really happens is that the +function @code{read} is called, which reads some text and creates an object +based on the syntax of that text; then @code{eval} is called, which +possibly does something special; then this loop repeats until there's +no more text to read. (@code{eval} only actually does something special +with symbols, which causes the symbol's value to be returned, +similar to referencing a variable; and with conses [i.e. lists], +which cause a function invocation. All other values are returned +unchanged.) + The read syntax @example -device-msw.c -device-tty.c -device-x.c -device.c -device.h +17297 @end example -These modules implement the @dfn{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. - - +converts to an integer whose value is 17297. @example -frame-msw.c -frame-tty.c -frame-x.c -frame.c -frame.h +355/113 @end example -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 @file{frame-*} files implement the @dfn{frame} Lisp object type and -provide the generic and device-type-specific operations on frames -(e.g. raising, lowering, resizing, moving, etc.). - - +converts to a ratio commonly used to approximate @emph{pi} when ratios +are configured, and otherwise to a symbol whose name is ``355/113'' (for +backward compatibility). @example -window.c -window.h +1.983e-4 @end example -@cindex window (in Emacs) -@cindex pane -Each frame consists of one or more non-overlapping @dfn{windows} (better -known as @dfn{panes} in standard window-system terminology) in which a -buffer's text can be displayed. Windows can also have scrollbars -displayed around their edges. - -@file{window.c} and @file{window.h} implement the @dfn{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. - - - -@node Modules for other Display-Related Lisp Objects -@section Modules for other Display-Related Lisp Objects -@cindex modules for other display-related Lisp objects -@cindex display-related Lisp objects, modules for other -@cindex Lisp objects, modules for other display-related +converts to a float whose value is 1.983e-4, or .0001983. @example -faces.c -faces.h +?b @end example - +converts to a char that represents the lowercase letter b. @example -bitmaps.h -glyphs-eimage.c -glyphs-msw.c -glyphs-msw.h -glyphs-widget.c -glyphs-x.c -glyphs-x.h -glyphs.c -glyphs.h +?^[$(B#&^[(B @end example - +(where @samp{^[} actually is an @samp{ESC} character) converts to a +particular Kanji character when using an ISO2022-based coding system for +input. (To decode this goo: @samp{ESC} begins an escape sequence; +@samp{ESC $ (} is a class of escape sequences meaning ``switch to a +94x94 character set''; @samp{ESC $ ( B} means ``switch to Japanese +Kanji''; @samp{#} and @samp{&} collectively index into a 94-by-94 array +of characters [subtract 33 from the ASCII value of each character to get +the corresponding index]; @samp{ESC (} is a class of escape sequences +meaning ``switch to a 94 character set''; @samp{ESC (B} means ``switch +to US ASCII''. It is a coincidence that the letter @samp{B} is used to +denote both Japanese Kanji and US ASCII. If the first @samp{B} were +replaced with an @samp{A}, you'd be requesting a Chinese Hanzi character +from the GB2312 character set.) @example -objects-msw.c -objects-msw.h -objects-tty.c -objects-tty.h -objects-x.c -objects-x.h -objects.c -objects.h +"foobar" @end example - +converts to a string. @example -menubar-msw.c -menubar-msw.h -menubar-x.c -menubar.c -menubar.h +foobar @end example - - -@example -scrollbar-msw.c -scrollbar-msw.h -scrollbar-x.c -scrollbar-x.h -scrollbar.c -scrollbar.h -@end example - - +converts to a symbol whose name is @code{"foobar"}. This is done by +looking up the string equivalent in the global variable +@code{obarray}, whose contents should be an obarray. If no symbol +is found, a new symbol with the name @code{"foobar"} is automatically +created and added to @code{obarray}; this process is called +@dfn{interning} the symbol. +@cindex interning @example -toolbar-msw.c -toolbar-x.c -toolbar.c -toolbar.h +(foo . bar) @end example - +converts to a cons cell containing the symbols @code{foo} and @code{bar}. @example -font-lock.c +(1 a 2.5) @end example -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. - - +converts to a three-element list containing the specified objects +(note that a list is actually a set of nested conses; see the +XEmacs Lisp Reference). @example -dgif_lib.c -gif_err.c -gif_lib.h -gifalloc.c +[1 a 2.5] @end example -These modules decode GIF-format image files, for use with glyphs. -These files were removed due to Unisys patent infringement concerns. - - - -@node Modules for the Redisplay Mechanism -@section Modules for the Redisplay Mechanism -@cindex modules for the redisplay mechanism -@cindex redisplay mechanism, modules for the +converts to a three-element vector containing the specified objects. @example -redisplay-output.c -redisplay-msw.c -redisplay-tty.c -redisplay-x.c -redisplay.c -redisplay.h +#[... ... ... ...] @end example -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. - -@file{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. - -@file{redisplay-output.c} goes through the redisplay structures and converts -them into calls to device-specific methods to actually output the screen -changes. - -@file{redisplay-x.c} and @file{redisplay-tty.c} are two implementations -of these redisplay output methods, for X frames and TTY frames, -respectively. - - +converts to a compiled-function object (the actual contents are not +shown since they are not relevant here; look at a file that ends with +@file{.elc} for examples). @example -indent.c +#*01110110 @end example -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. - - +converts to a bit-vector. @example -termcap.c -terminfo.c -tparam.c +#s(hash-table ... ...) @end example -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. - - +converts to a hash table (the actual contents are not shown). @example -cm.c -cm.h +#s(range-table ... ...) @end example -These files provide some miscellaneous TTY-output functions and should -probably be merged into @file{redisplay-tty.c}. - - - -@node Modules for Interfacing with the File System -@section Modules for Interfacing with the File System -@cindex modules for interfacing with the file system -@cindex interfacing with the file system, modules for -@cindex file system, modules for interfacing with the +converts to a range table (the actual contents are not shown). @example -lstream.c -lstream.h +#s(char-table ... ...) @end example -These modules implement the @dfn{stream} Lisp object type. This is an -internal-only Lisp object that implements a generic buffering stream. -The idea is to provide a uniform interface onto all sources and sinks of -data, including file descriptors, stdio streams, chunks of memory, Lisp -buffers, Lisp strings, etc. That way, I/O functions can be written to -the stream interface and can transparently handle all possible sources -and sinks. (For example, the @code{read} function can read data from a -file, a string, a buffer, or even a function that is called repeatedly -to return data, without worrying about where the data is coming from or -what-size chunks it is returned in.) - -@cindex lstream -Note that in the C code, streams are called @dfn{lstreams} (for ``Lisp -streams'') to distinguish them from other kinds of streams, e.g. stdio -streams and C++ I/O streams. - -Similar to other subsystems in XEmacs, lstreams are separated into -generic functions and a set of methods for the different types of -lstreams. @file{lstream.c} provides implementations of many different -types of streams; others are provided, e.g., in @file{file-coding.c}. - +converts to a char table (the actual contents are not shown). +Note that the @code{#s()} syntax is the general syntax for structures, +which are not really implemented in XEmacs Lisp but should be. -@example -fileio.c -@end example +When an object is printed out (using @code{print} or a related +function), the read syntax is used, so that the same object can be read +in again. -This implements the basic primitives for interfacing with the file -system. This includes primitives for reading files into buffers, -writing buffers into files, checking for the presence or accessibility -of files, canonicalizing file names, etc. Note that these primitives -are usually not invoked directly by the user: There is a great deal of -higher-level Lisp code that implements the user commands such as -@code{find-file} and @code{save-buffer}. This is similar to the -distinction between the lower-level primitives in @file{editfns.c} and -the higher-level user commands in @file{commands.c} and -@file{simple.el}. +The other objects do not have read syntaxes, usually because it does not +really make sense to create them in this fashion (i.e. processes, where +it doesn't make sense to have a subprocess created as a side effect of +reading some Lisp code), or because they can't be created at all +(e.g. subrs). Permanent objects, as a rule, do not have a read syntax; +nor do most complex objects, which contain too much state to be easily +initialized through a read syntax. +@node How Lisp Objects Are Represented in C, Allocation of Objects in XEmacs Lisp, The XEmacs Object System (Abstractly Speaking), Top +@chapter How Lisp Objects Are Represented in C +@cindex Lisp objects are represented in C, how +@cindex objects are represented in C, how Lisp +@cindex represented in C, how Lisp objects are +Lisp objects are represented in C using a 32-bit or 64-bit machine word +(depending on the processor; i.e. DEC Alphas use 64-bit Lisp objects and +most other processors use 32-bit Lisp objects). The representation +stuffs a pointer together with a tag, as follows: @example -filelock.c -@end example - -This file provides functions for detecting clashes between different -processes (e.g. XEmacs and some external process, or two different -XEmacs processes) modifying the same file. (XEmacs can optionally use -the @file{lock/} subdirectory to provide a form of ``locking'' between -different XEmacs processes.) This module is also used by the low-level -functions in @file{insdel.c} to ensure that, if the first modification -is being made to a buffer whose corresponding file has been externally -modified, the user is made aware of this so that the buffer can be -synched up with the external changes if necessary. - + [ 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 ] + [ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ] -@example -filemode.c + <---------------------------------------------------------> <-> + a pointer to a structure, or an integer tag @end example -This file provides some miscellaneous functions that construct a -@samp{rwxr-xr-x}-type permissions string (as might appear in an -@file{ls}-style directory listing) given the information returned by the -@code{stat()} system call. - - - -@example -dired.c -ndir.h -@end example +A tag of 00 is used for all pointer object types, a tag of 10 is used +for characters, and the other two tags 01 and 11 are joined together to +form the integer object type. This representation gives us 31 bit +integers and 30 bit characters, while pointers are represented directly +without any bit masking or shifting. This representation, though, +assumes that pointers to structs are always aligned to multiples of 4, +so the lower 2 bits are always zero. -These files implement the XEmacs interface to directory searching. This -includes a number of primitives for determining the files in a directory -and for doing filename completion. (Remember that generic completion is -handled by a different mechanism, in @file{minibuf.c}.) +Lisp objects use the typedef @code{Lisp_Object}, but the actual C type +used for the Lisp object can vary. It can be either a simple type +(@code{long} on the DEC Alpha, @code{int} on other machines) or a +structure whose fields are bit fields that line up properly (actually, a +union of structures is used). Generally the simple integral type is +preferable because it ensures that the compiler will actually use a +machine word to represent the object (some compilers will use more +general and less efficient code for unions and structs even if they can +fit in a machine word). The union type, however, has the advantage of +stricter type checking. If you accidentally pass an integer where a Lisp +object is desired, you get a compile error. The choice of which type +to use is determined by the preprocessor constant @code{USE_UNION_TYPE} +which is defined via the @code{--use-union-type} option to +@code{configure}. -@file{ndir.h} is a header file used for the directory-searching -emulation functions provided in @file{sysdep.c} (see section J below), -for systems that don't provide any directory-searching functions. (On -those systems, directories can be read directly as files, and parsed.) +Various macros are used to convert between Lisp_Objects and the +corresponding C type. Macros of the form @code{XINT()}, @code{XCHAR()}, +@code{XSTRING()}, @code{XSYMBOL()}, do any required bit shifting and/or +masking and cast it to the appropriate type. @code{XINT()} needs to be +a bit tricky so that negative numbers are properly sign-extended. Since +integers are stored left-shifted, if the right-shift operator does an +arithmetic shift (i.e. it leaves the most-significant bit as-is rather +than shifting in a zero, so that it mimics a divide-by-two even for +negative numbers) the shift to remove the tag bit is enough. This is +the case on all the systems we support. +Note that when @code{ERROR_CHECK_TYPECHECK} is defined, the converter +macros become more complicated---they check the tag bits and/or the +type field in the first four bytes of a record type to ensure that the +object is really of the correct type. This is great for catching places +where an incorrect type is being dereferenced---this typically results +in a pointer being dereferenced as the wrong type of structure, with +unpredictable (and sometimes not easily traceable) results. +There are similar @code{XSET@var{TYPE}()} macros that construct a Lisp +object. These macros are of the form @code{XSET@var{TYPE} +(@var{lvalue}, @var{result})}, i.e. they have to be a statement rather +than just used in an expression. The reason for this is that standard C +doesn't let you ``construct'' a structure (but GCC does). Granted, this +sometimes isn't too convenient; for the case of integers, at least, you +can use the function @code{make_int()}, which constructs and +@emph{returns} an integer Lisp object. Note that the +@code{XSET@var{TYPE}()} macros are also affected by +@code{ERROR_CHECK_TYPECHECK} and make sure that the structure is of the +right type in the case of record types, where the type is contained in +the structure. -@example -realpath.c -@end example +The C programmer is responsible for @strong{guaranteeing} that a +Lisp_Object is the correct type before using the @code{X@var{TYPE}} +macros. This is especially important in the case of lists. Use +@code{XCAR} and @code{XCDR} if a Lisp_Object is certainly a cons cell, +else use @code{Fcar()} and @code{Fcdr()}. Trust other C code, but not +Lisp code. On the other hand, if XEmacs has an internal logic error, +it's better to crash immediately, so sprinkle @code{assert()}s and +``unreachable'' @code{abort()}s liberally about the source code. Where +performance is an issue, use @code{type_checking_assert}, +@code{bufpos_checking_assert}, and @code{gc_checking_assert}, which do +nothing unless the corresponding configure error checking flag was +specified. -This file provides an implementation of the @code{realpath()} function -for expanding symbolic links, on systems that don't implement it or have -a broken implementation. +@node Allocation of Objects in XEmacs Lisp, The Lisp Reader and Compiler, How Lisp Objects Are Represented in C, Top +@chapter Allocation of Objects in XEmacs Lisp +@cindex allocation of objects in XEmacs Lisp +@cindex objects in XEmacs Lisp, allocation of +@cindex Lisp objects, allocation of in XEmacs +@menu +* Introduction to Allocation:: +* Garbage Collection:: +* GCPROing:: +* Garbage Collection - Step by Step:: +* Integers and Characters:: +* Allocation from Frob Blocks:: +* lrecords:: +* Low-level allocation:: +* Cons:: +* Vector:: +* Bit Vector:: +* Symbol:: +* Marker:: +* String:: +* Compiled Function:: +@end menu +@node Introduction to Allocation, Garbage Collection, Allocation of Objects in XEmacs Lisp, Allocation of Objects in XEmacs Lisp +@section Introduction to Allocation +@cindex allocation, introduction to -@node Modules for Other Aspects of the Lisp Interpreter and Object System -@section Modules for Other Aspects of the Lisp Interpreter and Object System -@cindex modules for other aspects of the Lisp interpreter and object system -@cindex Lisp interpreter and object system, modules for other aspects of the -@cindex interpreter and object system, modules for other aspects of the Lisp -@cindex object system, modules for other aspects of the Lisp interpreter and - -@example -elhash.c -elhash.h -hash.c -hash.h -@end example - -These files provide two implementations of hash tables. Files -@file{hash.c} and @file{hash.h} provide a generic C implementation of -hash tables which can stand independently of XEmacs. Files -@file{elhash.c} and @file{elhash.h} provide a separate implementation of -hash tables that can store only Lisp objects, and knows about Lispy -things like garbage collection, and implement the @dfn{hash-table} Lisp -object type. + Emacs Lisp, like all Lisps, has garbage collection. This means that +the programmer never has to explicitly free (destroy) an object; it +happens automatically when the object becomes inaccessible. Most +experts agree that garbage collection is a necessity in a modern, +high-level language. Its omission from C stems from the fact that C was +originally designed to be a nice abstract layer on top of assembly +language, for writing kernels and basic system utilities rather than +large applications. + Lisp objects can be created by any of a number of Lisp primitives. +Most object types have one or a small number of basic primitives +for creating objects. For conses, the basic primitive is @code{cons}; +for vectors, the primitives are @code{make-vector} and @code{vector}; for +symbols, the primitives are @code{make-symbol} and @code{intern}; etc. +Some Lisp objects, especially those that are primarily used internally, +have no corresponding Lisp primitives. Every Lisp object, though, +has at least one C primitive for creating it. -@example -specifier.c -specifier.h -@end example + Recall from section (VII) that a Lisp object, as stored in a 32-bit or +64-bit word, has a few tag bits, and a ``value'' that occupies the +remainder of the bits. We can separate the different Lisp object types +into three broad categories: -This module implements the @dfn{specifier} Lisp object type. This is -primarily used for displayable properties, and allows for values that -are specific to a particular buffer, window, frame, device, or device -class, as well as a default value existing. This is used, for example, -to control the height of the horizontal scrollbar or the appearance of -the @code{default}, @code{bold}, or other faces. The specifier object -consists of a number of specifications, each of which maps from a -buffer, window, etc. to a value. The function @code{specifier-instance} -looks up a value given a window (from which a buffer, frame, and device -can be derived). +@itemize @bullet +@item +(a) Those for whom the value directly represents the contents of the +Lisp object. Only two types are in this category: integers and +characters. No special allocation or garbage collection is necessary +for such objects. Lisp objects of these types do not need to be +@code{GCPRO}ed. +@end itemize + In the remaining two categories, the type is stored in the object +itself. The tag for all such objects is the generic @dfn{lrecord} +(Lisp_Type_Record) tag. The first bytes of the object's structure are an +integer (actually a char) characterising the object's type and some +flags, in particular the mark bit used for garbage collection. A +structure describing the type is accessible thru the +lrecord_implementation_table indexed with said integer. This structure +includes the method pointers and a pointer to a string naming the type. -@example -chartab.c -chartab.h -casetab.c -@end example +@itemize @bullet +@item +(b) Those lrecords that are allocated in frob blocks (see above). This +includes the objects that are most common and relatively small, and +includes conses, strings, subrs, floats, compiled functions, symbols, +extents, events, and markers. With the cleanup of frob blocks done in +19.12, it's not terribly hard to add more objects to this category, but +it's a bit trickier than adding an object type to type (c) (esp. if the +object needs a finalization method), and is not likely to save much +space unless the object is small and there are many of them. (In fact, +if there are very few of them, it might actually waste space.) +@item +(c) Those lrecords that are individually @code{malloc()}ed. These are +called @dfn{lcrecords}. All other types are in this category. Adding a +new type to this category is comparatively easy, and all types added +since 19.8 (when the current allocation scheme was devised, by Richard +Mlynarik), with the exception of the character type, have been in this +category. +@end itemize -@file{chartab.c} and @file{chartab.h} implement the @dfn{char table} -Lisp object type, which maps from characters or certain sorts of -character ranges to Lisp objects. The implementation of this object -type is optimized for the internal representation of characters. Char -tables come in different types, which affect the allowed object types to -which a character can be mapped and also dictate certain other -properties of the char table. + Note that bit vectors are a bit of a special case. They are +simple lrecords as in category (b), but are individually @code{malloc()}ed +like vectors. You can basically view them as exactly like vectors +except that their type is stored in lrecord fashion rather than +in directly-tagged fashion. -@cindex case table -@file{casetab.c} implements one sort of char table, the @dfn{case -table}, which maps characters to other characters of possibly different -case. These are used by XEmacs to implement case-changing primitives -and to do case-insensitive searching. +@node Garbage Collection, GCPROing, Introduction to Allocation, Allocation of Objects in XEmacs Lisp +@section Garbage Collection +@cindex garbage collection +@cindex mark and sweep + Garbage collection is simple in theory but tricky to implement. +Emacs Lisp uses the oldest garbage collection method, called +@dfn{mark and sweep}. Garbage collection begins by starting with +all accessible locations (i.e. all variables and other slots where +Lisp objects might occur) and recursively traversing all objects +accessible from those slots, marking each one that is found. +We then go through all of memory and free each object that is +not marked, and unmarking each object that is marked. Note +that ``all of memory'' means all currently allocated objects. +Traversing all these objects means traversing all frob blocks, +all vectors (which are chained in one big list), and all +lcrecords (which are likewise chained). -@example -syntax.c -syntax.h -@end example + Garbage collection can be invoked explicitly by calling +@code{garbage-collect} but is also called automatically by @code{eval}, +once a certain amount of memory has been allocated since the last +garbage collection (according to @code{gc-cons-threshold}). -@cindex scanner -This module implements @dfn{syntax tables}, another sort of char table -that maps characters into syntax classes that define the syntax of these -characters (e.g. a parenthesis belongs to a class of @samp{open} -characters that have corresponding @samp{close} characters and can be -nested). This module also implements the Lisp @dfn{scanner}, a set of -primitives for scanning over text based on syntax tables. This is used, -for example, to find the matching parenthesis in a command such as -@code{forward-sexp}, and by @file{font-lock.c} to locate quoted strings, -comments, etc. -@c #### Break this out into a separate node somewhere! -Syntax codes are implemented as bitfields in an int. Bits 0-6 contain -the syntax code itself, bit 7 is a special prefix flag used for Lisp, -and bits 16-23 contain comment syntax flags. From the Lisp programmer's -point of view, there are 11 flags: 2 styles X 2 characters X @{start, -end@} flags for two-character comment delimiters, 2 style flags for -one-character comment delimiters, and the prefix flag. +@node GCPROing, Garbage Collection - Step by Step, Garbage Collection, Allocation of Objects in XEmacs Lisp +@section @code{GCPRO}ing +@cindex @code{GCPRO}ing +@cindex garbage collection protection +@cindex protection, garbage collection -Internally, however, the characters used in multi-character delimiters -will have non-comment-character syntax classes (@emph{e.g.}, the -@samp{/} in C's @samp{/*} comment-start delimiter has ``punctuation'' -(here meaning ``operator-like'') class in C modes). Thus in a mixed -comment style, such as C++'s @samp{//} to end of line, is represented by -giving @samp{/} the ``punctuation'' class and the ``style b first -character of start sequence'' and ``style b second character of start -sequence'' flags. The fact that class is @emph{not} punctuation allows -the syntax scanner to recognize that this is a multi-character -delimiter. The @samp{newline} character is given (single-character) -``comment-end'' @emph{class} and the ``style b first character of end -sequence'' @emph{flag}. The ``comment-end'' class allows the scanner to -determine that no second character is needed to terminate the comment. +@code{GCPRO}ing is one of the ugliest and trickiest parts of Emacs +internals. The basic idea is that whenever garbage collection +occurs, all in-use objects must be reachable somehow or +other from one of the roots of accessibility. The roots +of accessibility are: -There used to be a syntax class @samp{Sextword}. A character of -@samp{Sextword} class is a word-constituent but a word boundary may -exist between two such characters. Ken'ichi HANDA <handa@@etl.go.jp> -explains the purpose of the Sextword syntax category: +@enumerate +@item +All objects that have been @code{staticpro()}d or +@code{staticpro_nodump()}ed. This is used for any global C variables +that hold Lisp objects. A call to @code{staticpro()} happens implicitly +as a result of any symbols declared with @code{defsymbol()} and any +variables declared with @code{DEFVAR_FOO()}. You need to explicitly +call @code{staticpro()} (in the @code{vars_of_foo()} method of a module) +for other global C variables holding Lisp objects. (This typically +includes internal lists and such things.). Use +@code{staticpro_nodump()} only in the rare cases when you do not want +the pointed variable to be saved at dump time but rather recompute it at +startup. -@quotation -Japanese words are not separated by spaces, which makes finding word -boundaries very difficult. Theoretically it's impossible without -using natural language processing techniques. But, by defining -pseudo-words as below (much simplified for letting you understand it -easily) for Japanese, we can have a convenient forward-word function -for Japanese. +Note that @code{obarray} is one of the @code{staticpro()}d things. +Therefore, all functions and variables get marked through this. +@item +Any shadowed bindings that are sitting on the @code{specpdl} stack. +@item +Any objects sitting in currently active (Lisp) stack frames, +catches, and condition cases. +@item +A couple of special-case places where active objects are +located. +@item +Anything currently marked with @code{GCPRO}. +@end enumerate -@display -A Japanese word is a sequence of characters that consists of -zero or more Kanji characters followed by zero or more -Hiragana characters. -@end display + Marking with @code{GCPRO} is necessary because some C functions (quite +a lot, in fact), allocate objects during their operation. Quite +frequently, there will be no other pointer to the object while the +function is running, and if a garbage collection occurs and the object +needs to be referenced again, bad things will happen. The solution is +to mark those references with @code{GCPRO}. Note that it is a +@emph{reference} that is marked with @code{GCPRO}, not an object. If +you declare a @code{Lisp_Object} variable, assign to it, @code{GCPRO} +it, and then assign to it again, the first object assigned @emph{is not} +protected, while the second object @emph{is} protected. Unfortunately +@code{GCPRO}ing is easy to forget, and there is basically no way around +this problem. Here are some rules, though: -Then, the problem is that now we can't say that a sequence of -word-constituents makes up a word. For instance, both Hiragana "A" -and Kanji "KAN" are word-constituents but the sequence of these two -letters can't be a single word. +@enumerate +@item +A garbage collection can occur whenever anything calls @code{Feval}, or +whenever a @code{QUIT} can occur where execution can continue past +this. (Remember, this is almost anywhere.) Note that @code{Fsignal} can +GC, and it can return (even though it normally doesn't). This means +that you must @code{GCPRO} before calling most of the error functions, +including the @samp{CONCHECK} family of macros, if references occur +after the call. -So, we introduced Sextword for Japanese letters. -@end quotation +@item +You @emph{must} @code{UNGCPRO} anything that's @code{GCPRO}ed, and you +@emph{must not} @code{UNGCPRO} if you haven't @code{GCPRO}ed. Getting +either of these wrong will lead to crashes, often in completely random +places unrelated to where the problem lies. There are some functions +(@code{Fsignal} is the canonical example) which may or may not return. +In these cases, the function is responsible for cleaning up the +@code{GCPRO}s if it doesn't return, so you should treat it as an +ordinary function. -There seems to have been some controversy about this category, as it has -been removed, readded, and removed again. Currently neither GNU Emacs -(21.3.99) nor XEmacs (21.5.17) seems to use it. +@item +For every @code{GCPRO@var{n}}, there have to be declarations of +@code{struct gcpro gcpro1, gcpro2, ..., gcpro@var{n}}. +@item +The way this actually works is that all currently active @code{GCPRO}s +are chained through the @code{struct gcpro} local variables, with the +variable @samp{gcprolist} pointing to the head of the list and the nth +local @code{gcpro} variable pointing to the first @code{gcpro} variable +in the next enclosing stack frame. Each @code{GCPRO}ed thing is an +lvalue, and the @code{struct gcpro} local variable contains a pointer to +this lvalue. This is why things will mess up badly if you don't pair up +the @code{GCPRO}s and @code{UNGCPRO}s---you will end up with +@code{gcprolist}s containing pointers to @code{struct gcpro}s or local +@code{Lisp_Object} variables in no-longer-active stack frames. -@example -casefiddle.c +@item +It is actually possible for a single @code{struct gcpro} to +protect a contiguous array of any number of values, rather than +just a single lvalue. To effect this, call @code{GCPRO@var{n}} as usual on +the first object in the array and then set @code{gcpro@var{n}.nvars}. + +@item +@strong{Strings are relocated.} What this means in practice is that the +pointer obtained using @code{XSTRING_DATA()} is liable to change at any +time, and you should never keep it around past any function call, or +pass it as an argument to any function that might cause a garbage +collection. This is why a number of functions accept either a +``non-relocatable'' @code{char *} pointer or a relocatable Lisp string, +and only access the Lisp string's data at the very last minute. In some +cases, you may end up having to @code{alloca()} some space and copy the +string's data into it. + +@item +By convention, if you have to nest @code{GCPRO}'s, use @code{NGCPRO@var{n}} +(along with @code{struct gcpro ngcpro1, ngcpro2}, etc.), @code{NNGCPRO@var{n}}, +etc. This avoids compiler warnings about shadowed locals. + +@item +It is @emph{always} better to err on the side of extra @code{GCPRO}s +rather than too few. The extra cycles spent on this are +almost never going to make a whit of difference in the +speed of anything. + +@item +The general rule to follow is that caller, not callee, @code{GCPRO}s. +That is, you should not have to explicitly @code{GCPRO} any Lisp objects +that are passed in as parameters. + +One exception from this rule is if you ever plan to change the parameter +value, and store a new object in it. In that case, you @emph{must} +@code{GCPRO} the parameter, because otherwise the new object will not be +protected. + +So, if you create any Lisp objects (remember, this happens in all sorts +of circumstances, e.g. with @code{Fcons()}, etc.), you are responsible +for @code{GCPRO}ing them, unless you are @emph{absolutely sure} that +there's no possibility that a garbage-collection can occur while you +need to use the object. Even then, consider @code{GCPRO}ing. + +@item +If you have the @emph{least smidgeon of doubt} about whether +you need to @code{GCPRO}, you should @code{GCPRO}. + +@item +Beware of @code{GCPRO}ing something that is uninitialized. If you have +any shade of doubt about this, initialize all your variables to @code{Qnil}. + +@item +Be careful of traps, like calling @code{Fcons()} in the argument to +another function. By the ``caller protects'' law, you should be +@code{GCPRO}ing the newly-created cons, but you aren't. A certain +number of functions that are commonly called on freshly created stuff +(e.g. @code{nconc2()}, @code{Fsignal()}), break the ``caller protects'' +law and go ahead and @code{GCPRO} their arguments so as to simplify +things, but make sure and check if it's OK whenever doing something like +this. + +@item +Once again, remember to @code{GCPRO}! Bugs resulting from insufficient +@code{GCPRO}ing are intermittent and extremely difficult to track down, +often showing up in crashes inside of @code{garbage-collect} or in +weirdly corrupted objects or even in incorrect values in a totally +different section of code. +@end enumerate + +If you don't understand whether to @code{GCPRO} in a particular +instance, ask on the mailing lists. A general hint is that @code{prog1} +is the canonical example. + +@cindex garbage collection, conservative +@cindex conservative garbage collection + Given the extremely error-prone nature of the @code{GCPRO} scheme, and +the difficulties in tracking down, it should be considered a deficiency +in the XEmacs code. A solution to this problem would involve +implementing so-called @dfn{conservative} garbage collection for the C +stack. That involves looking through all of stack memory and treating +anything that looks like a reference to an object as a reference. This +will result in a few objects not getting collected when they should, but +it obviates the need for @code{GCPRO}ing, and allows garbage collection +to happen at any point at all, such as during object allocation. + +@node Garbage Collection - Step by Step, Integers and Characters, GCPROing, Allocation of Objects in XEmacs Lisp +@section Garbage Collection - Step by Step +@cindex garbage collection - step by step + +@menu +* Invocation:: +* garbage_collect_1:: +* mark_object:: +* gc_sweep:: +* sweep_lcrecords_1:: +* compact_string_chars:: +* sweep_strings:: +* sweep_bit_vectors_1:: +@end menu + +@node Invocation, garbage_collect_1, Garbage Collection - Step by Step, Garbage Collection - Step by Step +@subsection Invocation +@cindex garbage collection, invocation + +The first thing that anyone should know about garbage collection is: +when and how the garbage collector is invoked. One might think that this +could happen every time new memory is allocated, e.g. new objects are +created, but this is @emph{not} the case. Instead, we have the following +situation: + +The entry point of any process of garbage collection is an invocation +of the function @code{garbage_collect_1} in file @code{alloc.c}. The +invocation can occur @emph{explicitly} by calling the function +@code{Fgarbage_collect} (in addition this function provides information +about the freed memory), or can occur @emph{implicitly} in four different +situations: +@enumerate +@item +In function @code{main_1} in file @code{emacs.c}. This function is called +at each startup of xemacs. The garbage collection is invoked after all +initial creations are completed, but only if a special internal error +checking-constant @code{ERROR_CHECK_GC} is defined. +@item +In function @code{disksave_object_finalization} in file +@code{alloc.c}. The only purpose of this function is to clear the +objects from memory which need not be stored with xemacs when we dump out +an executable. This is only done by @code{Fdump_emacs} or by +@code{Fdump_emacs_data} respectively (both in @code{emacs.c}). The +actual clearing is accomplished by making these objects unreachable and +starting a garbage collection. The function is only used while building +xemacs. +@item +In function @code{Feval / eval} in file @code{eval.c}. Each time the +well known and often used function eval is called to evaluate a form, +one of the first things that could happen, is a potential call of +@code{garbage_collect_1}. There exist three global variables, +@code{consing_since_gc} (counts the created cons-cells since the last +garbage collection), @code{gc_cons_threshold} (a specified threshold +after which a garbage collection occurs) and @code{always_gc}. If +@code{always_gc} is set or if the threshold is exceeded, the garbage +collection will start. +@item +In function @code{Ffuncall / funcall} in file @code{eval.c}. This +function evaluates calls of elisp functions and works according to +@code{Feval}. +@end enumerate + +The upshot is that garbage collection can basically occur everywhere +@code{Feval}, respectively @code{Ffuncall}, is used - either directly or +through another function. Since calls to these two functions are hidden +in various other functions, many calls to @code{garbage_collect_1} are +not obviously foreseeable, and therefore unexpected. Instances where +they are used that are worth remembering are various elisp commands, as +for example @code{or}, @code{and}, @code{if}, @code{cond}, @code{while}, +@code{setq}, etc., miscellaneous @code{gui_item_...} functions, +everything related to @code{eval} (@code{Feval_buffer}, @code{call0}, +...) and inside @code{Fsignal}. The latter is used to handle signals, as +for example the ones raised by every @code{QUIT}-macro triggered after +pressing Ctrl-g. + +@node garbage_collect_1, mark_object, Invocation, Garbage Collection - Step by Step +@subsection @code{garbage_collect_1} +@cindex @code{garbage_collect_1} + +We can now describe exactly what happens after the invocation takes +place. +@enumerate +@item +There are several cases in which the garbage collector is left immediately: +when we are already garbage collecting (@code{gc_in_progress}), when +the garbage collection is somehow forbidden +(@code{gc_currently_forbidden}), when we are currently displaying something +(@code{in_display}) or when we are preparing for the armageddon of the +whole system (@code{preparing_for_armageddon}). +@item +Next the correct frame in which to put +all the output occurring during garbage collecting is determined. In +order to be able to restore the old display's state after displaying the +message, some data about the current cursor position has to be +saved. The variables @code{pre_gc_cursor} and @code{cursor_changed} take +care of that. +@item +The state of @code{gc_currently_forbidden} must be restored after +the garbage collection, no matter what happens during the process. We +accomplish this by @code{record_unwind_protect}ing the suitable function +@code{restore_gc_inhibit} together with the current value of +@code{gc_currently_forbidden}. +@item +If we are concurrently running an interactive xemacs session, the next step +is simply to show the garbage collector's cursor/message. +@item +The following steps are the intrinsic steps of the garbage collector, +therefore @code{gc_in_progress} is set. +@item +For debugging purposes, it is possible to copy the current C stack +frame. However, this seems to be a currently unused feature. +@item +Before actually starting to go over all live objects, references to +objects that are no longer used are pruned. We only have to do this for events +(@code{clear_event_resource}) and for specifiers +(@code{cleanup_specifiers}). +@item +Now the mark phase begins and marks all accessible elements. In order to +start from +all slots that serve as roots of accessibility, the function +@code{mark_object} is called for each root individually to go out from +there to mark all reachable objects. All roots that are traversed are +shown in their processed order: +@itemize @bullet +@item +all constant symbols and static variables that are registered via +@code{staticpro}@ in the dynarr @code{staticpros}. +@xref{Adding Global Lisp Variables}. +@item +all Lisp objects that are created in C functions and that must be +protected from freeing them. They are registered in the global +list @code{gcprolist}. +@xref{GCPROing}. +@item +all local variables (i.e. their name fields @code{symbol} and old +values @code{old_values}) that are bound during the evaluation by the Lisp +engine. They are stored in @code{specbinding} structs pushed on a stack +called @code{specpdl}. +@xref{Dynamic Binding; The specbinding Stack; Unwind-Protects}. +@item +all catch blocks that the Lisp engine encounters during the evaluation +cause the creation of structs @code{catchtag} inserted in the list +@code{catchlist}. Their tag (@code{tag}) and value (@code{val} fields +are freshly created objects and therefore have to be marked. +@xref{Catch and Throw}. +@item +every function application pushes new structs @code{backtrace} +on the call stack of the Lisp engine (@code{backtrace_list}). The unique +parts that have to be marked are the fields for each function +(@code{function}) and all their arguments (@code{args}). +@xref{Evaluation}. +@item +all objects that are used by the redisplay engine that must not be freed +are marked by a special function called @code{mark_redisplay} (in +@code{redisplay.c}). +@item +all objects created for profiling purposes are allocated by C functions +instead of using the lisp allocation mechanisms. In order to receive the +right ones during the sweep phase, they also have to be marked +manually. That is done by the function @code{mark_profiling_info} +@end itemize +@item +Hash tables in XEmacs belong to a kind of special objects that +make use of a concept often called 'weak pointers'. +To make a long story short, these kind of pointers are not followed +during the estimation of the live objects during garbage collection. +Any object referenced only by weak pointers is collected +anyway, and the reference to it is cleared. In hash tables there are +different usage patterns of them, manifesting in different types of hash +tables, namely 'non-weak', 'weak', 'key-weak' and 'value-weak' +(internally also 'key-car-weak' and 'value-car-weak') hash tables, each +clearing entries depending on different conditions. More information can +be found in the documentation to the function @code{make-hash-table}. + +Because there are complicated dependency rules about when and what to +mark while processing weak hash tables, the standard @code{marker} +method is only active if it is marking non-weak hash tables. As soon as +a weak component is in the table, the hash table entries are ignored +while marking. Instead their marking is done each separately by the +function @code{finish_marking_weak_hash_tables}. This function iterates +over each hash table entry @code{hentries} for each weak hash table in +@code{Vall_weak_hash_tables}. Depending on the type of a table, the +appropriate action is performed. +If a table is acting as @code{HASH_TABLE_KEY_WEAK}, and a key already marked, +everything reachable from the @code{value} component is marked. If it is +acting as a @code{HASH_TABLE_VALUE_WEAK} and the value component is +already marked, the marking starts beginning only from the +@code{key} component. +If it is a @code{HASH_TABLE_KEY_CAR_WEAK} and the car +of the key entry is already marked, we mark both the @code{key} and +@code{value} components. +Finally, if the table is of the type @code{HASH_TABLE_VALUE_CAR_WEAK} +and the car of the value components is already marked, again both the +@code{key} and the @code{value} components get marked. + +Again, there are lists with comparable properties called weak +lists. There exist different peculiarities of their types called +@code{simple}, @code{assoc}, @code{key-assoc} and +@code{value-assoc}. You can find further details about them in the +description to the function @code{make-weak-list}. The scheme of their +marking is similar: all weak lists are listed in @code{Qall_weak_lists}, +therefore we iterate over them. The marking is advanced until we hit an +already marked pair. Then we know that during a former run all +the rest has been marked completely. Again, depending on the special +type of the weak list, our jobs differ. If it is a @code{WEAK_LIST_SIMPLE} +and the elem is marked, we mark the @code{cons} part. If it is a +@code{WEAK_LIST_ASSOC} and not a pair or a pair with both marked car and +cdr, we mark the @code{cons} and the @code{elem}. If it is a +@code{WEAK_LIST_KEY_ASSOC} and not a pair or a pair with a marked car of +the elem, we mark the @code{cons} and the @code{elem}. Finally, if it is +a @code{WEAK_LIST_VALUE_ASSOC} and not a pair or a pair with a marked +cdr of the elem, we mark both the @code{cons} and the @code{elem}. + +Since, by marking objects in reach from weak hash tables and weak lists, +other objects could get marked, this perhaps implies further marking of +other weak objects, both finishing functions are redone as long as +yet unmarked objects get freshly marked. + +@item +After completing the special marking for the weak hash tables and for the weak +lists, all entries that point to objects that are going to be swept in +the further process are useless, and therefore have to be removed from +the table or the list. + +The function @code{prune_weak_hash_tables} does the job for weak hash +tables. Totally unmarked hash tables are removed from the list +@code{Vall_weak_hash_tables}. The other ones are treated more carefully +by scanning over all entries and removing one as soon as one of +the components @code{key} and @code{value} is unmarked. + +The same idea applies to the weak lists. It is accomplished by +@code{prune_weak_lists}: An unmarked list is pruned from +@code{Vall_weak_lists} immediately. A marked list is treated more +carefully by going over it and removing just the unmarked pairs. + +@item +The function @code{prune_specifiers} checks all listed specifiers held +in @code{Vall_specifiers} and removes the ones from the lists that are +unmarked. + +@item +All syntax tables are stored in a list called +@code{Vall_syntax_tables}. The function @code{prune_syntax_tables} walks +through it and unlinks the tables that are unmarked. + +@item +Next, we will attack the complete sweeping - the function +@code{gc_sweep} which holds the predominance. +@item +First, all the variables with respect to garbage collection are +reset. @code{consing_since_gc} - the counter of the created cells since +the last garbage collection - is set back to 0, and +@code{gc_in_progress} is not @code{true} anymore. +@item +In case the session is interactive, the displayed cursor and message are +removed again. +@item +The state of @code{gc_inhibit} is restored to the former value by +unwinding the stack. +@item +A small memory reserve is always held back that can be reached by +@code{breathing_space}. If nothing more is left, we create a new reserve +and exit. +@end enumerate + +@node mark_object, gc_sweep, garbage_collect_1, Garbage Collection - Step by Step +@subsection @code{mark_object} +@cindex @code{mark_object} + +The first thing that is checked while marking an object is whether the +object is a real Lisp object @code{Lisp_Type_Record} or just an integer +or a character. Integers and characters are the only two types that are +stored directly - without another level of indirection, and therefore they +don't have to be marked and collected. +@xref{How Lisp Objects Are Represented in C}. + +The second case is the one we have to handle. It is the one when we are +dealing with a pointer to a Lisp object. But, there exist also three +possibilities, that prevent us from doing anything while marking: The +object is read only which prevents it from being garbage collected, +i.e. marked (@code{C_READONLY_RECORD_HEADER}). The object in question is +already marked, and need not be marked for the second time (checked by +@code{MARKED_RECORD_HEADER_P}). If it is a special, unmarkable object +(@code{UNMARKABLE_RECORD_HEADER_P}, apparently, these are objects that +sit in some const space, and can therefore not be marked, see +@code{this_one_is_unmarkable} in @code{alloc.c}). + +Now, the actual marking is feasible. We do so by once using the macro +@code{MARK_RECORD_HEADER} to mark the object itself (actually the +special flag in the lrecord header), and calling its special marker +"method" @code{marker} if available. The marker method marks every +other object that is in reach from our current object. Note, that these +marker methods should not call @code{mark_object} recursively, but +instead should return the next object from where further marking has to +be performed. + +In case another object was returned, as mentioned before, we reiterate +the whole @code{mark_object} process beginning with this next object. + +@node gc_sweep, sweep_lcrecords_1, mark_object, Garbage Collection - Step by Step +@subsection @code{gc_sweep} +@cindex @code{gc_sweep} + +The job of this function is to free all unmarked records from memory. As +we know, there are different types of objects implemented and managed, and +consequently different ways to free them from memory. +@xref{Introduction to Allocation}. + +We start with all objects stored through @code{lcrecords}. All +bulkier objects are allocated and handled using that scheme of +@code{lcrecords}. Each object is @code{malloc}ed separately +instead of placing it in one of the contiguous frob blocks. All types +that are currently stored +using @code{lcrecords}'s @code{alloc_lcrecord} and +@code{make_lcrecord_list} are the types: vectors, buffers, +char-table, char-table-entry, console, weak-list, database, device, +ldap, hash-table, command-builder, extent-auxiliary, extent-info, face, +coding-system, frame, image-instance, glyph, popup-data, gui-item, +keymap, charset, color_instance, font_instance, opaque, opaque-list, +process, range-table, specifier, symbol-value-buffer-local, +symbol-value-lisp-magic, symbol-value-varalias, toolbar-button, +tooltalk-message, tooltalk-pattern, window, and window-configuration. We +take care of them in the fist place +in order to be able to handle and to finalize items stored in them more +easily. The function @code{sweep_lcrecords_1} as described below is +doing the whole job for us. +For a description about the internals: @xref{lrecords}. + +Our next candidates are the other objects that behave quite differently +than everything else: the strings. They consists of two parts, a +fixed-size portion (@code{struct Lisp_String}) holding the string's +length, its property list and a pointer to the second part, and the +actual string data, which is stored in string-chars blocks comparable to +frob blocks. In this block, the data is not only freed, but also a +compression of holes is made, i.e. all strings are relocated together. +@xref{String}. This compacting phase is performed by the function +@code{compact_string_chars}, the actual sweeping by the function +@code{sweep_strings} is described below. + +After that, the other types are swept step by step using functions +@code{sweep_conses}, @code{sweep_bit_vectors_1}, +@code{sweep_compiled_functions}, @code{sweep_floats}, +@code{sweep_symbols}, @code{sweep_extents}, @code{sweep_markers} and +@code{sweep_extents}. They are the fixed-size types cons, floats, +compiled-functions, symbol, marker, extent, and event stored in +so-called "frob blocks", and therefore we can basically do the same on +every type objects, using the same macros, especially defined only to +handle everything with respect to fixed-size blocks. The only fixed-size +type that is not handled here are the fixed-size portion of strings, +because we took special care of them earlier. + +The only big exceptions are bit vectors stored differently and +therefore treated differently by the function @code{sweep_bit_vectors_1} +described later. + +At first, we need some brief information about how +these fixed-size types are managed in general, in order to understand +how the sweeping is done. They have all a fixed size, and are therefore +stored in big blocks of memory - allocated at once - that can hold a +certain amount of objects of one type. The macro +@code{DECLARE_FIXED_TYPE_ALLOC} creates the suitable structures for +every type. More precisely, we have the block struct +(holding a pointer to the previous block @code{prev} and the +objects in @code{block[]}), a pointer to current block +(@code{current_..._block)}) and its last index +(@code{current_..._block_index}), and a pointer to the free list that +will be created. Also a macro @code{FIXED_TYPE_FROM_BLOCK} plus some +related macros exists that are used to obtain a new object, either from +the free list @code{ALLOCATE_FIXED_TYPE_1} if there is an unused object +of that type stored or by allocating a completely new block using +@code{ALLOCATE_FIXED_TYPE_FROM_BLOCK}. + +The rest works as follows: all of them define a +macro @code{UNMARK_...} that is used to unmark the object. They define a +macro @code{ADDITIONAL_FREE_...} that defines additional work that has +to be done when converting an object from in use to not in use (so far, +only markers use it in order to unchain them). Then, they all call +the macro @code{SWEEP_FIXED_TYPE_BLOCK} instantiated with their type name +and their struct name. + +This call in particular does the following: we go over all blocks +starting with the current moving towards the oldest. +For each block, we look at every object in it. If the object already +freed (checked with @code{FREE_STRUCT_P} using the first pointer of the +object), or if it is +set to read only (@code{C_READONLY_RECORD_HEADER_P}, nothing must be +done. If it is unmarked (checked with @code{MARKED_RECORD_HEADER_P}), it +is put in the free list and set free (using the macro +@code{FREE_FIXED_TYPE}, otherwise it stays in the block, but is unmarked +(by @code{UNMARK_...}). While going through one block, we note if the +whole block is empty. If so, the whole block is freed (using +@code{xfree}) and the free list state is set to the state it had before +handling this block. + +@node sweep_lcrecords_1, compact_string_chars, gc_sweep, Garbage Collection - Step by Step +@subsection @code{sweep_lcrecords_1} +@cindex @code{sweep_lcrecords_1} + +After nullifying the complete lcrecord statistics, we go over all +lcrecords two separate times. They are all chained together in a list with +a head called @code{all_lcrecords}. + +The first loop calls for each object its @code{finalizer} method, but only +in the case that it is not read only +(@code{C_READONLY_RECORD_HEADER_P)}, it is not already marked +(@code{MARKED_RECORD_HEADER_P}), it is not already in a free list (list of +freed objects, field @code{free}) and finally it owns a finalizer +method. + +The second loop actually frees the appropriate objects again by iterating +through the whole list. In case an object is read only or marked, it +has to persist, otherwise it is manually freed by calling +@code{xfree}. During this loop, the lcrecord statistics are kept up to +date by calling @code{tick_lcrecord_stats} with the right arguments, + +@node compact_string_chars, sweep_strings, sweep_lcrecords_1, Garbage Collection - Step by Step +@subsection @code{compact_string_chars} +@cindex @code{compact_string_chars} + +The purpose of this function is to compact all the data parts of the +strings that are held in so-called @code{string_chars_block}, i.e. the +strings that do not exceed a certain maximal length. + +The procedure with which this is done is as follows. We are keeping two +positions in the @code{string_chars_block}s using two pointer/integer +pairs, namely @code{from_sb}/@code{from_pos} and +@code{to_sb}/@code{to_pos}. They stand for the actual positions, from +where to where, to copy the actually handled string. + +While going over all chained @code{string_char_block}s and their held +strings, staring at @code{first_string_chars_block}, both pointers +are advanced and eventually a string is copied from @code{from_sb} to +@code{to_sb}, depending on the status of the pointed at strings. + +More precisely, we can distinguish between the following actions. +@itemize @bullet +@item +The string at @code{from_sb}'s position could be marked as free, which +is indicated by an invalid pointer to the pointer that should point back +to the fixed size string object, and which is checked by +@code{FREE_STRUCT_P}. In this case, the @code{from_sb}/@code{from_pos} +is advanced to the next string, and nothing has to be copied. +@item +Also, if a string object itself is unmarked, nothing has to be +copied. We likewise advance the @code{from_sb}/@code{from_pos} +pair as described above. +@item +In all other cases, we have a marked string at hand. The string data +must be moved from the from-position to the to-position. In case +there is not enough space in the actual @code{to_sb}-block, we advance +this pointer to the beginning of the next block before copying. In case the +from and to positions are different, we perform the +actual copying using the library function @code{memmove}. +@end itemize + +After compacting, the pointer to the current +@code{string_chars_block}, sitting in @code{current_string_chars_block}, +is reset on the last block to which we moved a string, +i.e. @code{to_block}, and all remaining blocks (we know that they just +carry garbage) are explicitly @code{xfree}d. + +@node sweep_strings, sweep_bit_vectors_1, compact_string_chars, Garbage Collection - Step by Step +@subsection @code{sweep_strings} +@cindex @code{sweep_strings} + +The sweeping for the fixed sized string objects is essentially exactly +the same as it is for all other fixed size types. As before, the freeing +into the suitable free list is done by using the macro +@code{SWEEP_FIXED_SIZE_BLOCK} after defining the right macros +@code{UNMARK_string} and @code{ADDITIONAL_FREE_string}. These two +definitions are a little bit special compared to the ones used +for the other fixed size types. + +@code{UNMARK_string} is defined the same way except some additional code +used for updating the bookkeeping information. + +For strings, @code{ADDITIONAL_FREE_string} has to do something in +addition: in case, the string was not allocated in a +@code{string_chars_block} because it exceeded the maximal length, and +therefore it was @code{malloc}ed separately, we know also @code{xfree} +it explicitly. + +@node sweep_bit_vectors_1, , sweep_strings, Garbage Collection - Step by Step +@subsection @code{sweep_bit_vectors_1} +@cindex @code{sweep_bit_vectors_1} + +Bit vectors are also one of the rare types that are @code{malloc}ed +individually. Consequently, while sweeping, all further needless +bit vectors must be freed by hand. This is done, as one might imagine, +the expected way: since they are all registered in a list called +@code{all_bit_vectors}, all elements of that list are traversed, +all unmarked bit vectors are unlinked by calling @code{xfree} and all of +them become unmarked. +In addition, the bookkeeping information used for garbage +collector's output purposes is updated. + +@node Integers and Characters, Allocation from Frob Blocks, Garbage Collection - Step by Step, Allocation of Objects in XEmacs Lisp +@section Integers and Characters +@cindex integers and characters +@cindex characters, integers and + + Integer and character Lisp objects are created from integers using the +macros @code{XSETINT()} and @code{XSETCHAR()} or the equivalent +functions @code{make_int()} and @code{make_char()}. (These are actually +macros on most systems.) These functions basically just do some moving +of bits around, since the integral value of the object is stored +directly in the @code{Lisp_Object}. + + @code{XSETINT()} and the like will truncate values given to them that +are too big; i.e. you won't get the value you expected but the tag bits +will at least be correct. + +@node Allocation from Frob Blocks, lrecords, Integers and Characters, Allocation of Objects in XEmacs Lisp +@section Allocation from Frob Blocks +@cindex allocation from frob blocks +@cindex frob blocks, allocation from + +The uninitialized memory required by a @code{Lisp_Object} of a particular type +is allocated using +@code{ALLOCATE_FIXED_TYPE()}. This only occurs inside of the +lowest-level object-creating functions in @file{alloc.c}: +@code{Fcons()}, @code{make_float()}, @code{Fmake_byte_code()}, +@code{Fmake_symbol()}, @code{allocate_extent()}, +@code{allocate_event()}, @code{Fmake_marker()}, and +@code{make_uninit_string()}. The idea is that, for each type, there are +a number of frob blocks (each 2K in size); each frob block is divided up +into object-sized chunks. Each frob block will have some of these +chunks that are currently assigned to objects, and perhaps some that are +free. (If a frob block has nothing but free chunks, it is freed at the +end of the garbage collection cycle.) The free chunks are stored in a +free list, which is chained by storing a pointer in the first four bytes +of the chunk. (Except for the free chunks at the end of the last frob +block, which are handled using an index which points past the end of the +last-allocated chunk in the last frob block.) +@code{ALLOCATE_FIXED_TYPE()} first tries to retrieve a chunk from the +free list; if that fails, it calls +@code{ALLOCATE_FIXED_TYPE_FROM_BLOCK()}, which looks at the end of the +last frob block for space, and creates a new frob block if there is +none. (There are actually two versions of these macros, one of which is +more defensive but less efficient and is used for error-checking.) + +@node lrecords, Low-level allocation, Allocation from Frob Blocks, Allocation of Objects in XEmacs Lisp +@section lrecords +@cindex lrecords + + [see @file{lrecord.h}] + + All lrecords have at the beginning of their structure a @code{struct +lrecord_header}. This just contains a type number and some flags, +including the mark bit. All builtin type numbers are defined as +constants in @code{enum lrecord_type}, to allow the compiler to generate +more efficient code for @code{@var{type}P}. The type number, thru the +@code{lrecord_implementation_table}, gives access to a @code{struct +lrecord_implementation}, which is a structure containing method pointers +and such. There is one of these for each type, and it is a global, +constant, statically-declared structure that is declared in the +@code{DEFINE_LRECORD_IMPLEMENTATION()} macro. + + Simple lrecords (of type (b) above) just have a @code{struct +lrecord_header} at their beginning. lcrecords, however, actually have a +@code{struct lcrecord_header}. This, in turn, has a @code{struct +lrecord_header} at its beginning, so sanity is preserved; but it also +has a pointer used to chain all lcrecords together, and a special ID +field used to distinguish one lcrecord from another. (This field is used +only for debugging and could be removed, but the space gain is not +significant.) + + Simple lrecords are created using @code{ALLOCATE_FIXED_TYPE()}, just +like for other frob blocks. The only change is that the implementation +pointer must be initialized correctly. (The implementation structure for +an lrecord, or rather the pointer to it, is named @code{lrecord_float}, +@code{lrecord_extent}, @code{lrecord_buffer}, etc.) + + lcrecords are created using @code{alloc_lcrecord()}. This takes a +size to allocate and an implementation pointer. (The size needs to be +passed because some lcrecords, such as window configurations, are of +variable size.) This basically just @code{malloc()}s the storage, +initializes the @code{struct lcrecord_header}, and chains the lcrecord +onto the head of the list of all lcrecords, which is stored in the +variable @code{all_lcrecords}. The calls to @code{alloc_lcrecord()} +generally occur in the lowest-level allocation function for each lrecord +type. + +Whenever you create an lrecord, you need to call either +@code{DEFINE_LRECORD_IMPLEMENTATION()} or +@code{DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION()}. This needs to be +specified in a @file{.c} file, at the top level. What this actually +does is define and initialize the implementation structure for the +lrecord. (And possibly declares a function @code{error_check_foo()} that +implements the @code{XFOO()} macro when error-checking is enabled.) The +arguments to the macros are the actual type name (this is used to +construct the C variable name of the lrecord implementation structure +and related structures using the @samp{##} macro concatenation +operator), a string that names the type on the Lisp level (this may not +be the same as the C type name; typically, the C type name has +underscores, while the Lisp string has dashes), various method pointers, +and the name of the C structure that contains the object. The methods +are used to encapsulate type-specific information about the object, such +as how to print it or mark it for garbage collection, so that it's easy +to add new object types without having to add a specific case for each +new type in a bunch of different places. + + The difference between @code{DEFINE_LRECORD_IMPLEMENTATION()} and +@code{DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION()} is that the former is +used for fixed-size object types and the latter is for variable-size +object types. Most object types are fixed-size; some complex +types, however (e.g. window configurations), are variable-size. +Variable-size object types have an extra method, which is called +to determine the actual size of a particular object of that type. +(Currently this is only used for keeping allocation statistics.) + + For the purpose of keeping allocation statistics, the allocation +engine keeps a list of all the different types that exist. Note that, +since @code{DEFINE_LRECORD_IMPLEMENTATION()} is a macro that is +specified at top-level, there is no way for it to initialize the global +data structures containing type information, like +@code{lrecord_implementations_table}. For this reason a call to +@code{INIT_LRECORD_IMPLEMENTATION} must be added to the same source file +containing @code{DEFINE_LRECORD_IMPLEMENTATION}, but instead of to the +top level, to one of the init functions, typically +@code{syms_of_@var{foo}.c}. @code{INIT_LRECORD_IMPLEMENTATION} must be +called before an object of this type is used. + +The type number is also used to index into an array holding the number +of objects of each type and the total memory allocated for objects of +that type. The statistics in this array are computed during the sweep +stage. These statistics are returned by the call to +@code{garbage-collect}. + + Note that for every type defined with a @code{DEFINE_LRECORD_*()} +macro, there needs to be a @code{DECLARE_LRECORD_IMPLEMENTATION()} +somewhere in a @file{.h} file, and this @file{.h} file needs to be +included by @file{inline.c}. + + Furthermore, there should generally be a set of @code{XFOOBAR()}, +@code{FOOBARP()}, etc. macros in a @file{.h} (or occasionally @file{.c}) +file. To create one of these, copy an existing model and modify as +necessary. + + @strong{Please note:} If you define an lrecord in an external +dynamically-loaded module, you must use @code{DECLARE_EXTERNAL_LRECORD}, +@code{DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION}, and +@code{DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION} instead of the +non-EXTERNAL forms. These macros will dynamically add new type numbers +to the global enum that records them, whereas the non-EXTERNAL forms +assume that the programmer has already inserted the correct type numbers +into the enum's code at compile-time. + + The various methods in the lrecord implementation structure are: + +@enumerate +@item +@cindex mark method +A @dfn{mark} method. This is called during the marking stage and passed +a function pointer (usually the @code{mark_object()} function), which is +used to mark an object. All Lisp objects that are contained within the +object need to be marked by applying this function to them. The mark +method should also return a Lisp object, which should be either @code{nil} or +an object to mark. (This can be used in lieu of calling +@code{mark_object()} on the object, to reduce the recursion depth, and +consequently should be the most heavily nested sub-object, such as a +long list.) + +@strong{Please note:} When the mark method is called, garbage collection +is in progress, and special precautions need to be taken when accessing +objects; see section (B) above. + +If your mark method does not need to do anything, it can be +@code{NULL}. + +@item +A @dfn{print} method. This is called to create a printed representation +of the object, whenever @code{princ}, @code{prin1}, or the like is +called. It is passed the object, a stream to which the output is to be +directed, and an @code{escapeflag} which indicates whether the object's +printed representation should be @dfn{escaped} so that it is +readable. (This corresponds to the difference between @code{princ} and +@code{prin1}.) Basically, @dfn{escaped} means that strings will have +quotes around them and confusing characters in the strings such as +quotes, backslashes, and newlines will be backslashed; and that special +care will be taken to make symbols print in a readable fashion +(e.g. symbols that look like numbers will be backslashed). Other +readable objects should perhaps pass @code{escapeflag} on when +sub-objects are printed, so that readability is preserved when necessary +(or if not, always pass in a 1 for @code{escapeflag}). Non-readable +objects should in general ignore @code{escapeflag}, except that some use +it as an indication that more verbose output should be given. + +Sub-objects are printed using @code{print_internal()}, which takes +exactly the same arguments as are passed to the print method. + +Literal C strings should be printed using @code{write_c_string()}, +or @code{write_string_1()} for non-null-terminated strings. + +Functions that do not have a readable representation should check the +@code{print_readably} flag and signal an error if it is set. + +If you specify NULL for the print method, the +@code{default_object_printer()} will be used. + +@item +A @dfn{finalize} method. This is called at the beginning of the sweep +stage on lcrecords that are about to be freed, and should be used to +perform any extra object cleanup. This typically involves freeing any +extra @code{malloc()}ed memory associated with the object, releasing any +operating-system and window-system resources associated with the object +(e.g. pixmaps, fonts), etc. + +The finalize method can be NULL if nothing needs to be done. + +WARNING #1: The finalize method is also called at the end of the dump +phase; this time with the for_disksave parameter set to non-zero. The +object is @emph{not} about to disappear, so you have to make sure to +@emph{not} free any extra @code{malloc()}ed memory if you're going to +need it later. (Also, signal an error if there are any operating-system +and window-system resources here, because they can't be dumped.) + +Finalize methods should, as a rule, set to zero any pointers after +they've been freed, and check to make sure pointers are not zero before +freeing. Although I'm pretty sure that finalize methods are not called +twice on the same object (except for the @code{for_disksave} proviso), +we've gotten nastily burned in some cases by not doing this. + +WARNING #2: The finalize method is @emph{only} called for +lcrecords, @emph{not} for simply lrecords. If you need a +finalize method for simple lrecords, you have to stick +it in the @code{ADDITIONAL_FREE_foo()} macro in @file{alloc.c}. + +WARNING #3: Things are in an @emph{extremely} bizarre state +when @code{ADDITIONAL_FREE_foo()} is called, so you have to +be incredibly careful when writing one of these functions. +See the comment in @code{gc_sweep()}. If you ever have to add +one of these, consider using an lcrecord or dealing with +the problem in a different fashion. + +@item +An @dfn{equal} method. This compares the two objects for similarity, +when @code{equal} is called. It should compare the contents of the +objects in some reasonable fashion. It is passed the two objects and a +@dfn{depth} value, which is used to catch circular objects. To compare +sub-Lisp-objects, call @code{internal_equal()} and bump the depth value +by one. If this value gets too high, a @code{circular-object} error +will be signaled. + +If this is NULL, objects are @code{equal} only when they are @code{eq}, +i.e. identical. + +@item +A @dfn{hash} method. This is used to hash objects when they are to be +compared with @code{equal}. The rule here is that if two objects are +@code{equal}, they @emph{must} hash to the same value; i.e. your hash +function should use some subset of the sub-fields of the object that are +compared in the ``equal'' method. If you specify this method as +@code{NULL}, the object's pointer will be used as the hash, which will +@emph{fail} if the object has an @code{equal} method, so don't do this. + +To hash a sub-Lisp-object, call @code{internal_hash()}. Bump the +depth by one, just like in the ``equal'' method. + +To convert a Lisp object directly into a hash value (using +its pointer), use @code{LISP_HASH()}. This is what happens when +the hash method is NULL. + +To hash two or more values together into a single value, use +@code{HASH2()}, @code{HASH3()}, @code{HASH4()}, etc. + +@item +@dfn{getprop}, @dfn{putprop}, @dfn{remprop}, and @dfn{plist} methods. +These are used for object types that have properties. I don't feel like +documenting them here. If you create one of these objects, you have to +use different macros to define them, +i.e. @code{DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS()} or +@code{DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS()}. + +@item +A @dfn{size_in_bytes} method, when the object is of variable-size. +(i.e. declared with a @code{_SEQUENCE_IMPLEMENTATION} macro.) This should +simply return the object's size in bytes, exactly as you might expect. +For an example, see the methods for window configurations and opaques. +@end enumerate + +@node Low-level allocation, Cons, lrecords, Allocation of Objects in XEmacs Lisp +@section Low-level allocation +@cindex low-level allocation +@cindex allocation, low-level + + Memory that you want to allocate directly should be allocated using +@code{xmalloc()} rather than @code{malloc()}. This implements +error-checking on the return value, and once upon a time did some more +vital stuff (i.e. @code{BLOCK_INPUT}, which is no longer necessary). +Free using @code{xfree()}, and realloc using @code{xrealloc()}. Note +that @code{xmalloc()} will do a non-local exit if the memory can't be +allocated. (Many functions, however, do not expect this, and thus XEmacs +will likely crash if this happens. @strong{This is a bug.} If you can, +you should strive to make your function handle this OK. However, it's +difficult in the general circumstance, perhaps requiring extra +unwind-protects and such.) + + Note that XEmacs provides two separate replacements for the standard +@code{malloc()} library function. These are called @dfn{old GNU malloc} +(@file{malloc.c}) and @dfn{new GNU malloc} (@file{gmalloc.c}), +respectively. New GNU malloc is better in pretty much every way than +old GNU malloc, and should be used if possible. (It used to be that on +some systems, the old one worked but the new one didn't. I think this +was due specifically to a bug in SunOS, which the new one now works +around; so I don't think the old one ever has to be used any more.) The +primary difference between both of these mallocs and the standard system +malloc is that they are much faster, at the expense of increased space. +The basic idea is that memory is allocated in fixed chunks of powers of +two. This allows for basically constant malloc time, since the various +chunks can just be kept on a number of free lists. (The standard system +malloc typically allocates arbitrary-sized chunks and has to spend some +time, sometimes a significant amount of time, walking the heap looking +for a free block to use and cleaning things up.) The new GNU malloc +improves on things by allocating large objects in chunks of 4096 bytes +rather than in ever larger powers of two, which results in ever larger +wastage. There is a slight speed loss here, but it's of doubtful +significance. + + NOTE: Apparently there is a third-generation GNU malloc that is +significantly better than the new GNU malloc, and should probably +be included in XEmacs. + + There is also the relocating allocator, @file{ralloc.c}. This actually +moves blocks of memory around so that the @code{sbrk()} pointer shrunk +and virtual memory released back to the system. On some systems, +this is a big win. On all systems, it causes a noticeable (and +sometimes huge) speed penalty, so I turn it off by default. +@file{ralloc.c} only works with the new GNU malloc in @file{gmalloc.c}. +There are also two versions of @file{ralloc.c}, one that uses @code{mmap()} +rather than block copies to move data around. This purports to +be faster, although that depends on the amount of data that would +have had to be block copied and the system-call overhead for +@code{mmap()}. I don't know exactly how this works, except that the +relocating-allocation routines are pretty much used only for +the memory allocated for a buffer, which is the biggest consumer +of space, esp. of space that may get freed later. + + Note that the GNU mallocs have some ``memory warning'' facilities. +XEmacs taps into them and issues a warning through the standard +warning system, when memory gets to 75%, 85%, and 95% full. +(On some systems, the memory warnings are not functional.) + + Allocated memory that is going to be used to make a Lisp object +is created using @code{allocate_lisp_storage()}. This just calls +@code{xmalloc()}. It used to verify that the pointer to the memory can +fit into a Lisp word, before the current Lisp object representation was +introduced. @code{allocate_lisp_storage()} is called by +@code{alloc_lcrecord()}, @code{ALLOCATE_FIXED_TYPE()}, and the vector +and bit-vector creation routines. These routines also call +@code{INCREMENT_CONS_COUNTER()} at the appropriate times; this keeps +statistics on how much memory is allocated, so that garbage-collection +can be invoked when the threshold is reached. + +@node Cons, Vector, Low-level allocation, Allocation of Objects in XEmacs Lisp +@section Cons +@cindex cons + + Conses are allocated in standard frob blocks. The only thing to +note is that conses can be explicitly freed using @code{free_cons()} +and associated functions @code{free_list()} and @code{free_alist()}. This +immediately puts the conses onto the cons free list, and decrements +the statistics on memory allocation appropriately. This is used +to good effect by some extremely commonly-used code, to avoid +generating extra objects and thereby triggering GC sooner. +However, you have to be @emph{extremely} careful when doing this. +If you mess this up, you will get BADLY BURNED, and it has happened +before. + +@node Vector, Bit Vector, Cons, Allocation of Objects in XEmacs Lisp +@section Vector +@cindex vector + + As mentioned above, each vector is @code{malloc()}ed individually, and +all are threaded through the variable @code{all_vectors}. Vectors are +marked strangely during garbage collection, by kludging the size field. +Note that the @code{struct Lisp_Vector} is declared with its +@code{contents} field being a @emph{stretchy} array of one element. It +is actually @code{malloc()}ed with the right size, however, and access +to any element through the @code{contents} array works fine. + +@node Bit Vector, Symbol, Vector, Allocation of Objects in XEmacs Lisp +@section Bit Vector +@cindex bit vector +@cindex vector, bit + + Bit vectors work exactly like vectors, except for more complicated +code to access an individual bit, and except for the fact that bit +vectors are lrecords while vectors are not. (The only difference here is +that there's an lrecord implementation pointer at the beginning and the +tag field in bit vector Lisp words is ``lrecord'' rather than +``vector''.) + +@node Symbol, Marker, Bit Vector, Allocation of Objects in XEmacs Lisp +@section Symbol +@cindex symbol + + Symbols are also allocated in frob blocks. Symbols in the awful +horrible obarray structure are chained through their @code{next} field. + +Remember that @code{intern} looks up a symbol in an obarray, creating +one if necessary. + +@node Marker, String, Symbol, Allocation of Objects in XEmacs Lisp +@section Marker +@cindex marker + + Markers are allocated in frob blocks, as usual. They are kept +in a buffer unordered, but in a doubly-linked list so that they +can easily be removed. (Formerly this was a singly-linked list, +but in some cases garbage collection took an extraordinarily +long time due to the O(N^2) time required to remove lots of +markers from a buffer.) Markers are removed from a buffer in +the finalize stage, in @code{ADDITIONAL_FREE_marker()}. + +@node String, Compiled Function, Marker, Allocation of Objects in XEmacs Lisp +@section String +@cindex string + + As mentioned above, strings are a special case. A string is logically +two parts, a fixed-size object (containing the length, property list, +and a pointer to the actual data), and the actual data in the string. +The fixed-size object is a @code{struct Lisp_String} and is allocated in +frob blocks, as usual. The actual data is stored in special +@dfn{string-chars blocks}, which are 8K blocks of memory. +Currently-allocated strings are simply laid end to end in these +string-chars blocks, with a pointer back to the @code{struct Lisp_String} +stored before each string in the string-chars block. When a new string +needs to be allocated, the remaining space at the end of the last +string-chars block is used if there's enough, and a new string-chars +block is created otherwise. + + There are never any holes in the string-chars blocks due to the string +compaction and relocation that happens at the end of garbage collection. +During the sweep stage of garbage collection, when objects are +reclaimed, the garbage collector goes through all string-chars blocks, +looking for unused strings. Each chunk of string data is preceded by a +pointer to the corresponding @code{struct Lisp_String}, which indicates +both whether the string is used and how big the string is, i.e. how to +get to the next chunk of string data. Holes are compressed by +block-copying the next string into the empty space and relocating the +pointer stored in the corresponding @code{struct Lisp_String}. +@strong{This means you have to be careful with strings in your code.} +See the section above on @code{GCPRO}ing. + + Note that there is one situation not handled: a string that is too big +to fit into a string-chars block. Such strings, called @dfn{big +strings}, are all @code{malloc()}ed as their own block. (#### Although it +would make more sense for the threshold for big strings to be somewhat +lower, e.g. 1/2 or 1/4 the size of a string-chars block. It seems that +this was indeed the case formerly---indeed, the threshold was set at +1/8---but Mly forgot about this when rewriting things for 19.8.) + +Note also that the string data in string-chars blocks is padded as +necessary so that proper alignment constraints on the @code{struct +Lisp_String} back pointers are maintained. + + Finally, strings can be resized. This happens in Mule when a +character is substituted with a different-length character, or during +modeline frobbing. (You could also export this to Lisp, but it's not +done so currently.) Resizing a string is a potentially tricky process. +If the change is small enough that the padding can absorb it, nothing +other than a simple memory move needs to be done. Keep in mind, +however, that the string can't shrink too much because the offset to the +next string in the string-chars block is computed by looking at the +length and rounding to the nearest multiple of four or eight. If the +string would shrink or expand beyond the correct padding, new string +data needs to be allocated at the end of the last string-chars block and +the data moved appropriately. This leaves some dead string data, which +is marked by putting a special marker of 0xFFFFFFFF in the @code{struct +Lisp_String} pointer before the data (there's no real @code{struct +Lisp_String} to point to and relocate), and storing the size of the dead +string data (which would normally be obtained from the now-non-existent +@code{struct Lisp_String}) at the beginning of the dead string data gap. +The string compactor recognizes this special 0xFFFFFFFF marker and +handles it correctly. + +@node Compiled Function, , String, Allocation of Objects in XEmacs Lisp +@section Compiled Function +@cindex compiled function +@cindex function, compiled + + Not yet documented. + + +@node The Lisp Reader and Compiler, Evaluation; Stack Frames; Bindings, Allocation of Objects in XEmacs Lisp, Top +@chapter The Lisp Reader and Compiler +@cindex Lisp reader and compiler, the +@cindex reader and compiler, the Lisp +@cindex compiler, the Lisp reader and + +Not yet documented. + +@node Evaluation; Stack Frames; Bindings, Symbols and Variables, The Lisp Reader and Compiler, Top +@chapter Evaluation; Stack Frames; Bindings +@cindex evaluation; stack frames; bindings +@cindex stack frames; bindings, evaluation; +@cindex bindings, evaluation; stack frames; + +@menu +* Evaluation:: +* Dynamic Binding; The specbinding Stack; Unwind-Protects:: +* Simple Special Forms:: +* Catch and Throw:: +* Error Trapping:: +@end menu + +@node Evaluation, Dynamic Binding; The specbinding Stack; Unwind-Protects, Evaluation; Stack Frames; Bindings, Evaluation; Stack Frames; Bindings +@section Evaluation +@cindex evaluation + + @code{Feval()} evaluates the form (a Lisp object) that is passed to +it. Note that evaluation is only non-trivial for two types of objects: +symbols and conses. A symbol is evaluated simply by calling +@code{symbol-value} on it and returning the value. + + Evaluating a cons means calling a function. First, @code{eval} checks +to see if garbage-collection is necessary, and calls +@code{garbage_collect_1()} if so. It then increases the evaluation +depth by 1 (@code{lisp_eval_depth}, which is always less than +@code{max_lisp_eval_depth}) and adds an element to the linked list of +@code{struct backtrace}'s (@code{backtrace_list}). Each such structure +contains a pointer to the function being called plus a list of the +function's arguments. Originally these values are stored unevalled, and +as they are evaluated, the backtrace structure is updated. Garbage +collection pays attention to the objects pointed to in the backtrace +structures (garbage collection might happen while a function is being +called or while an argument is being evaluated, and there could easily +be no other references to the arguments in the argument list; once an +argument is evaluated, however, the unevalled version is not needed by +eval, and so the backtrace structure is changed). + +At this point, the function to be called is determined by looking at +the car of the cons (if this is a symbol, its function definition is +retrieved and the process repeated). The function should then consist +of either a @code{Lisp_Subr} (built-in function written in C), a +@code{Lisp_Compiled_Function} object, or a cons whose car is one of the +symbols @code{autoload}, @code{macro} or @code{lambda}. + +If the function is a @code{Lisp_Subr}, the lisp object points to a +@code{struct Lisp_Subr} (created by @code{DEFUN()}), which contains a +pointer to the C function, a minimum and maximum number of arguments +(or possibly the special constants @code{MANY} or @code{UNEVALLED}), a +pointer to the symbol referring to that subr, and a couple of other +things. If the subr wants its arguments @code{UNEVALLED}, they are +passed raw as a list. Otherwise, an array of evaluated arguments is +created and put into the backtrace structure, and either passed whole +(@code{MANY}) or each argument is passed as a C argument. + +If the function is a @code{Lisp_Compiled_Function}, +@code{funcall_compiled_function()} is called. If the function is a +lambda list, @code{funcall_lambda()} is called. If the function is a +macro, [..... fill in] is done. If the function is an autoload, +@code{do_autoload()} is called to load the definition and then eval +starts over [explain this more]. + +When @code{Feval()} exits, the evaluation depth is reduced by one, the +debugger is called if appropriate, and the current backtrace structure +is removed from the list. + +Both @code{funcall_compiled_function()} and @code{funcall_lambda()} need +to go through the list of formal parameters to the function and bind +them to the actual arguments, checking for @code{&rest} and +@code{&optional} symbols in the formal parameters and making sure the +number of actual arguments is correct. +@code{funcall_compiled_function()} can do this a little more +efficiently, since the formal parameter list can be checked for sanity +when the compiled function object is created. + +@code{funcall_lambda()} simply calls @code{Fprogn} to execute the code +in the lambda list. + +@code{funcall_compiled_function()} calls the real byte-code interpreter +@code{execute_optimized_program()} on the byte-code instructions, which +are converted into an internal form for faster execution. + +When a compiled function is executed for the first time by +@code{funcall_compiled_function()}, or during the dump phase of building +XEmacs, the byte-code instructions are converted from a +@code{Lisp_String} (which is inefficient to access, especially in the +presence of MULE) into a @code{Lisp_Opaque} object containing an array +of unsigned char, which can be directly executed by the byte-code +interpreter. At this time the byte code is also analyzed for validity +and transformed into a more optimized form, so that +@code{execute_optimized_program()} can really fly. + +Here are some of the optimizations performed by the internal byte-code +transformer: +@enumerate +@item +References to the @code{constants} array are checked for out-of-range +indices, so that the byte interpreter doesn't have to. +@item +References to the @code{constants} array that will be used as a Lisp +variable are checked for being correct non-constant (i.e. not @code{t}, +@code{nil}, or @code{keywordp}) symbols, so that the byte interpreter +doesn't have to. +@item +The maximum number of variable bindings in the byte-code is +pre-computed, so that space on the @code{specpdl} stack can be +pre-reserved once for the whole function execution. +@item +All byte-code jumps are relative to the current program counter instead +of the start of the program, thereby saving a register. +@item +One-byte relative jumps are converted from the byte-code form of unsigned +chars offset by 127 to machine-friendly signed chars. +@end enumerate + +Of course, this transformation of the @code{instructions} should not be +visible to the user, so @code{Fcompiled_function_instructions()} needs +to know how to convert the optimized opaque object back into a Lisp +string that is identical to the original string from the @file{.elc} +file. (Actually, the resulting string may (rarely) contain slightly +different, yet equivalent, byte code.) + +@code{Ffuncall()} implements Lisp @code{funcall}. @code{(funcall fun +x1 x2 x3 ...)} is equivalent to @code{(eval (list fun (quote x1) (quote +x2) (quote x3) ...))}. @code{Ffuncall()} contains its own code to do +the evaluation, however, and is very similar to @code{Feval()}. + +From the performance point of view, it is worth knowing that most of the +time in Lisp evaluation is spent executing @code{Lisp_Subr} and +@code{Lisp_Compiled_Function} objects via @code{Ffuncall()} (not +@code{Feval()}). + +@code{Fapply()} implements Lisp @code{apply}, which is very similar to +@code{funcall} except that if the last argument is a list, the result is the +same as if each of the arguments in the list had been passed separately. +@code{Fapply()} does some business to expand the last argument if it's a +list, then calls @code{Ffuncall()} to do the work. + +@code{apply1()}, @code{call0()}, @code{call1()}, @code{call2()}, and +@code{call3()} call a function, passing it the argument(s) given (the +arguments are given as separate C arguments rather than being passed as +an array). @code{apply1()} uses @code{Fapply()} while the others use +@code{Ffuncall()} to do the real work. + +@node Dynamic Binding; The specbinding Stack; Unwind-Protects, Simple Special Forms, Evaluation, Evaluation; Stack Frames; Bindings +@section Dynamic Binding; The specbinding Stack; Unwind-Protects +@cindex dynamic binding; the specbinding stack; unwind-protects +@cindex binding; the specbinding stack; unwind-protects, dynamic +@cindex specbinding stack; unwind-protects, dynamic binding; the +@cindex unwind-protects, dynamic binding; the specbinding stack; + +@example +struct specbinding +@{ + Lisp_Object symbol; + Lisp_Object old_value; + Lisp_Object (*func) (Lisp_Object); /* for unwind-protect */ +@}; +@end example + + @code{struct specbinding} is used for local-variable bindings and +unwind-protects. @code{specpdl} holds an array of @code{struct specbinding}'s, +@code{specpdl_ptr} points to the beginning of the free bindings in the +array, @code{specpdl_size} specifies the total number of binding slots +in the array, and @code{max_specpdl_size} specifies the maximum number +of bindings the array can be expanded to hold. @code{grow_specpdl()} +increases the size of the @code{specpdl} array, multiplying its size by +2 but never exceeding @code{max_specpdl_size} (except that if this +number is less than 400, it is first set to 400). + + @code{specbind()} binds a symbol to a value and is used for local +variables and @code{let} forms. The symbol and its old value (which +might be @code{Qunbound}, indicating no prior value) are recorded in the +specpdl array, and @code{specpdl_size} is increased by 1. + + @code{record_unwind_protect()} implements an @dfn{unwind-protect}, +which, when placed around a section of code, ensures that some specified +cleanup routine will be executed even if the code exits abnormally +(e.g. through a @code{throw} or quit). @code{record_unwind_protect()} +simply adds a new specbinding to the @code{specpdl} array and stores the +appropriate information in it. The cleanup routine can either be a C +function, which is stored in the @code{func} field, or a @code{progn} +form, which is stored in the @code{old_value} field. + + @code{unbind_to()} removes specbindings from the @code{specpdl} array +until the specified position is reached. Each specbinding can be one of +three types: + +@enumerate +@item +an unwind-protect with a C cleanup function (@code{func} is not 0, and +@code{old_value} holds an argument to be passed to the function); +@item +an unwind-protect with a Lisp form (@code{func} is 0, @code{symbol} +is @code{nil}, and @code{old_value} holds the form to be executed with +@code{Fprogn()}); or +@item +a local-variable binding (@code{func} is 0, @code{symbol} is not +@code{nil}, and @code{old_value} holds the old value, which is stored as +the symbol's value). +@end enumerate + +@node Simple Special Forms, Catch and Throw, Dynamic Binding; The specbinding Stack; Unwind-Protects, Evaluation; Stack Frames; Bindings +@section Simple Special Forms +@cindex special forms, simple + +@code{or}, @code{and}, @code{if}, @code{cond}, @code{progn}, +@code{prog1}, @code{prog2}, @code{setq}, @code{quote}, @code{function}, +@code{let*}, @code{let}, @code{while} + +All of these are very simple and work as expected, calling +@code{Feval()} or @code{Fprogn()} as necessary and (in the case of +@code{let} and @code{let*}) using @code{specbind()} to create bindings +and @code{unbind_to()} to undo the bindings when finished. + +Note that, with the exception of @code{Fprogn}, these functions are +typically called in real life only in interpreted code, since the byte +compiler knows how to convert calls to these functions directly into +byte code. + +@node Catch and Throw, Error Trapping, Simple Special Forms, Evaluation; Stack Frames; Bindings +@section Catch and Throw +@cindex catch and throw +@cindex throw, catch and + +@example +struct catchtag +@{ + Lisp_Object tag; + Lisp_Object val; + struct catchtag *next; + struct gcpro *gcpro; + jmp_buf jmp; + struct backtrace *backlist; + int lisp_eval_depth; + int pdlcount; +@}; +@end example + + @code{catch} is a Lisp function that places a catch around a body of +code. A catch is a means of non-local exit from the code. When a catch +is created, a tag is specified, and executing a @code{throw} to this tag +will exit from the body of code caught with this tag, and its value will +be the value given in the call to @code{throw}. If there is no such +call, the code will be executed normally. + + Information pertaining to a catch is held in a @code{struct catchtag}, +which is placed at the head of a linked list pointed to by +@code{catchlist}. @code{internal_catch()} is passed a C function to +call (@code{Fprogn()} when Lisp @code{catch} is called) and arguments to +give it, and places a catch around the function. Each @code{struct +catchtag} is held in the stack frame of the @code{internal_catch()} +instance that created the catch. + + @code{internal_catch()} is fairly straightforward. It stores into the +@code{struct catchtag} the tag name and the current values of +@code{backtrace_list}, @code{lisp_eval_depth}, @code{gcprolist}, and the +offset into the @code{specpdl} array, sets a jump point with @code{_setjmp()} +(storing the jump point into the @code{struct catchtag}), and calls the +function. Control will return to @code{internal_catch()} either when +the function exits normally or through a @code{_longjmp()} to this jump +point. In the latter case, @code{throw} will store the value to be +returned into the @code{struct catchtag} before jumping. When it's +done, @code{internal_catch()} removes the @code{struct catchtag} from +the catchlist and returns the proper value. + + @code{Fthrow()} goes up through the catchlist until it finds one with +a matching tag. It then calls @code{unbind_catch()} to restore +everything to what it was when the appropriate catch was set, stores the +return value in the @code{struct catchtag}, and jumps (with +@code{_longjmp()}) to its jump point. + + @code{unbind_catch()} removes all catches from the catchlist until it +finds the correct one. Some of the catches might have been placed for +error-trapping, and if so, the appropriate entries on the handlerlist +must be removed (see ``errors''). @code{unbind_catch()} also restores +the values of @code{gcprolist}, @code{backtrace_list}, and +@code{lisp_eval}, and calls @code{unbind_to()} to undo any specbindings +created since the catch. + +@node Error Trapping, , Catch and Throw, Evaluation; Stack Frames; Bindings +@section Error Trapping +@cindex error trapping + +@subheading call_trapping_problems(): + +This is equivalent to (*fun) (arg), except that various conditions +can be trapped or inhibited, according to FLAGS. + +@itemize @bullet +@item +If FLAGS does not contain NO_INHIBIT_ERRORS, when an error occurs, +the error is caught and a warning is issued, specifying the +specific error that occurred and a backtrace. In that case, +WARNING_STRING should be given, and will be printed at the +beginning of the error to indicate where the error occurred. + +@item +If FLAGS does not contain NO_INHIBIT_THROWS, all attempts to +@code{throw} out of the function being called are trapped, and a warning +issued. (Again, WARNING_STRING should be given.) + +@item +If FLAGS contains INHIBIT_WARNING_ISSUE, no warnings are issued; +this applies to recursive invocations of call_trapping_problems, too. + +@item +If FLAGS contains POSTPONE_WARNING_ISSUE, no warnings are issued; +but values useful for generating a warning are still computed (in +particular, the backtrace), so that the calling function can issue +a warning. + +@item +If FLAGS contains ISSUE_WARNINGS_AT_DEBUG_LEVEL, warnings will be +issued, but at level @code{debug}, which normally is below the minimum +specified by @code{log-warning-minimum-level}, meaning such warnings will +be ignored entirely. The user can change this variable, however, +to see the warnings.) + +Note: If neither of NO_INHIBIT_THROWS or NO_INHIBIT_ERRORS is +given, you are @strong{guaranteed} that there will be no non-local exits +out of this function. + +@item +If FLAGS contains INHIBIT_QUIT, QUIT using C-g is inhibited. (This +is @strong{rarely} a good idea. Unless you use NO_INHIBIT_ERRORS, QUIT is +automatically caught as well, and treated as an error; you can +check for this using EQ (problems->error_conditions, Qquit). + +@item +If FLAGS contains UNINHIBIT_QUIT, QUIT checking will be explicitly +turned on. (It will abort the code being called, but will still be +trapped and reported as an error, unless NO_INHIBIT_ERRORS is +given.) This is useful when QUIT checking has been turned off by a +higher-level caller. + +@item +If FLAGS contains INHIBIT_GC, garbage collection is inhibited. +This is useful for Lisp called within redisplay, for example. + +@item +If FLAGS contains INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION, +Lisp code is not allowed to delete any window, buffers, frames, devices, +or consoles that were already in existence at the time this function +was called. (However, it's perfectly legal for code to create a new +buffer and then delete it.) + +#### It might be useful to have a flag that inhibits deletion of a +specific permanent display object and everything it's attached to +(e.g. a window, and the buffer, frame, device, and console it's +attached to. + +@item +If FLAGS contains INHIBIT_EXISTING_BUFFER_TEXT_MODIFICATION, Lisp +code is not allowed to modify the text of any buffers that were +already in existence at the time this function was called. +(However, it's perfectly legal for code to create a new buffer and +then modify its text.) + +@quotation +[These last two flags are implemented using global variables +Vdeletable_permanent_display_objects and Vmodifiable_buffers, +which keep track of a list of all buffers or permanent display +objects created since the last time one of these flags was set. +The code that deletes buffers, etc. and modifies buffers checks + +@enumerate +@item +if the corresponding flag is set (through the global variable +inhibit_flags or its accessor function get_inhibit_flags()), and + +@item +if the object to be modified or deleted is not in the +appropriate list. +@end enumerate + +If so, it signals an error. + +Recursive calls to call_trapping_problems() are allowed. In +the case of the two flags mentioned above, the current values +of the global variables are stored in an unwind-protect, and +they're reset to nil.] +@end quotation + +@item +If FLAGS contains INHIBIT_ENTERING_DEBUGGER, the debugger will not +be entered if an error occurs inside the Lisp code being called, +even when the user has requested an error. In such case, a warning +is issued stating that access to the debugger is denied, unless +INHIBIT_WARNING_ISSUE has also been supplied. This is useful when +calling Lisp code inside redisplay, in menu callbacks, etc. because +in such cases either the display is in an inconsistent state or +doing window operations is explicitly forbidden by the OS, and the +debugger would causes visual changes on the screen and might create +another frame. + +@item +If FLAGS contains INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY, no +changes of any sort to extents, faces, glyphs, buffer text, +specifiers relating to display, other variables relating to +display, splitting, deleting, or resizing windows or frames, +deleting buffers, windows, frames, devices, or consoles, etc. is +allowed. This is for things called absolutely in the middle of +redisplay, which expects things to be @strong{exactly} the same after the +call as before. This isn't completely implemented and needs to be +thought out some more to determine exactly what its semantics are. +For the moment, turning on this flag also turns on + +@itemize @minus +@item +INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION +@item +INHIBIT_EXISTING_BUFFER_TEXT_MODIFICATION +@item +INHIBIT_ENTERING_DEBUGGER +@item +INHIBIT_WARNING_ISSUE +@item +INHIBIT_GC +@end itemize + +@item +#### The following five flags are defined, but unimplemented: + +#define INHIBIT_EXISTING_CODING_SYSTEM_DELETION (1<<6) +#define INHIBIT_EXISTING_CHARSET_DELETION (1<<7) +#define INHIBIT_PERMANENT_DISPLAY_OBJECT_CREATION (1<<8) +#define INHIBIT_CODING_SYSTEM_CREATION (1<<9) +#define INHIBIT_CHARSET_CREATION (1<<10) + +@item +FLAGS containing CALL_WITH_SUSPENDED_ERRORS is a sign that +call_with_suspended_errors() was invoked. This exists only for +debugging purposes -- often we want to break when a signal happens, +but ignore signals from call_with_suspended_errors(), because they +occur often and for legitimate reasons. +@end itemize + +If PROBLEM is non-zero, it should be a pointer to a structure into +which exact information about any occurring problems (either an +error or an attempted throw past this boundary). + +If a problem occurred and aborted operation (error, quit, or +invalid throw), Qunbound is returned. Otherwise the return value +from the call to (*fun) (arg) is returned. + +@node Symbols and Variables, Buffers, Evaluation; Stack Frames; Bindings, Top +@chapter Symbols and Variables +@cindex symbols and variables +@cindex variables, symbols and + +@menu +* Introduction to Symbols:: +* Obarrays:: +* Symbol Values:: +@end menu + +@node Introduction to Symbols, Obarrays, Symbols and Variables, Symbols and Variables +@section Introduction to Symbols +@cindex symbols, introduction to + + A symbol is basically just an object with four fields: a name (a +string), a value (some Lisp object), a function (some Lisp object), and +a property list (usually a list of alternating keyword/value pairs). +What makes symbols special is that there is usually only one symbol with +a given name, and the symbol is referred to by name. This makes a +symbol a convenient way of calling up data by name, i.e. of implementing +variables. (The variable's value is stored in the @dfn{value slot}.) +Similarly, functions are referenced by name, and the definition of the +function is stored in a symbol's @dfn{function slot}. This means that +there can be a distinct function and variable with the same name. The +property list is used as a more general mechanism of associating +additional values with particular names, and once again the namespace is +independent of the function and variable namespaces. + +@node Obarrays, Symbol Values, Introduction to Symbols, Symbols and Variables +@section Obarrays +@cindex obarrays + + The identity of symbols with their names is accomplished through a +structure called an obarray, which is just a poorly-implemented hash +table mapping from strings to symbols whose name is that string. (I say +``poorly implemented'' because an obarray appears in Lisp as a vector +with some hidden fields rather than as its own opaque type. This is an +Emacs Lisp artifact that should be fixed.) + + Obarrays are implemented as a vector of some fixed size (which should +be a prime for best results), where each ``bucket'' of the vector +contains one or more symbols, threaded through a hidden @code{next} +field in the symbol. Lookup of a symbol in an obarray, and adding a +symbol to an obarray, is accomplished through standard hash-table +techniques. + + The standard Lisp function for working with symbols and obarrays is +@code{intern}. This looks up a symbol in an obarray given its name; if +it's not found, a new symbol is automatically created with the specified +name, added to the obarray, and returned. This is what happens when the +Lisp reader encounters a symbol (or more precisely, encounters the name +of a symbol) in some text that it is reading. There is a standard +obarray called @code{obarray} that is used for this purpose, although +the Lisp programmer is free to create his own obarrays and @code{intern} +symbols in them. + + Note that, once a symbol is in an obarray, it stays there until +something is done about it, and the standard obarray @code{obarray} +always stays around, so once you use any particular variable name, a +corresponding symbol will stay around in @code{obarray} until you exit +XEmacs. + + Note that @code{obarray} itself is a variable, and as such there is a +symbol in @code{obarray} whose name is @code{"obarray"} and which +contains @code{obarray} as its value. + + Note also that this call to @code{intern} occurs only when in the Lisp +reader, not when the code is executed (at which point the symbol is +already around, stored as such in the definition of the function). + + You can create your own obarray using @code{make-vector} (this is +horrible but is an artifact) and intern symbols into that obarray. +Doing that will result in two or more symbols with the same name. +However, at most one of these symbols is in the standard @code{obarray}: +You cannot have two symbols of the same name in any particular obarray. +Note that you cannot add a symbol to an obarray in any fashion other +than using @code{intern}: i.e. you can't take an existing symbol and put +it in an existing obarray. Nor can you change the name of an existing +symbol. (Since obarrays are vectors, you can violate the consistency of +things by storing directly into the vector, but let's ignore that +possibility.) + + Usually symbols are created by @code{intern}, but if you really want, +you can explicitly create a symbol using @code{make-symbol}, giving it +some name. The resulting symbol is not in any obarray (i.e. it is +@dfn{uninterned}), and you can't add it to any obarray. Therefore its +primary purpose is as a symbol to use in macros to avoid namespace +pollution. It can also be used as a carrier of information, but cons +cells could probably be used just as well. + + You can also use @code{intern-soft} to look up a symbol but not create +a new one, and @code{unintern} to remove a symbol from an obarray. This +returns the removed symbol. (Remember: You can't put the symbol back +into any obarray.) Finally, @code{mapatoms} maps over all of the symbols +in an obarray. + +@node Symbol Values, , Obarrays, Symbols and Variables +@section Symbol Values +@cindex symbol values +@cindex values, symbol + + The value field of a symbol normally contains a Lisp object. However, +a symbol can be @dfn{unbound}, meaning that it logically has no value. +This is internally indicated by storing a special Lisp object, called +@dfn{the unbound marker} and stored in the global variable +@code{Qunbound}. The unbound marker is of a special Lisp object type +called @dfn{symbol-value-magic}. It is impossible for the Lisp +programmer to directly create or access any object of this type. + + @strong{You must not let any ``symbol-value-magic'' object escape to +the Lisp level.} Printing any of these objects will cause the message +@samp{INTERNAL EMACS BUG} to appear as part of the print representation. +(You may see this normally when you call @code{debug_print()} from the +debugger on a Lisp object.) If you let one of these objects escape to +the Lisp level, you will violate a number of assumptions contained in +the C code and make the unbound marker not function right. + + When a symbol is created, its value field (and function field) are set +to @code{Qunbound}. The Lisp programmer can restore these conditions +later using @code{makunbound} or @code{fmakunbound}, and can query to +see whether the value of function fields are @dfn{bound} (i.e. have a +value other than @code{Qunbound}) using @code{boundp} and +@code{fboundp}. The fields are set to a normal Lisp object using +@code{set} (or @code{setq}) and @code{fset}. + + Other symbol-value-magic objects are used as special markers to +indicate variables that have non-normal properties. This includes any +variables that are tied into C variables (setting the variable magically +sets some global variable in the C code, and likewise for retrieving the +variable's value), variables that magically tie into slots in the +current buffer, variables that are buffer-local, etc. The +symbol-value-magic object is stored in the value cell in place of +a normal object, and the code to retrieve a symbol's value +(i.e. @code{symbol-value}) knows how to do special things with them. +This means that you should not just fetch the value cell directly if you +want a symbol's value. + + The exact workings of this are rather complex and involved and are +well-documented in comments in @file{buffer.c}, @file{symbols.c}, and +@file{lisp.h}. + +@node Buffers, Text, Symbols and Variables, Top +@chapter Buffers +@cindex buffers + +@menu +* Introduction to Buffers:: A buffer holds a block of text such as a file. +* Buffer Lists:: Keeping track of all buffers. +* Markers and Extents:: Tagging locations within a buffer. +* The Buffer Object:: The Lisp object corresponding to a buffer. +@end menu + +@node Introduction to Buffers, Buffer Lists, Buffers, Buffers +@section Introduction to Buffers +@cindex buffers, introduction to + + A buffer is logically just a Lisp object that holds some text. +In this, it is like a string, but a buffer is optimized for +frequent insertion and deletion, while a string is not. Furthermore: + +@enumerate +@item +Buffers are @dfn{permanent} objects, i.e. once you create them, they +remain around, and need to be explicitly deleted before they go away. +@item +Each buffer has a unique name, which is a string. Buffers are +normally referred to by name. In this respect, they are like +symbols. +@item +Buffers have a default insertion position, called @dfn{point}. +Inserting text (unless you explicitly give a position) goes at point, +and moves point forward past the text. This is what is going on when +you type text into Emacs. +@item +Buffers have lots of extra properties associated with them. +@item +Buffers can be @dfn{displayed}. What this means is that there +exist a number of @dfn{windows}, which are objects that correspond +to some visible section of your display, and each window has +an associated buffer, and the current contents of the buffer +are shown in that section of the display. The redisplay mechanism +(which takes care of doing this) knows how to look at the +text of a buffer and come up with some reasonable way of displaying +this. Many of the properties of a buffer control how the +buffer's text is displayed. +@item +One buffer is distinguished and called the @dfn{current buffer}. It is +stored in the variable @code{current_buffer}. Buffer operations operate +on this buffer by default. When you are typing text into a buffer, the +buffer you are typing into is always @code{current_buffer}. Switching +to a different window changes the current buffer. Note that Lisp code +can temporarily change the current buffer using @code{set-buffer} (often +enclosed in a @code{save-excursion} so that the former current buffer +gets restored when the code is finished). However, calling +@code{set-buffer} will NOT cause a permanent change in the current +buffer. The reason for this is that the top-level event loop sets +@code{current_buffer} to the buffer of the selected window, each time +it finishes executing a user command. +@end enumerate + + Make sure you understand the distinction between @dfn{current buffer} +and @dfn{buffer of the selected window}, and the distinction between +@dfn{point} of the current buffer and @dfn{window-point} of the selected +window. (This latter distinction is explained in detail in the section +on windows.) + +@node Buffer Lists, Markers and Extents, Introduction to Buffers, Buffers +@section Buffer Lists +@cindex buffer lists + + Recall earlier that buffers are @dfn{permanent} objects, i.e. that +they remain around until explicitly deleted. This entails that there is +a list of all the buffers in existence. This list is actually an +assoc-list (mapping from the buffer's name to the buffer) and is stored +in the global variable @code{Vbuffer_alist}. + + The order of the buffers in the list is important: the buffers are +ordered approximately from most-recently-used to least-recently-used. +Switching to a buffer using @code{switch-to-buffer}, +@code{pop-to-buffer}, etc. and switching windows using +@code{other-window}, etc. usually brings the new current buffer to the +front of the list. @code{switch-to-buffer}, @code{other-buffer}, +etc. look at the beginning of the list to find an alternative buffer to +suggest. You can also explicitly move a buffer to the end of the list +using @code{bury-buffer}. + + In addition to the global ordering in @code{Vbuffer_alist}, each frame +has its own ordering of the list. These lists always contain the same +elements as in @code{Vbuffer_alist} although possibly in a different +order. @code{buffer-list} normally returns the list for the selected +frame. This allows you to work in separate frames without things +interfering with each other. + + The standard way to look up a buffer given a name is +@code{get-buffer}, and the standard way to create a new buffer is +@code{get-buffer-create}, which looks up a buffer with a given name, +creating a new one if necessary. These operations correspond exactly +with the symbol operations @code{intern-soft} and @code{intern}, +respectively. You can also force a new buffer to be created using +@code{generate-new-buffer}, which takes a name and (if necessary) makes +a unique name from this by appending a number, and then creates the +buffer. This is basically like the symbol operation @code{gensym}. + +@node Markers and Extents, The Buffer Object, Buffer Lists, Buffers +@section Markers and Extents +@cindex markers and extents +@cindex extents, markers and + + Among the things associated with a buffer are things that are +logically attached to certain buffer positions. This can be used to +keep track of a buffer position when text is inserted and deleted, so +that it remains at the same spot relative to the text around it; to +assign properties to particular sections of text; etc. There are two +such objects that are useful in this regard: they are @dfn{markers} and +@dfn{extents}. + + A @dfn{marker} is simply a flag placed at a particular buffer +position, which is moved around as text is inserted and deleted. +Markers are used for all sorts of purposes, such as the @code{mark} that +is the other end of textual regions to be cut, copied, etc. + + An @dfn{extent} is similar to two markers plus some associated +properties, and is used to keep track of regions in a buffer as text is +inserted and deleted, and to add properties (e.g. fonts) to particular +regions of text. The external interface of extents is explained +elsewhere. + + The important thing here is that markers and extents simply contain +buffer positions in them as integers, and every time text is inserted or +deleted, these positions must be updated. In order to minimize the +amount of shuffling that needs to be done, the positions in markers and +extents (there's one per marker, two per extent) are stored in Membpos's. +This means that they only need to be moved when the text is physically +moved in memory; since the gap structure tries to minimize this, it also +minimizes the number of marker and extent indices that need to be +adjusted. Look in @file{insdel.c} for the details of how this works. + + One other important distinction is that markers are @dfn{temporary} +while extents are @dfn{permanent}. This means that markers disappear as +soon as there are no more pointers to them, and correspondingly, there +is no way to determine what markers are in a buffer if you are just +given the buffer. Extents remain in a buffer until they are detached +(which could happen as a result of text being deleted) or the buffer is +deleted, and primitives do exist to enumerate the extents in a buffer. + +@node The Buffer Object, , Markers and Extents, Buffers +@section The Buffer Object +@cindex buffer object, the +@cindex object, the buffer + + Buffers contain fields not directly accessible by the Lisp programmer. +We describe them here, naming them by the names used in the C code. +Many are accessible indirectly in Lisp programs via Lisp primitives. + +@table @code +@item name +The buffer name is a string that names the buffer. It is guaranteed to +be unique. @xref{Buffer Names,,, lispref, XEmacs Lisp Reference +Manual}. + +@item save_modified +This field contains the time when the buffer was last saved, as an +integer. @xref{Buffer Modification,,, lispref, XEmacs Lisp Reference +Manual}. + +@item modtime +This field contains the modification time of the visited file. It is +set when the file is written or read. Every time the buffer is written +to the file, this field is compared to the modification time of the +file. @xref{Buffer Modification,,, lispref, XEmacs Lisp Reference +Manual}. + +@item auto_save_modified +This field contains the time when the buffer was last auto-saved. + +@item last_window_start +This field contains the @code{window-start} position in the buffer as of +the last time the buffer was displayed in a window. + +@item undo_list +This field points to the buffer's undo list. @xref{Undo,,, lispref, +XEmacs Lisp Reference Manual}. + +@item syntax_table_v +This field contains the syntax table for the buffer. @xref{Syntax +Tables,,, lispref, XEmacs Lisp Reference Manual}. + +@item downcase_table +This field contains the conversion table for converting text to lower +case. @xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}. + +@item upcase_table +This field contains the conversion table for converting text to upper +case. @xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}. + +@item case_canon_table +This field contains the conversion table for canonicalizing text for +case-folding search. @xref{Case Tables,,, lispref, XEmacs Lisp +Reference Manual}. + +@item case_eqv_table +This field contains the equivalence table for case-folding search. +@xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}. + +@item display_table +This field contains the buffer's display table, or @code{nil} if it +doesn't have one. @xref{Display Tables,,, lispref, XEmacs Lisp +Reference Manual}. + +@item markers +This field contains the chain of all markers that currently point into +the buffer. Deletion of text in the buffer, and motion of the buffer's +gap, must check each of these markers and perhaps update it. +@xref{Markers,,, lispref, XEmacs Lisp Reference Manual}. + +@item backed_up +This field is a flag that tells whether a backup file has been made for +the visited file of this buffer. + +@item mark +This field contains the mark for the buffer. The mark is a marker, +hence it is also included on the list @code{markers}. @xref{The Mark,,, +lispref, XEmacs Lisp Reference Manual}. + +@item mark_active +This field is non-@code{nil} if the buffer's mark is active. + +@item local_var_alist +This field contains the association list describing the variables local +in this buffer, and their values, with the exception of local variables +that have special slots in the buffer object. (Those slots are omitted +from this table.) @xref{Buffer-Local Variables,,, lispref, XEmacs Lisp +Reference Manual}. + +@item modeline_format +This field contains a Lisp object which controls how to display the mode +line for this buffer. @xref{Modeline Format,,, lispref, XEmacs Lisp +Reference Manual}. + +@item base_buffer +This field holds the buffer's base buffer (if it is an indirect buffer), +or @code{nil}. +@end table + +@node Text, Multilingual Support, Buffers, Top +@chapter Text +@cindex text + +@menu +* The Text in a Buffer:: Representation of the text in a buffer. +* Ibytes and Ichars:: Representation of individual characters. +* Byte-Char Position Conversion:: +* Searching and Matching:: Higher-level algorithms. +@end menu + +@node The Text in a Buffer, Ibytes and Ichars, Text, Text +@section The Text in a Buffer +@cindex text in a buffer, the +@cindex buffer, the text in a + + The text in a buffer consists of a sequence of zero or more +characters. A @dfn{character} is an integer that logically represents +a letter, number, space, or other unit of text. Most of the characters +that you will typically encounter belong to the ASCII set of characters, +but there are also characters for various sorts of accented letters, +special symbols, Chinese and Japanese ideograms (i.e. Kanji, Katakana, +etc.), Cyrillic and Greek letters, etc. The actual number of possible +characters is quite large. + + For now, we can view a character as some non-negative integer that +has some shape that defines how it typically appears (e.g. as an +uppercase A). (The exact way in which a character appears depends on the +font used to display the character.) The internal type of characters in +the C code is an @code{Ichar}; this is just an @code{int}, but using a +symbolic type makes the code clearer. + + Between every character in a buffer is a @dfn{buffer position} or +@dfn{character position}. We can speak of the character before or after +a particular buffer position, and when you insert a character at a +particular position, all characters after that position end up at new +positions. When we speak of the character @dfn{at} a position, we +really mean the character after the position. (This schizophrenia +between a buffer position being ``between'' two characters and ``on'' a +character is rampant in Emacs.) + + Buffer positions are numbered starting at 1. This means that +position 1 is before the first character, and position 0 is not +valid. If there are N characters in a buffer, then buffer +position N+1 is after the last one, and position N+2 is not valid. + + The internal makeup of the Ichar integer varies depending on whether +we have compiled with MULE support. If not, the Ichar integer is an +8-bit integer with possible values from 0 - 255. 0 - 127 are the +standard ASCII characters, while 128 - 255 are the characters from the +ISO-8859-1 character set. If we have compiled with MULE support, an +Ichar is a 19-bit integer, with the various bits having meanings +according to a complex scheme that will be detailed later. The +characters numbered 0 - 255 still have the same meanings as for the +non-MULE case, though. + + Internally, the text in a buffer is represented in a fairly simple +fashion: as a contiguous array of bytes, with a @dfn{gap} of some size +in the middle. Although the gap is of some substantial size in bytes, +there is no text contained within it: From the perspective of the text +in the buffer, it does not exist. The gap logically sits at some buffer +position, between two characters (or possibly at the beginning or end of +the buffer). Insertion of text in a buffer at a particular position is +always accomplished by first moving the gap to that position +(i.e. through some block moving of text), then writing the text into the +beginning of the gap, thereby shrinking the gap. If the gap shrinks +down to nothing, a new gap is created. (What actually happens is that a +new gap is ``created'' at the end of the buffer's text, which requires +nothing more than changing a couple of indices; then the gap is +``moved'' to the position where the insertion needs to take place by +moving up in memory all the text after that position.) Similarly, +deletion occurs by moving the gap to the place where the text is to be +deleted, and then simply expanding the gap to include the deleted text. +(@dfn{Expanding} and @dfn{shrinking} the gap as just described means +just that the internal indices that keep track of where the gap is +located are changed.) + + Note that the total amount of memory allocated for a buffer text never +decreases while the buffer is live. Therefore, if you load up a +20-megabyte file and then delete all but one character, there will be a +20-megabyte gap, which won't get any smaller (except by inserting +characters back again). Once the buffer is killed, the memory allocated +for the buffer text will be freed, but it will still be sitting on the +heap, taking up virtual memory, and will not be released back to the +operating system. (However, if you have compiled XEmacs with rel-alloc, +the situation is different. In this case, the space @emph{will} be +released back to the operating system. However, this tends to result in a +noticeable speed penalty.) + + Astute readers may notice that the text in a buffer is represented as +an array of @emph{bytes}, while (at least in the MULE case) an Ichar is +a 19-bit integer, which clearly cannot fit in a byte. This means (of +course) that the text in a buffer uses a different representation from +an Ichar: specifically, the 19-bit Ichar becomes a series of one to +four bytes. The conversion between these two representations is complex +and will be described later. + + In the non-MULE case, everything is very simple: An Ichar +is an 8-bit value, which fits neatly into one byte. + + If we are given a buffer position and want to retrieve the +character at that position, we need to follow these steps: + +@enumerate +@item +Pretend there's no gap, and convert the buffer position into a @dfn{byte +index} that indexes to the appropriate byte in the buffer's stream of +textual bytes. By convention, byte indices begin at 1, just like buffer +positions. In the non-MULE case, byte indices and buffer positions are +identical, since one character equals one byte. +@item +Convert the byte index into a @dfn{memory index}, which takes the gap +into account. The memory index is a direct index into the block of +memory that stores the text of a buffer. This basically just involves +checking to see if the byte index is past the gap, and if so, adding the +size of the gap to it. By convention, memory indices begin at 1, just +like buffer positions and byte indices, and when referring to the +position that is @dfn{at} the gap, we always use the memory position at +the @emph{beginning}, not at the end, of the gap. +@item +Fetch the appropriate bytes at the determined memory position. +@item +Convert these bytes into an Ichar. +@end enumerate + + In the non-Mule case, (3) and (4) boil down to a simple one-byte +memory access. + + Note that we have defined three types of positions in a buffer: + +@enumerate +@item +@dfn{buffer positions} or @dfn{character positions}, typedef @code{Charbpos} +@item +@dfn{byte indices}, typedef @code{Bytebpos} +@item +@dfn{memory indices}, typedef @code{Membpos} +@end enumerate + + All three typedefs are just @code{int}s, but defining them this way makes +things a lot clearer. + + Most code works with buffer positions. In particular, all Lisp code +that refers to text in a buffer uses buffer positions. Lisp code does +not know that byte indices or memory indices exist. + + Finally, we have a typedef for the bytes in a buffer. This is a +@code{Ibyte}, which is an unsigned char. Referring to them as +Ibytes underscores the fact that we are working with a string of bytes +in the internal Emacs buffer representation rather than in one of a +number of possible alternative representations (e.g. EUC-encoded text, +etc.). + +@node Ibytes and Ichars, Byte-Char Position Conversion, The Text in a Buffer, Text +@section Ibytes and Ichars +@cindex Ibytes and Ichars +@cindex Ichars, Ibytes and + + Not yet documented. + +@node Byte-Char Position Conversion, Searching and Matching, Ibytes and Ichars, Text +@section Byte-Char Position Conversion +@cindex byte-char position conversion +@cindex position conversion, byte-char +@cindex conversion, byte-char position + +Oct 2004: + +This is what I wrote when describing the previous algorithm: + +@quotation +The basic algorithm we use is to keep track of a known region of +characters in each buffer, all of which are of the same width. We keep +track of the boundaries of the region in both Charbpos and Bytebpos +coordinates and also keep track of the char width, which is 1 - 4 bytes. +If the position we're translating is not in the known region, then we +invoke a function to update the known region to surround the position in +question. This assumes locality of reference, which is usually the +case. + +Note that the function to update the known region can be simple or +complicated depending on how much information we cache. In addition to +the known region, we always cache the correct conversions for point, +BEGV, and ZV, and in addition to this we cache 16 positions where the +conversion is known. We only look in the cache or update it when we +need to move the known region more than a certain amount (currently 50 +chars), and then we throw away a "random" value and replace it with the +newly calculated value. + +Finally, we maintain an extra flag that tracks whether the buffer is +entirely ASCII, to speed up the conversions even more. This flag is +actually of dubious value because in an entirely-ASCII buffer the known +region will always span the entire buffer (in fact, we update the flag +based on this fact), and so all we're saving is a few machine cycles. + +A potentially smarter method than what we do with known regions and +cached positions would be to keep some sort of pseudo-extent layer over +the buffer; maybe keep track of the charbpos/bytebpos correspondence at +the beginning of each line, which would allow us to do a binary search +over the pseudo-extents to narrow things down to the correct line, at +which point you could use a linear movement method. This would also +mesh well with efficiently implementing a line-numbering scheme. +However, you have to weigh the amount of time spent updating the cache +vs. the savings that result from it. In reality, we modify the buffer +far less often than we access it, so a cache of this sort that provides +guaranteed LOG (N) performance (or perhaps N * LOG (N), if we set a +maximum on the cache size) would indeed be a win, particularly in very +large buffers. If we ever implement this, we should probably set a +reasonably high minimum below which we use the old method, because the +time spent updating the fancy cache would likely become dominant when +making buffer modifications in smaller buffers. + +Note also that we have to multiply or divide by the char width in order +to convert the positions. We do some tricks to avoid ever actually +having to do a multiply or divide, because that is typically an +expensive operation (esp. divide). Multiplying or dividing by 1, 2, or +4 can be implemented simply as a shift left or shift right, and we keep +track of a shifter value (0, 1, or 2) indicating how much to shift. +Multiplying by 3 can be implemented by doubling and then adding the +original value. Dividing by 3, alas, cannot be implemented in any +simple shift/subtract method, as far as I know; so we just do a table +lookup. For simplicity, we use a table of size 128K, which indexes the +"divide-by-3" values for the first 64K non-negative numbers. (Note that +we can increase the size up to 384K, i.e. indexing the first 192K +non-negative numbers, while still using shorts in the array.) This also +means that the size of the known region can be at most 64K for +width-three characters. +@end quotation + +Unfortunately, it turned out that the implementation had serious problems +which had never been corrected. In particular, the known region had a +large tendency to become zero-length and stay that way. + +So I decided to port the algorithm from FSF 21.3, in markers.c. + +This algorithm is fairly simple. Instead of using markers I kept the cache +array of known positions from the previous implementation. + +Basically, we keep a number of positions cached: + +@itemize @bullet +@item +the actual end of the buffer +@item +the beginning and end of the accessible region +@item +the value of point +@item +the position of the gap +@item +the last value we computed +@item +a set of positions that are "far away" from previously computed positions +(5000 chars currently; #### perhaps should be smaller) +@end itemize + +For each position, we @code{CONSIDER()} it. This means: + +@itemize @bullet +@item +If the position is what we're looking for, return it directly. +@item +Starting with the beginning and end of the buffer, we successively +compute the smallest enclosing range of known positions. If at any +point we discover that this range has the same byte and char length +(i.e. is entirely single-byte), then our computation is trivial. +@item +If at any point we get a small enough range (50 chars currently), +stop considering further positions. +@end itemize + +Otherwise, once we have an enclosing range, see which side is closer, and +iterate until we find the desired value. As an optimization, I replaced +the simple loop in FSF with the use of @code{bytecount_to_charcount()}, +@code{charcount_to_bytecount()}, @code{bytecount_to_charcount_down()}, or +@code{charcount_to_bytecount_down()}. (The latter two I added for this purpose.) +These scan 4 or 8 bytes at a time through purely single-byte characters. + +If the amount we had to scan was more than our "far away" distance (5000 +characters, see above), then cache the new position. + +#### Things to do: + +@itemize @bullet +@item +Look at the most recent GNU Emacs to see whether anything has changed. +@item +Think about whether it makes sense to try to implement some sort of +known region or list of "known regions", like we had before. This would +be a region of entirely single-byte characters that we can check very +quickly. (Previously I used a range of same-width characters of any +size; but this adds extra complexity and slows down the scanning, and is +probably not worth it.) As part of the scanning process in +@code{bytecount_to_charcount()} et al, we skip over chunks of entirely +single-byte chars, so it should be easy to remember the last one. +Presumably what we should do is keep track of the largest known surrounding +entirely-single-byte region for each of the cache positions as well as +perhaps the last-cached position. We want to be careful not to get bitten +by the previous problem of having the known region getting reset too +often. If we implement this, we might well want to continue scanning +some distance past the desired position (maybe 300-1000 bytes) if we are +in a single-byte range so that we won't end up expanding the known range +one position at a time and entering the function each time. +@item +Think about whether it makes sense to keep the position cache sorted. +This would allow it to be larger and finer-grained in its positions. +Note that with FSF's use of markers, they were sorted, but this +was not really made good use of. With an array, we can do binary searching +to quickly find the smallest range. We would probably want to make use of +the gap-array code in extents.c. +@end itemize + +Note that FSF's algorithm checked @strong{ALL} markers, not just the ones cached +by this algorithm. This includes markers created by the user as well as +both ends of any overlays. We could do similarly, and our extents could +keep both byte and character positions rather than just the former. (But +this would probably be overkill. We should just use our cache instead. +Any place an extent was set was surely already visited by the char<-->byte +conversion routines.) + +@node Searching and Matching, , Byte-Char Position Conversion, Text +@section Searching and Matching +@cindex searching +@cindex matching + +Very incomplete, limited to a brief introduction. + +People find the searching and matching code difficult to understand. +And indeed, the details are hard. However, the basic structures are not +so complex. First, there's a hard question with a simple answer. What +about Mule? The answer here is that it turns out that Mule characters +can be matched byte by byte, so neither the search code nor the regular +expression code need take much notice of it at all! Of course, we add +some special features (such as regular expressions that match only +certain charsets), but these do not require new concepts. The main +exception is that wild-card matches in Mule have to be careful to +swallow whole characters. This is handled using the same basic macros +that are used for buffer and string movements. + +This will also be true if a UTF-8 representation is used for the +internal encoding. + +The complex algorithms for searching are for simple string searches. In +particular, the algorithm used for fast string searching is Boyer-Moore. +This algorithm is based on the idea that if you have a mismatch at a +given position, you can precompute where to restart the search. This +typically means that you can often make many fewer than N character +comparisons, where N is the position at which the match is found, or the +size of the text if it contains no match. That's fast! But it's not +easy. You must ``compile'' the search string into a jump table. See +the source, @file{search.c}, for more information. + +Emacs changes the basic algorithms somewhat in order to handle +case-insensitive searches without a full-blown regular expression. + +Regular expressions, on the other hand, have a trivial search +implementation: try a match at each position. (Under POSIX rules, it's +a bit more complex, because POSIX requires that you find the +@emph{longest} match in the text. This means you keep a record of the +best match so far, and find all the matches.) + +The matching code for regular expressions is quite complex. First, the +regular expression itself is compiled. There are two basic approaches +that could be taken. The first is to compile the expression into tables +to drive a generic finite automaton emulator. This is the approach +given in many textbooks (Sedgewick's @emph{Algorithms} and Aho, Sethi, +and Ullmann's @emph{Compilers: Principles, Techniques, and Tools}, aka +``The Dragon Book'') as well as being used by the @file{lex} family of +lexical analysis engines. + +Emacs uses a somewhat different technique. The expression is compiled +into a form of bytecode, which is interpreted by a special interpreter. +The interpreter itself basically amounts to an inline implementation of +the finite automaton emulator. The advantage of this technique is that +it's easier to add special features, such as control of case-sensitivity +via a global variable. + +The compiler is not treated here. See the source, @file{regex.c}. The +interpreter, although it is divided into several functions, and looks +fearsomely complex, is actually quite simple in concept. However, +basically what you're doing there is a strcmp on steroids, right? + +@example +int +strcmp (char *p, /* pattern pointer */ + char *b) /* buffer pointer */ +@{ + while (*p++ == *b++) + ; + return *(--p) - *(--b); /* oops, we overshot */ +@} +@end example + +Really, it's no harder than that. (A bit of a white lie, OK?) + +How does the regexp code generalize this? + +@enumerate +@item +Depending on the pattern, @code{*b} may have a general relationship to +@code{*p}. @emph{I.e.}, direct comparison against @code{*p} is +generalized to include checks for set membership, and context dependent +properties. This depends on @code{&*b}. Of course that's meaningless +in C, so we use @code{b} directly, instead. + +@item +Although to ensure the algorithm terminates, @code{b} must advance step +by step, @code{p} can branch and jump. + +@item +The information returned is much greater, including information about +subexpressions. +@end enumerate + +We'll ignore (3). (2) is mostly interesting when compiling the regular +expression. Now we have + +@example +@group +enum operator_t @{ + accept = 0, + exact, + any, + range, + group, /* actually, these are probably */ + repeat, /* turned into conditional code */ + /* etc */ +@}; +@end group + +@group +enum status_t @{ + working = 0, + matched, + mismatch, + end_of_buffer, + error + @}; +@end group + +@group +struct pattern @{ + enum operator_t operator; + char char_value; + boolean range_table[256]; + /* etc, etc */ + @}; +@end group + +@group +char *p, /* pattern pointer */ + *b; /* buffer pointer */ + +enum status_t +match (struct pattern *p, char *b) +@{ + enum status_t done = working; + + while (!(done = match_1_operator (p, b))) + @{ + struct pattern *p1 = p; + p = next_p (p, b); + b = next_b (p1, b); + @} + return done; +@} +@end group +@end example + +This format exposes the underlying finite automaton. + +All of them have the following structure, except that the @samp{next_*} +functions decide where to jump (for @samp{p}) and whether or not to +increment (for @samp{b}), rather than checking for satisfaction of a +matching condition. + +@example +enum status_t +match_1_operator (pattern *p, char *b) +@{ + if (! *b) return end_of_buffer; + switch (p->operator) + @{ + case accept: + return matched; + case exact: + if (*b != p->char_value) return mismatch; else break; + case any: + break; + case range: + /* range_table is computed in the regexp_compile function */ + if (! p->range_table[*b]) return mismatch; + /* etc, etc */ + @} + return working; +@} +@end example + +Grouping, repetition, and alternation are handled by compiling the +subexpression and calling @code{match (p->subpattern, b)} recursively. + +In terms of reading the actual code, there are five optimizations +(obfuscations, if you like) that have been done. + +@enumerate +@item +An explicit "failure stack" has been substituted for recursion. + +@item +The @code{match_1_operator}, @code{next_p}, and @code{next_b} functions +are actually inlined into the @code{match} function for efficiency. +Then the pointer movement is interspersed with the matching operations. + +@item +If the operator uses buffer context, the buffer pointer movement is +sometimes implicit in the operations retrieving the context. + +@item +Some cases are combined into short preparation for individual cases, and +a "fall-through" into combined code for several cases. + +@item +The @code{pattern} type is not an explicit @samp{struct}. Instead, the +data (including, @emph{e.g.}, @samp{range_table}) is inlined into the +compiled bytecode. This leads to bizarre code in the interpreter like + +@example +case range: + p += *(p + 1); break; +@end example + +in @code{next_p}, because the compiled pattern is laid out + +@example +..., 'range', count, first_8_flags, second_8_flags, ..., next_op, ... +@end example +@end enumerate + +But if you keep your eye on the "switch in a loop" structure, you +should be able to understand the parts you need. + +@node Multilingual Support, Consoles; Devices; Frames; Windows, Text, Top +@chapter Multilingual Support +@cindex Mule character sets and encodings +@cindex character sets and encodings, Mule +@cindex encodings, Mule character sets and + +@emph{NOTE}: There is a great deal of overlapping and redundant +information in this chapter. Ben wrote introductions to Mule issues a +number of times, each time not realizing that he had already written +another introduction previously. Hopefully, in time these will all be +integrated. + + @emph{NOTE}: The information at the top of the source file +@file{text.c} is more complete than the following, and there is also a +list of all other places to look for text/I18N-related info. Also look in +@file{text.h} for info about the DFC and Eistring API's. + + Recall that there are two primary ways that text is represented in +XEmacs. The @dfn{buffer} representation sees the text as a series of +bytes (Ibytes), with a variable number of bytes used per character. +The @dfn{character} representation sees the text as a series of integers +(Ichars), one per character. The character representation is a cleaner +representation from a theoretical standpoint, and is thus used in many +cases when lots of manipulations on a string need to be done. However, +the buffer representation is the standard representation used in both +Lisp strings and buffers, and because of this, it is the ``default'' +representation that text comes in. The reason for using this +representation is that it's compact and is compatible with ASCII. + +@menu +* Introduction to Multilingual Issues #1:: +* Introduction to Multilingual Issues #2:: +* Introduction to Multilingual Issues #3:: +* Introduction to Multilingual Issues #4:: +* Character Sets:: +* Encodings:: +* Internal Mule Encodings:: +* Byte/Character Types; Buffer Positions; Other Typedefs:: +* Internal Text API's:: +* Coding for Mule:: +* CCL:: +* Microsoft Windows-Related Multilingual Issues:: +* Modules for Internationalization:: +@end menu + +@node Introduction to Multilingual Issues #1, Introduction to Multilingual Issues #2, Multilingual Support, Multilingual Support +@section Introduction to Multilingual Issues #1 +@cindex introduction to multilingual issues #1 + +There is an introduction to these issues in the Lisp Reference manual. +@xref{Internationalization Terminology,,, lispref, XEmacs Lisp Reference +Manual}. Among other documentation that may be of interest to internals +programmers is ISO-2022 (@pxref{ISO 2022,,, lispref, XEmacs Lisp +Reference Manual}) and CCL (@pxref{CCL,,, lispref, XEmacs Lisp Reference +Manual}) + +@node Introduction to Multilingual Issues #2, Introduction to Multilingual Issues #3, Introduction to Multilingual Issues #1, Multilingual Support +@section Introduction to Multilingual Issues #2 +@cindex introduction to multilingual issues #2 + +@subheading Introduction + +This document covers a number of design issues, problems and proposals +with regards to XEmacs MULE. At first we present some definitions and +some aspects of the design that have been agreed upon. Then we present +some issues and problems that need to be addressed, and then I include a +proposal of mine to address some of these issues. When there are other +proposals, for example from Olivier, these will be appended to the end +of this document. + +@subheading Definitions and Design Basics + +First, @dfn{text} is defined to be a series of characters which together +defines an utterance or partial utterance in some language. +Generally, this language is a human language, but it may also be a +computer language if the computer language uses a representation close +enough to that of human languages for it to also make sense to call its +representation text. Text is opposed to @dfn{binary}, which is a sequence +of bytes, representing machine-readable but not human-readable data. +A @dfn{byte} is merely a number within a predefined range, which nowadays is +nearly always zero to 255. A @dfn{character} is a unit of text. What makes +one character different from another is not always clear-cut. It is +generally related to the appearance of the character, although perhaps +not any possible appearance of that character, but some sort of ideal +appearance that is assigned to a character. Whether two characters +that look very similar are actually the same depends on various +factors such as political ones, such as whether the characters are +used to mean similar sorts of things, or behave similarly in similar +contexts. In any case, it is not always clearly defined whether two +characters are actually the same or not. In practice, however, this +is more or less agreed upon. + +A @dfn{character set} is just that, a set of one or more characters. +The set is unique in that there will not be more than one instance of +the same character in a character set, and logically is unordered, +although an order is often imposed or suggested for the characters in +the character set. We can also define an @dfn{order} on a character +set, which is a way of assigning a unique number, or possibly a pair of +numbers, or a triplet of numbers, or even a set of four or more numbers +to each character in the character set. The combination of an order in +the character set results in an @dfn{ordered character set}. In an +ordered character set, there is an upper limit and a lower limit on the +possible values that a character, or that any number within the set of +numbers assigned to a character, can take. However, the lower limit +does not have to start at zero or one, or anywhere else in particular, +nor does the upper limit have to end anywhere particular, and there may +be gaps within these ranges such that particular numbers or sets of +numbers do not have a corresponding character, even though they are +within the upper and lower limits. For example, @dfn{ASCII} defines a +very standard ordered character set. It is normally defined to be 94 +characters in the range 33 through 126 inclusive on both ends, with +every possible character within this range being actually present in the +character set. + +Sometimes the ASCII character set is extended to include what are called +@dfn{non-printing characters}. Non-printing characters are characters +which instead of really being displayed in a more or less rectangular +block, like all other characters, instead indicate certain functions +typically related to either control of the display upon which the +characters are being displayed, or have some effect on a communications +channel that may be currently open and transmitting characters, or may +change the meaning of future characters as they are being decoded, or +some other similar function. You might say that non-printing characters +are somewhat of a hack because they are a special exception to the +standard concept of a character as being a printed glyph that has some +direct correspondence in the non-computer world. + +With non-printing characters in mind, the 94-character ordered character +set called ASCII is often extended into a 96-character ordered character +set, also often called ASCII, which includes in addition to the 94 +characters already mentioned, two non-printing characters, one called +space and assigned the number 32, just below the bottom of the previous +range, and another called @dfn{delete} or @dfn{rubout}, which is given +number 127 just above the end of the previous range. Thus to reiterate, +the result is a 96-character ordered character set, whose characters +take the values from 32 to 127 inclusive. Sometimes ASCII is further +extended to contain 32 more non-printing characters, which are given the +numbers zero through 31 so that the result is a 128-character ordered +character set with characters numbered zero through 127, and with many +non-printing characters. Another way to look at this, and the way that +is normally taken by XEmacs MULE, is that the characters that would be +in the range 30 through 31 in the most extended definition of ASCII, +instead form their own ordered character set, which is called +@dfn{control zero}, and consists of 32 characters in the range zero +through 31. A similar ordered character set called @dfn{control one} is +also created, and it contains 32 more non-printing characters in the +range 128 through 159. Note that none of these three ordered character +sets overlaps in any of the numbers they are assigned to their +characters, so they can all be used at once. Note further that the same +character can occur in more than one character set. This was shown +above, for example, in two different ordered character sets we defined, +one of which we could have called @dfn{ASCII}, and the other +@dfn{ASCII-extended}, to show that it had extended by two non-printable +characters. Most of the characters in these two character sets are +shared and present in both of them. + +Note that there is no restriction on the size of the character set, or +on the numbers that are assigned to characters in an ordered character +set. It is often extremely useful to represent a sequence of characters +as a sequence of bytes, where a byte as defined above is a number in the +range zero to 255. An @dfn{encoding} does precisely this. It is simply +a mapping from a sequence of characters, possibly augmented with +information indicating the character set that each of these characters +belongs to, to a sequence of bytes which represents that sequence of +characters and no other -- which is to say the mapping is reversible. + +A @dfn{coding system} is a set of rules for encoding a sequence of +characters augmented with character set information into a sequence of +bytes, and later performing the reverse operation. It is frequently +possible to group coding systems into classes or types based on common +features. Typically, for example, a particular coding system class +may contain a base coding system which specifies some of the rules, +but leaves the rest unspecified. Individual members of the coding +system class are formed by starting with the base coding system, and +augmenting it with additional rules to produce a particular coding +system, what you might think of as a sort of variation within a +theme. + +@subheading XEmacs Specific Definitions + +First of all, in XEmacs, the concept of character is a little different +from the general definition given above. For one thing, the character +set that a character belongs to may or may not be an inherent part of +the character itself. In other words, the same character occurring in +two different character sets may appear in XEmacs as two different +characters. This is generally the case now, but we are attempting to +move in the other direction. Different proposals may have different +ideas about exactly the extent to which this change will be carried out. +The general trend, though, is to represent all information about a +character other than the character itself, using text properties +attached to the character. That way two instances of the same character +will look the same to lisp code that merely retrieves the character, and +does not also look at the text properties of that character. Everyone +involved is in agreement in doing it this way with all Latin characters, +and in fact for all characters other than Chinese, Japanese, and Korean +ideographs. For those, there may be a difference of opinion. + +A second difference between the general definition of character and the +XEmacs usage of character is that each character is assigned a unique +number that distinguishes it from all other characters in the world, or +at the very least, from all other characters currently existing anywhere +inside the current XEmacs invocation. (If there is a case where the +weaker statement applies, but not the stronger statement, it would +possibly be with composite characters and any other such characters that +are created on the sly.) + +This unique number is called the @dfn{character representation} of the +character, and its particular details are a matter of debate. There is +the current standard in use that it is undoubtedly going to change. +What has definitely been agreed upon is that it will be an integer, more +specifically a positive integer, represented with less than or equal to +31 bits on a 32-bit architecture, and possibly up to 63 bits on a 64-bit +architecture, with the proviso that any characters that whose +representation would fit in a 64-bit architecture, but not on a 32-bit +architecture, would be used only for composite characters, and others +that would satisfy the weak uniqueness property mentioned above, but not +with the strong uniqueness property. + +At this point, it is useful to talk about the different representations +that a sequence of characters can take. The simplest representation is +simply as a sequence of characters, and this is called the @dfn{Lisp +representation} of text, because it is the representation that Lisp +programs see. Other representations include the external +representation, which refers to any encoding of the sequence of +characters, using the definition of encoding mentioned above. +Typically, text in the external representation is used outside of +XEmacs, for example in files, e-mail messages, web sites, and the like. +Another representation for a sequence of characters is what I will call +the @dfn{byte representation}, and it represents the way that XEmacs +internally represents text in a buffer, or in a string. Potentially, +the representation could be different between a buffer and a string, and +then the terms @dfn{buffer byte representation} and @dfn{string byte +representation} would be used, but in practice I don't think this will +occur. It will be possible, of course, for buffers and strings, or +particular buffers and particular strings, to contain different +sub-representations of a single representation. For example, Olivier's +1-2-4 proposal allows for three sub-representations of his internal byte +representation, allowing for 1 byte, 2 bytes, and 4 byte width +characters respectively. A particular string may be in one +sub-representation, and a particular buffer in another +sub-representation, but overall both are following the same byte +representation. I do not use the term @dfn{internal representation} +here, as many people have, because it is potentially ambiguous. + +Another representation is called the @dfn{array of characters +representation}. This is a representation on the C-level in which the +sequence of text is represented, not using the byte representation, but +by using an array of characters, each represented using the character +representation. This sort of representation is often used by redisplay +because it is more convenient to work with than any of the other +internal representations. + +The term @dfn{binary representation} may also be heard. Binary +representation is used to represent binary data. When binary data is +represented in the lisp representation, an equivalence is simply set up +between bytes zero through 255, and characters zero through 255. These +characters come from four character sets, which are from bottom to top, +control zero, ASCII, control 1, and Latin 1. Together, they comprise +256 characters, and are a good mapping for the 256 possible bytes in a +binary representation. Binary representation could also be used to +refer to an external representation of the binary data, which is a +simple direct byte-to-byte representation. No internal representation +should ever be referred to as a binary representation because of +ambiguity. The terms character set/encoding system were defined +generally, above. In XEmacs, the equivalent concepts exist, although +character set has been shortened to charset, and in fact represents +specifically an ordered character set. For each possible charset, and +for each possible coding system, there is an associated object in +XEmacs. These objects will be of type charset and coding system, +respectively. Charsets and coding systems are divided into classes, or +@dfn{types}, the normal term under XEmacs, and all possible charsets +encoding systems that may be defined must be in one of these types. If +you need to create a charset or coding system that is not one of these +types, you will have to modify the C code to support this new type. +Some of the existing or soon-to-be-created types are, or will be, +generic enough so that this shouldn't be an issue. Note also that the +byte encoding for text and the character coding of a character are +closely related. You might say that ideally each is the simplest +equivalent of the other given the general constraints on each +representation. + +To be specific, in the current MULE representation, + +@enumerate +@item +Characters encode both the character itself and the character set +that it comes from. These character sets are always assumed to be +representable as an ordered character set of size 96 or of size 96 +by 96, or the trivially-related sizes 94 and 94 by 94. The only +allowable exceptions are the control zero and control one character +sets, which are of size 32. Character sets which do not naturally +have a compatible ordering such as this are shoehorned into an +ordered character set, or possibly two ordered character sets of a +compatible size. +@item +The variable width byte representation was deliberately chosen to +allow scanning text forwards and backwards efficiently. This +necessitated defining the possible bytes into three ranges which +we shall call A, B, and C. Range A is used exclusively for +single-byte characters, which is to say characters that are +representing using only one contiguous byte. Multi-byte +characters are always represented by using one byte from Range B, +followed by one or more bytes from Range C. What this means is +that bytes that begin a character are unequivocally distinguished +from bytes that do not begin a character, and therefore there is +never a problem scaling backwards and finding the beginning of a +character. Know that UTF8 adopts a proposal that is very similar +in spirit in that it uses separate ranges for the first byte of a +multi byte sequence, and the following bytes in multi-byte +sequence. +@item +Given the fact that all ordered character sets allowed were +essentially 96 characters per dimension, it made perfect sense to +make Range C comprise 96 bytes. With a little more tweaking, the +currently-standard MULE byte representation was created, and was +drafted from this. +@item +The MULE byte representation defined four basic representations for +characters, which would take up from one to four bytes, +respectively. The MULE character representation thus had the +following constraints: +@enumerate +@item +Character numbers zero through 255 should represent the +characters that binary values zero through 255 would be +mapped onto. (Note: this was not the case in Kenichi Handa's +version of this representation, but I changed it.) +@item +The four sub-classes of representation in the MULE byte +representation should correspond to four contiguous +non-overlapping ranges of characters. +@item +The algorithmic conversion between the single character +represented in the byte representation and in the character +representation should be as easy as possible. +@item +Given the previous constraints, the character representation +should be as compact as possible, which is to say it should +use the least number of bits possible. +@end enumerate +@end enumerate + +So you see that the entire structure of the byte and character +representations stemmed from a very small number of basic choices, +which were + +@enumerate +@item +the choice to encode character set information in a character +@item +the choice to assume that all character sets would have an order +imposed upon them with 96 characters per one or two +dimensions. (This is less arbitrary than it seems--it follows +ISO-2022) +@item +the choice to use a variable width byte representation. +@end enumerate + +What this means is that you cannot really separate the byte +representation, the character representation, and the assumptions made +about characters and whether they represent character sets from each +other. All of these are closely intertwined, and for purposes of +simplicity, they should be designed together. If you change one +representation without changing another, you are in essence creating a +completely new design with its own attendant problems--since your new +design is likely to be quite complex and not very coherent with +regards to the translation between the character and byte +representations, you are likely to run into problems. + +@node Introduction to Multilingual Issues #3, Introduction to Multilingual Issues #4, Introduction to Multilingual Issues #2, Multilingual Support +@section Introduction to Multilingual Issues #3 +@cindex introduction to multilingual issues #3 + +In XEmacs, Mule is a code word for the support for input handling and +display of multi-lingual text. This section provides an overview of how +this support impacts the C and Lisp code in XEmacs. It is important for +anyone who works on the C or the Lisp code, especially on the C code, to +be aware of these issues, even if they don't work directly on code that +implements multi-lingual features, because there are various general +procedures that need to be followed in order to write Mule-compliant +code. (The specifics of these procedures are documented elsewhere in +this manual.) + +There are four primary aspects of Mule support: + +@enumerate +@item +internal handling and representation of multi-lingual text. +@item +conversion between the internal representation of text and the various +external representations in which multi-lingual text is encoded, such as +Unicode representations (including mostly fixed width encodings such as +UCS-2/UTF-16 and UCS-4 and variable width ASCII conformant encodings, +such as UTF-7 and UTF-8); the various ISO2022 representations, which +typically use escape sequences to switch between different character +sets (such as Compound Text, used under X Windows; JIS, used +specifically for encoding Japanese; and EUC, a non-modal encoding used +for Japanese, Korean, and certain other languages); Microsoft's +multi-byte encodings (such as Shift-JIS); various simple encodings for +particular 8-bit character sets (such as Latin-1 and Latin-2, and +encodings (such as koi8 and Alternativny) for Cyrillic); and others. +This conversion needs to happen both for text in files and text sent to +or retrieved from system API calls. It even needs to happen for +external binary data because the internal representation does not +represent binary data simply as a sequence of bytes as it is represented +externally. +@item +Proper display of multi-lingual characters. +@item +Input of multi-lingual text using the keyboard. +@end enumerate + +These four aspects are for the most part independent of each other. + +@subheading Characters, Character Sets, and Encodings + +A @dfn{character} (which is, BTW, a surprisingly complex concept) is, in +a written representation of text, the most basic written unit that has a +meaning of its own. It's comparable to a phoneme when analyzing words +in spoken speech (for example, the sound of @samp{t} in English, which +in fact has different pronunciations in different words -- aspirated in +@samp{time}, unaspirated in @samp{stop}, unreleased or even pronounced +as a glottal stop in @samp{button}, etc. -- but logically is a single +concept). Like a phoneme, a character is an abstract concept defined by +its @emph{meaning}. The character @samp{lowercase f}, for example, can +always be used to represent the first letter in the word @samp{fill}, +regardless of whether it's drawn upright or italic, whether the +@samp{fi} combination is drawn as a single ligature, whether there are +serifs on the bottom of the vertical stroke, etc. (These different +appearances of a single character are often called @dfn{graphs} or +@dfn{glyphs}.) Our concern when representing text is on representing the +abstract characters, and not on their exact appearance. + +A @dfn{character set} (or @dfn{charset}), as we define it, is a set of +characters, each with an associated number (or set of numbers -- see +below), called a @dfn{code point}. It's important to understand that a +character is not defined by any number attached to it, but by its +meaning. For example, ASCII and EBCDIC are two charsets containing +exactly the same characters (lowercase and uppercase letters, numbers 0 +through 9, particular punctuation marks) but with different +numberings. The `comma' character in ASCII and EBCDIC, for instance, is +the same character despite having a different numbering. Conversely, +when comparing ASCII and JIS-Roman, which look the same except that the +latter has a yen sign substituted for the backslash, we would say that +the backslash and yen sign are @strong{not} the same characters, despite having +the same number (95) and despite the fact that all other characters are +present in both charsets, with the same numbering. ASCII and JIS-Roman, +then, do @emph{not} have exactly the same characters in them (ASCII has +a backslash character but no yen-sign character, and vice-versa for +JIS-Roman), unlike ASCII and EBCDIC, even though the numberings in ASCII +and JIS-Roman are closer. + +It's also important to distinguish between charsets and encodings. For +a simple charset like ASCII, there is only one encoding normally used -- +each character is represented by a single byte, with the same value as +its code point. For more complicated charsets, however, things are not +so obvious. Unicode version 2, for example, is a large charset with +thousands of characters, each indexed by a 16-bit number, often +represented in hex, e.g. 0x05D0 for the Hebrew letter "aleph". One +obvious encoding uses two bytes per character (actually two encodings, +depending on which of the two possible byte orderings is chosen). This +encoding is convenient for internal processing of Unicode text; however, +it's incompatible with ASCII, so a different encoding, e.g. UTF-8, is +usually used for external text, for example files or e-mail. UTF-8 +represents Unicode characters with one to three bytes (often extended to +six bytes to handle characters with up to 31-bit indices). Unicode +characters 00 to 7F (identical with ASCII) are directly represented with +one byte, and other characters with two or more bytes, each in the range +80 to FF. + +In general, a single encoding may be able to represent more than one +charset. + +@subheading Internal Representation of Text + +In an ASCII or single-European-character-set world, life is very simple. +There are 256 characters, and each character is represented using the +numbers 0 through 255, which fit into a single byte. With a few +exceptions (such as case-changing operations or syntax classes like +'whitespace'), "text" is simply an array of indices into a font. You +can get different languages simply by choosing fonts with different +8-bit character sets (ISO-8859-1, -2, special-symbol fonts, etc.), and +everything will "just work" as long as anyone else receiving your text +uses a compatible font. + +In the multi-lingual world, however, it is much more complicated. There +are a great number of different characters which are organized in a +complex fashion into various character sets. The representation to use +is not obvious because there are issues of size versus speed to +consider. In fact, there are in general two kinds of representations to +work with: one that represents a single character using an integer +(possibly a byte), and the other representing a single character as a +sequence of bytes. The former representation is normally called fixed +width, and the other variable width. Both representations represent +exactly the same characters, and the conversion from one representation +to the other is governed by a specific formula (rather than by table +lookup) but it may not be simple. Most C code need not, and in fact +should not, know the specifics of exactly how the representations work. +In fact, the code must not make assumptions about the representations. +This means in particular that it must use the proper macros for +retrieving the character at a particular memory location, determining +how many characters are present in a particular stretch of text, and +incrementing a pointer to a particular character to point to the +following character, and so on. It must not assume that one character +is stored using one byte, or even using any particular number of bytes. +It must not assume that the number of characters in a stretch of text +bears any particular relation to a number of bytes in that stretch. It +must not assume that the character at a particular memory location can +be retrieved simply by dereferencing the memory location, even if a +character is known to be ASCII or is being compared with an ASCII +character, etc. Careful coding is required to be Mule clean. The +biggest work of adding Mule support, in fact, is converting all of the +existing code to be Mule clean. + +Lisp code is mostly unaffected by these concerns. Text in strings and +buffers appears simply as a sequence of characters regardless of +whether Mule support is present. The biggest difference with older +versions of Emacs, as well as current versions of GNU Emacs, is that +integers and characters are no longer equivalent, but are separate +Lisp Object types. + +@subheading Conversion Between Internal and External Representations + +All text needs to be converted to an external representation before being +sent to a function or file, and all text retrieved from a function of +file needs to be converted to the internal representation. This +conversion needs to happen as close to the source or destination of the +text as possible. No operations should ever be performed on text encoded +in an external representation other than simple copying, because no +assumptions can reliably be made about the format of this text. You +cannot assume, for example, that the end of text is terminated by a null +byte. (For example, if the text is Unicode, it will have many null bytes +in it.) You cannot find the next "slash" character by searching through +the bytes until you find a byte that looks like a "slash" character, +because it might actually be the second byte of a Kanji character. +Furthermore, all text in the internal representation must be converted, +even if it is known to be completely ASCII, because the external +representation may not be ASCII compatible (for example, if it is +Unicode). + +The place where C code needs to be the most careful is when calling +external API functions. It is easy to forget that all text passed to or +retrieved from these functions needs to be converted. This includes text +in structures passed to or retrieved from these functions and all text +that is passed to a callback function that is called by the system. + +Macros are provided to perform conversions to or from external text. +These macros are called TO_EXTERNAL_FORMAT and TO_INTERNAL_FORMAT +respectively. These macros accept input in various forms, for example, +Lisp strings, buffers, lstreams, raw data, and can return data in +multiple formats, including both @code{malloc()}ed and @code{alloca()}ed data. The use +of @code{alloca()}ed data here is particularly important because, in general, +the returned data will not be used after making the API call, and as a +result, using @code{alloca()}ed data provides a very cheap and easy to use +method of allocation. + +These macros take a coding system argument which indicates the nature of +the external encoding. A coding system is an object that encapsulates +the structures of a particular external encoding and the methods required +to convert to and from this encoding. A facility exists to create coding +system aliases, which in essence gives a single coding system two +different names. It is effectively used in XEmacs to provide a layer of +abstraction on top of the actual coding systems. For example, the coding +system alias "file-name" points to whichever coding system is currently +used for encoding and decoding file names as passed to or retrieved from +system calls. In general, the actual encoding will differ from system to +system, and also on the particular locale that the user is in. The use +of the file-name alias effectively hides that implementation detail on +top of that abstract interface layer which provides a unified set of +coding systems which are consistent across all operating environments. + +The choice of which coding system to use in a particular conversion macro +requires some thought. In general, you should choose a lower-level +actual coding system when the very design of the APIs you are working +with call for that particular coding system. In all other cases, you +should find the least general abstract coding system (i.e. coding system +alias) that applies to your specific situation. Only use the most +general coding systems, such as native, when there is simply nothing else +that is more appropriate. By doing things this way, you allow the user +more control over how the encoding actually works, because the user is +free to map the abstracted coding system names onto to different actual +coding systems. + +Some common coding systems are: + +@table @code +@item ctext +Compound Text, which is the standard encoding under X Windows, which is +used for clipboard data and possibly other data. (ctext is a coding +system of type ISO2022.) + +@item mswindows-unicode +this is used for representing text passed to MS Window API calls with +arguments that need to be in Unicode format. (mswindows-unicode is a +coding system of type UTF-16) + +@item ms-windows-multi-byte +this is used for representing text passed to MS Windows API calls with +arguments that need to be in multi-byte format. Note that there are +very few if any examples of such calls. + +@item mswindows-tstr +this is used for representing text passed to any MS Windows API calls +that declare their argument as LPTSTR, or LPCTSTR. This is the vast +majority of system calls and automatically translates either to +mswindows-unicode or mswindows-multi-byte, depending on the presence or +absence of the UNICODE preprocessor constant. (If we compile XEmacs +with this preprocessor constant, then all API calls use Unicode for all +text passed to or received from these API calls.) + +@item terminal +used for text sent to or read from a text terminal in the absence of a +more specific coding system (calls to window-system specific APIs should +use the appropriate window-specific coding system if it makes sense to +do so.) + +@item file-name +used when specifying the names of files in the absence of a more +specific encoding, such as ms-windows-tstr. + +@item native +the most general coding system for specifying text passed to system +calls. This generally translates to whatever coding system is specified +by the current locale. This should only be used when none of the coding +systems mentioned above are appropriate. +@end table + +@subheading Proper Display of Multilingual Text + +There are two things required to get this working correctly. One is +selecting the correct font, and the other is encoding the text according +to the encoding used for that specific font, or the window-system +specific text display API. Generally each separate character set has a +different font associated with it, which is specified by name and each +font has an associated encoding into which the characters must be +translated. (this is the case on X Windows, at least; on Windows there +is a more general mechanism). Both the specific font for a charset and +the encoding of that font are system dependent. Currently there is a +way of specifying these two properties under X Windows (using the +registry and ccl properties of a character set) but not for other window +systems. A more general system needs to be implemented to allow these +characteristics to be specified for all Windows systems. + +Another issue is making sure that the necessary fonts for displaying +various character sets are installed on the system. Currently, XEmacs +provides, on its web site, X Windows fonts for a number of different +character sets that can be installed by users. This isn't done yet for +Windows, but it should be. + +@subheading Inputting of Multilingual Text + +This is a rather complicated issue because there are many paradigms +defined for inputting multi-lingual text, some of which are specific to +particular languages, and any particular language may have many +different paradigms defined for inputting its text. These paradigms are +encoded in input methods and there is a standard API for defining an +input method in XEmacs called LEIM, or Library of Emacs Input Methods. +Some of these input methods are written entirely in Elisp, and thus are +system-independent, while others require the aid either of an external +process, or of C level support that ties into a particular +system-specific input method API, for example, XIM under X Windows, or +the active keyboard layout and IME support under Windows. Currently, +there is no support for any system-specific input methods under +Microsoft Windows, although this will change. + +@node Introduction to Multilingual Issues #4, Character Sets, Introduction to Multilingual Issues #3, Multilingual Support +@section Introduction to Multilingual Issues #4 +@cindex introduction to multilingual issues #4 + +The rest of the sections in this chapter consist of yet another +introduction to multilingual issues, duplicating the information in the +previous sections. + +@node Character Sets, Encodings, Introduction to Multilingual Issues #4, Multilingual Support +@section Character Sets +@cindex character sets + + A @dfn{character set} (or @dfn{charset}) is an ordered set of +characters. A particular character in a charset is indexed using one or +more @dfn{position codes}, which are non-negative integers. The number +of position codes needed to identify a particular character in a charset +is called the @dfn{dimension} of the charset. In XEmacs/Mule, all +charsets have dimension 1 or 2, and the size of all charsets (except for +a few special cases) is either 94, 96, 94 by 94, or 96 by 96. The range +of position codes used to index characters from any of these types of +character sets is as follows: + +@example +Charset type Position code 1 Position code 2 +------------------------------------------------------------ +94 33 - 126 N/A +96 32 - 127 N/A +94x94 33 - 126 33 - 126 +96x96 32 - 127 32 - 127 +@end example + + Note that in the above cases position codes do not start at an +expected value such as 0 or 1. The reason for this will become clear +later. + + For example, Latin-1 is a 96-character charset, and JISX0208 (the +Japanese national character set) is a 94x94-character charset. + + [Note that, although the ranges above define the @emph{valid} position +codes for a charset, some of the slots in a particular charset may in +fact be empty. This is the case for JISX0208, for example, where (e.g.) +all the slots whose first position code is in the range 118 - 127 are +empty.] + + There are three charsets that do not follow the above rules. All of +them have one dimension, and have ranges of position codes as follows: + +@example +Charset name Position code 1 +------------------------------------ +ASCII 0 - 127 +Control-1 0 - 31 +Composite 0 - some large number +@end example + + (The upper bound of the position code for composite characters has not +yet been determined, but it will probably be at least 16,383). + + ASCII is the union of two subsidiary character sets: Printing-ASCII +(the printing ASCII character set, consisting of position codes 33 - +126, like for a standard 94-character charset) and Control-ASCII (the +non-printing characters that would appear in a binary file with codes 0 +- 32 and 127). + + Control-1 contains the non-printing characters that would appear in a +binary file with codes 128 - 159. + + Composite contains characters that are generated by overstriking one +or more characters from other charsets. + + Note that some characters in ASCII, and all characters in Control-1, +are @dfn{control} (non-printing) characters. These have no printed +representation but instead control some other function of the printing +(e.g. TAB or 8 moves the current character position to the next tab +stop). All other characters in all charsets are @dfn{graphic} +(printing) characters. + + When a binary file is read in, the bytes in the file are assigned to +character sets as follows: + +@example +Bytes Character set Range +-------------------------------------------------- +0 - 127 ASCII 0 - 127 +128 - 159 Control-1 0 - 31 +160 - 255 Latin-1 32 - 127 +@end example + + This is a bit ad-hoc but gets the job done. + +@node Encodings, Internal Mule Encodings, Character Sets, Multilingual Support +@section Encodings +@cindex encodings, Mule +@cindex Mule encodings + + An @dfn{encoding} is a way of numerically representing characters from +one or more character sets. If an encoding only encompasses one +character set, then the position codes for the characters in that +character set could be used directly. This is not possible, however, if +more than one character set is to be used in the encoding. + + For example, the conversion detailed above between bytes in a binary +file and characters is effectively an encoding that encompasses the +three character sets ASCII, Control-1, and Latin-1 in a stream of 8-bit +bytes. + + Thus, an encoding can be viewed as a way of encoding characters from a +specified group of character sets using a stream of bytes, each of which +contains a fixed number of bits (but not necessarily 8, as in the common +usage of ``byte''). + + Here are descriptions of a couple of common +encodings: + +@menu +* Japanese EUC (Extended Unix Code):: +* JIS7:: +@end menu + +@node Japanese EUC (Extended Unix Code), JIS7, Encodings, Encodings +@subsection Japanese EUC (Extended Unix Code) +@cindex Japanese EUC (Extended Unix Code) +@cindex EUC (Extended Unix Code), Japanese +@cindex Extended Unix Code, Japanese EUC + +This encompasses the character sets Printing-ASCII, Katakana-JISX0201 +(half-width katakana, the right half of JISX0201), Japanese-JISX0208, +and Japanese-JISX0212. + +Note that Printing-ASCII and Katakana-JISX0201 are 94-character +charsets, while Japanese-JISX0208 and Japanese-JISX0212 are +94x94-character charsets. + +The encoding is as follows: + +@example +Character set Representation (PC=position-code) +------------- -------------- +Printing-ASCII PC1 +Katakana-JISX0201 0x8E | PC1 + 0x80 +Japanese-JISX0208 PC1 + 0x80 | PC2 + 0x80 +Japanese-JISX0212 PC1 + 0x80 | PC2 + 0x80 +@end example + +Note that there are other versions of EUC for other Asian languages. +EUC in general is characterized by + +@enumerate +@item +row-column encoding, +@item +big-endian (row-first) ordering, and +@item +ASCII compatibility in variable width forms. +@end enumerate + +@node JIS7, , Japanese EUC (Extended Unix Code), Encodings +@subsection JIS7 +@cindex JIS7 + +This encompasses the character sets Printing-ASCII, +Latin-JISX0201 (the left half of JISX0201; this character set +is very similar to Printing-ASCII and is a 94-character charset), +Japanese-JISX0208, and Katakana-JISX0201. It uses 7-bit bytes. + +Unlike EUC, this is a @dfn{modal} encoding, which means that there are +multiple states that the encoding can be in, which affect how the bytes +are to be interpreted. Special sequences of bytes (called @dfn{escape +sequences}) are used to change states. + + The encoding is as follows: + +@example +Character set Representation (PC=position-code) +------------- -------------- +Printing-ASCII PC1 +Latin-JISX0201 PC1 +Katakana-JISX0201 PC1 +Japanese-JISX0208 PC1 | PC2 + + +Escape sequence ASCII equivalent Meaning +--------------- ---------------- ------- +0x1B 0x28 0x4A ESC ( J invoke Latin-JISX0201 +0x1B 0x28 0x49 ESC ( I invoke Katakana-JISX0201 +0x1B 0x24 0x42 ESC $ B invoke Japanese-JISX0208 +0x1B 0x28 0x42 ESC ( B invoke Printing-ASCII +@end example + + Initially, Printing-ASCII is invoked. + +@node Internal Mule Encodings, Byte/Character Types; Buffer Positions; Other Typedefs, Encodings, Multilingual Support +@section Internal Mule Encodings +@cindex internal Mule encodings +@cindex Mule encodings, internal +@cindex encodings, internal Mule + +In XEmacs/Mule, each character set is assigned a unique number, called a +@dfn{leading byte}. This is used in the encodings of a character. +Leading bytes are in the range 0x80 - 0xFF (except for ASCII, which has +a leading byte of 0), although some leading bytes are reserved. + +Charsets whose leading byte is in the range 0x80 - 0x9F are called +@dfn{official} and are used for built-in charsets. Other charsets are +called @dfn{private} and have leading bytes in the range 0xA0 - 0xFF; +these are user-defined charsets. + + More specifically: + +@example +Character set Leading byte +------------- ------------ +ASCII 0 (0x7F in arrays indexed by leading byte) +Composite 0x8D +Dimension-1 Official 0x80 - 0x8C/0x8D + (0x8E is free) +Control 0x8F +Dimension-2 Official 0x90 - 0x99 + (0x9A - 0x9D are free) +Dimension-1 Private Marker 0x9E +Dimension-2 Private Marker 0x9F +Dimension-1 Private 0xA0 - 0xEF +Dimension-2 Private 0xF0 - 0xFF +@end example + +There are two internal encodings for characters in XEmacs/Mule. One is +called @dfn{string encoding} and is an 8-bit encoding that is used for +representing characters in a buffer or string. It uses 1 to 4 bytes per +character. The other is called @dfn{character encoding} and is a 19-bit +encoding that is used for representing characters individually in a +variable. + +(In the following descriptions, we'll ignore composite characters for +the moment. We also give a general (structural) overview first, +followed later by the exact details.) + +@menu +* Internal String Encoding:: +* Internal Character Encoding:: +@end menu + +@node Internal String Encoding, Internal Character Encoding, Internal Mule Encodings, Internal Mule Encodings +@subsection Internal String Encoding +@cindex internal string encoding +@cindex string encoding, internal +@cindex encoding, internal string + +ASCII characters are encoded using their position code directly. Other +characters are encoded using their leading byte followed by their +position code(s) with the high bit set. Characters in private character +sets have their leading byte prefixed with a @dfn{leading byte prefix}, +which is either 0x9E or 0x9F. (No character sets are ever assigned these +leading bytes.) Specifically: + +@example +Character set Encoding (PC=position-code, LB=leading-byte) +------------- -------- +ASCII PC-1 | +Control-1 LB | PC1 + 0xA0 | +Dimension-1 official LB | PC1 + 0x80 | +Dimension-1 private 0x9E | LB | PC1 + 0x80 | +Dimension-2 official LB | PC1 + 0x80 | PC2 + 0x80 | +Dimension-2 private 0x9F | LB | PC1 + 0x80 | PC2 + 0x80 +@end example + + The basic characteristic of this encoding is that the first byte +of all characters is in the range 0x00 - 0x9F, and the second and +following bytes of all characters is in the range 0xA0 - 0xFF. +This means that it is impossible to get out of sync, or more +specifically: + +@enumerate +@item +Given any byte position, the beginning of the character it is +within can be determined in constant time. +@item +Given any byte position at the beginning of a character, the +beginning of the next character can be determined in constant +time. +@item +Given any byte position at the beginning of a character, the +beginning of the previous character can be determined in constant +time. +@item +Textual searches can simply treat encoded strings as if they +were encoded in a one-byte-per-character fashion rather than +the actual multi-byte encoding. +@end enumerate + + None of the standard non-modal encodings meet all of these +conditions. For example, EUC satisfies only (2) and (3), while +Shift-JIS and Big5 (not yet described) satisfy only (2). (All +non-modal encodings must satisfy (2), in order to be unambiguous.) + +@node Internal Character Encoding, , Internal String Encoding, Internal Mule Encodings +@subsection Internal Character Encoding +@cindex internal character encoding +@cindex character encoding, internal +@cindex encoding, internal character + + One 19-bit word represents a single character. The word is +separated into three fields: + +@example +Bit number: 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + <------------> <------------------> <------------------> +Field: 1 2 3 +@end example + + Note that fields 2 and 3 hold 7 bits each, while field 1 holds 5 bits. + +@example +Character set Field 1 Field 2 Field 3 +------------- ------- ------- ------- +ASCII 0 0 PC1 + range: (00 - 7F) +Control-1 0 1 PC1 + range: (00 - 1F) +Dimension-1 official 0 LB - 0x7F PC1 + range: (01 - 0D) (20 - 7F) +Dimension-1 private 0 LB - 0x80 PC1 + range: (20 - 6F) (20 - 7F) +Dimension-2 official LB - 0x8F PC1 PC2 + range: (01 - 0A) (20 - 7F) (20 - 7F) +Dimension-2 private LB - 0xE1 PC1 PC2 + range: (0F - 1E) (20 - 7F) (20 - 7F) +Composite 0x1F ? ? +@end example + +Note that character codes 0 - 255 are the same as the ``binary +encoding'' described above. + +Most of the code in XEmacs knows nothing of the representation of a +character other than that values 0 - 255 represent ASCII, Control 1, +and Latin 1. + +@strong{WARNING WARNING WARNING}: The Boyer-Moore code in +@file{search.c}, and the code in @code{search_buffer()} that determines +whether that code can be used, knows that ``field 3'' in a character +always corresponds to the last byte in the textual representation of the +character. (This is important because the Boyer-Moore algorithm works by +looking at the last byte of the search string and &&#### finish this. + +@node Byte/Character Types; Buffer Positions; Other Typedefs, Internal Text API's, Internal Mule Encodings, Multilingual Support +@section Byte/Character Types; Buffer Positions; Other Typedefs +@cindex byte/character types; buffer positions; other typedefs +@cindex byte/character types +@cindex character types +@cindex buffer positions +@cindex typedefs, other + +@menu +* Byte Types:: +* Different Ways of Seeing Internal Text:: +* Buffer Positions:: +* Other Typedefs:: +* Usage of the Various Representations:: +* Working With the Various Representations:: +@end menu + +@node Byte Types, Different Ways of Seeing Internal Text, Byte/Character Types; Buffer Positions; Other Typedefs, Byte/Character Types; Buffer Positions; Other Typedefs +@subsection Byte Types +@cindex byte types + +Stuff pointed to by a char * or unsigned char * will nearly always be +one of the following types: + +@itemize @minus +@item +a) [Ibyte] pointer to internally-formatted text +@item +b) [Extbyte] pointer to text in some external format, which can be + defined as all formats other than the internal one +@item +c) [Ascbyte] pure ASCII text +@item +d) [Binbyte] binary data that is not meant to be interpreted as text +@item +e) [Rawbyte] general data in memory, where we don't care about whether + it's text or binary +@item +f) [Boolbyte] a zero or a one +@item +g) [Bitbyte] a byte used for bit fields +@item +h) [Chbyte] null-semantics @code{char *}; used when casting an argument to + an external API where the the other types may not be + appropriate +@end itemize + +Types (b), (c), (f) and (h) are defined as @code{char}, while the others are +@code{unsigned char}. This is for maximum safety (signed characters are +dangerous to work with) while maintaining as much compatibility with +external API's and string constants as possible. + +We also provide versions of the above types defined with different +underlying C types, for API compatibility. These use the following +prefixes: + +@example +C = plain char, when the base type is unsigned +U = unsigned +S = signed +@end example + +(Formerly I had a comment saying that type (e) "should be replaced with +void *". However, there are in fact many places where an unsigned char +* might be used -- e.g. for ease in pointer computation, since void * +doesn't allow this, and for compatibility with external API's.) + +Note that these typedefs are purely for documentation purposes; from +the C code's perspective, they are exactly equivalent to @code{char *}, +@code{unsigned char *}, etc., so you can freely use them with library +functions declared as such. + +Using these more specific types rather than the general ones helps avoid +the confusions that occur when the semantics of a char * or unsigned +char * argument being studied are unclear. Furthermore, by requiring +that ALL uses of @code{char} be replaced with some other type as part of the +Mule-ization process, we can use a search for @code{char} as a way of finding +code that has not been properly Mule-ized yet. + +@node Different Ways of Seeing Internal Text, Buffer Positions, Byte Types, Byte/Character Types; Buffer Positions; Other Typedefs +@subsection Different Ways of Seeing Internal Text +@cindex different ways of seeing internal text + +There are various ways of representing internal text. The two primary +ways are as an "array" of individual characters; the other is as a +"stream" of bytes. In the ASCII world, where there are only 255 +characters at most, things are easy because each character fits into a +byte. In general, however, this is not true -- see the above discussion +of characters vs. encodings. + +In some cases, it's also important to distinguish between a stream +representation as a series of bytes and as a series of textual units. +This is particularly important wrt Unicode. The UTF-16 representation +(sometimes referred to, rather sloppily, as simply the "Unicode" format) +represents text as a series of 16-bit units. Mostly, each unit +corresponds to a single character, but not necessarily, as characters +outside of the range 0-65535 (the BMP or "Basic Multilingual Plane" of +Unicode) require two 16-bit units, through the mechanism of +"surrogates". When a series of 16-bit units is serialized into a byte +stream, there are at least two possible representations, little-endian +and big-endian, and which one is used may depend on the native format of +16-bit integers in the CPU of the machine that XEmacs is running +on. (Similarly, UTF-32 is logically a representation with 32-bit textual +units.) + +Specifically: + +@itemize @minus +@item +UTF-8 has 1-byte (8-bit) units. +@item +UTF-16 has 2-byte (16-bit) units. +@item +UTF-32 has 4-byte (32-bit) units. +@item +XEmacs-internal encoding (the old "Mule" encoding) has 1-byte (8-bit) +units. +@item +UTF-7 technically has 7-bit units that are within the "mail-safe" range +(ASCII 32 - 126 plus a few control characters), but normally is encoded +in an 8-bit stream. (UTF-7 is also a modal encoding, since it has a +normal mode where printable ASCII characters represent themselves and a +shifted mode, introduced with a plus sign, where a base-64 encoding is +used.) +@item +UTF-5 technically has 7-bit units (normally encoded in an 8-bit stream, +like UTF-7), but only uses uppercase A-V and 0-9, and only encodes 4 +bits worth of data per character. UTF-5 is meant for encoding Unicode +inside of DNS names. +@end itemize + +Thus, we can imagine three levels in the representation of texual data: + +@example +series of characters -> series of textual units -> series of bytes + [Ichar] [Itext] [Ibyte] +@end example + +XEmacs has three corresponding typedefs: + +@itemize @minus +@item +An Ichar is an integer (at least 32-bit), representing a 31-bit +character. +@item +An Itext is an unsigned value, either 8, 16 or 32 bits, depending +on the nature of the internal representation, and corresponding to +a single textual unit. +@item +An Ibyte is an @code{unsigned char}, representing a single byte in a +textual byte stream. +@end itemize + +Internal text in stream format can be simultaneously viewed as either +@code{Itext *} or @code{Ibyte *}. The @code{Ibyte *} representation is convenient for +copying data from one place to another, because such routines usually +expect byte counts. However, @code{Itext *} is much better for actually +working with the data. + +From a text-unit perspective, units 0 through 127 will always be ASCII +compatible, and data in Lisp strings (and other textual data generated +as a whole, e.g. from external conversion) will be followed by a +null-unit terminator. From an @code{Ibyte *} perspective, however, the +encoding is only ASCII-compatible if it uses 1-byte units. + +Similarly to the different text representations, three integral count +types exist -- Charcount, Textcount and Bytecount. + +NOTE: Despite the presence of the terminator, internal text itself can +have nulls in it! (Null text units, not just the null bytes present in +any UTF-16 encoding.) The terminator is present because in many cases +internal text is passed to routines that will ultimately pass the text +to library functions that cannot handle embedded nulls, e.g. functions +manipulating filenames, and it is a real hassle to have to pass the +length around constantly. But this can lead to sloppy coding! We need +to be careful about watching for nulls in places that are important, +e.g. manipulating string objects or passing data to/from the clipboard. + +@table @code +@item Ibyte +The data in a buffer or string is logically made up of Ibyte objects, +where a Ibyte takes up the same amount of space as a char. (It is +declared differently, though, to catch invalid usages.) Strings stored +using Ibytes are said to be in "internal format". The important +characteristics of internal format are + +@itemize @minus +@item +ASCII characters are represented as a single Ibyte, in the range 0 - +0x7f. +@item +All other characters are represented as a Ibyte in the range 0x80 - 0x9f +followed by one or more Ibytes in the range 0xa0 to 0xff. +@end itemize + +This leads to a number of desirable properties: + +@itemize @minus +@item +Given the position of the beginning of a character, you can find the +beginning of the next or previous character in constant time. +@item +When searching for a substring or an ASCII character within the string, +you need merely use standard searching routines. +@end itemize + +@item Itext + +#### Document me. + +@item Ichar +This typedef represents a single Emacs character, which can be ASCII, +ISO-8859, or some extended character, as would typically be used for +Kanji. Note that the representation of a character as an Ichar is @strong{not} +the same as the representation of that same character in a string; thus, +you cannot do the standard C trick of passing a pointer to a character +to a function that expects a string. + +An Ichar takes up 19 bits of representation and (for code compatibility +and such) is compatible with an int. This representation is visible on +the Lisp level. The important characteristics of the Ichar +representation are + +@itemize @minus +@item +values 0x00 - 0x7f represent ASCII. +@item +values 0x80 - 0xff represent the right half of ISO-8859-1. +@item +values 0x100 and up represent all other characters. +@end itemize + +This means that Ichar values are upwardly compatible with the standard +8-bit representation of ASCII/ISO-8859-1. + +@item Extbyte +Strings that go in or out of Emacs are in "external format", typedef'ed +as an array of char or a char *. There is more than one external format +(JIS, EUC, etc.) but they all have similar properties. They are modal +encodings, which is to say that the meaning of particular bytes is not +fixed but depends on what "mode" the string is currently in (e.g. bytes +in the range 0 - 0x7f might be interpreted as ASCII, or as Hiragana, or +as 2-byte Kanji, depending on the current mode). The mode starts out in +ASCII/ISO-8859-1 and is switched using escape sequences -- for example, +in the JIS encoding, 'ESC $ B' switches to a mode where pairs of bytes +in the range 0 - 0x7f are interpreted as Kanji characters. + +External-formatted data is generally desirable for passing data between +programs because it is upwardly compatible with standard +ASCII/ISO-8859-1 strings and may require less space than internal +encodings such as the one described above. In addition, some encodings +(e.g. JIS) keep all characters (except the ESC used to switch modes) in +the printing ASCII range 0x20 - 0x7e, which results in a much higher +probability that the data will avoid being garbled in transmission. +Externally-formatted data is generally not very convenient to work with, +however, and for this reason is usually converted to internal format +before any work is done on the string. + +NOTE: filenames need to be in external format so that ISO-8859-1 +characters come out correctly. +@end table + +@node Buffer Positions, Other Typedefs, Different Ways of Seeing Internal Text, Byte/Character Types; Buffer Positions; Other Typedefs +@subsection Buffer Positions +@cindex buffer positions + +There are three possible ways to specify positions in a buffer. All +of these are one-based: the beginning of the buffer is position or +index 1, and 0 is not a valid position. + +As a "buffer position" (typedef Charbpos): + + This is an index specifying an offset in characters from the + beginning of the buffer. Note that buffer positions are + logically @strong{between} characters, not on a character. The + difference between two buffer positions specifies the number of + characters between those positions. Buffer positions are the + only kind of position externally visible to the user. + +As a "byte index" (typedef Bytebpos): + + This is an index over the bytes used to represent the characters + in the buffer. If there is no Mule support, this is identical + to a buffer position, because each character is represented + using one byte. However, with Mule support, many characters + require two or more bytes for their representation, and so a + byte index may be greater than the corresponding buffer + position. + +As a "memory index" (typedef Membpos): + + This is the byte index adjusted for the gap. For positions + before the gap, this is identical to the byte index. For + positions after the gap, this is the byte index plus the gap + size. There are two possible memory indices for the gap + position; the memory index at the beginning of the gap should + always be used, except in code that deals with manipulating the + gap, where both indices may be seen. The address of the + character "at" (i.e. following) a particular position can be + obtained from the formula + + buffer_start_address + memory_index(position) - 1 + + except in the case of characters at the gap position. + +@node Other Typedefs, Usage of the Various Representations, Buffer Positions, Byte/Character Types; Buffer Positions; Other Typedefs +@subsection Other Typedefs +@cindex other typedefs + + Charcount: + ---------- + This typedef represents a count of characters, such as + a character offset into a string or the number of + characters between two positions in a buffer. The + difference between two Charbpos's is a Charcount, and + character positions in a string are represented using + a Charcount. + + Textcount: + ---------- + #### Document me. + + Bytecount: + ---------- + Similar to a Charcount but represents a count of bytes. + The difference between two Bytebpos's is a Bytecount. + + +@node Usage of the Various Representations, Working With the Various Representations, Other Typedefs, Byte/Character Types; Buffer Positions; Other Typedefs +@subsection Usage of the Various Representations +@cindex usage of the various representations + +Memory indices are used in low-level functions in insdel.c and for +extent endpoints and marker positions. The reason for this is that +this way, the extents and markers don't need to be updated for most +insertions, which merely shrink the gap and don't move any +characters around in memory. + +(The beginning-of-gap memory index simplifies insertions w.r.t. +markers, because text usually gets inserted after markers. For +extents, it is merely for consistency, because text can get +inserted either before or after an extent's endpoint depending on +the open/closedness of the endpoint.) + +Byte indices are used in other code that needs to be fast, +such as the searching, redisplay, and extent-manipulation code. + +Buffer positions are used in all other code. This is because this +representation is easiest to work with (especially since Lisp +code always uses buffer positions), necessitates the fewest +changes to existing code, and is the safest (e.g. if the text gets +shifted underneath a buffer position, it will still point to a +character; if text is shifted under a byte index, it might point +to the middle of a character, which would be bad). + +Similarly, Charcounts are used in all code that deals with strings +except for code that needs to be fast, which used Bytecounts. + +Strings are always passed around internally using internal format. +Conversions between external format are performed at the time +that the data goes in or out of Emacs. + +@node Working With the Various Representations, , Usage of the Various Representations, Byte/Character Types; Buffer Positions; Other Typedefs +@subsection Working With the Various Representations +@cindex working with the various representations + +We write things this way because it's very important the +MAX_BYTEBPOS_GAP_SIZE_3 is a multiple of 3. (As it happens, +65535 is a multiple of 3, but this may not always be the +case. #### unfinished + +@node Internal Text API's, Coding for Mule, Byte/Character Types; Buffer Positions; Other Typedefs, Multilingual Support +@section Internal Text API's +@cindex internal text API's +@cindex text API's, internal +@cindex API's, text, internal + +@strong{NOTE}: The most current documentation for these API's is in +@file{text.h}. In case of error, assume that file is correct and this +one wrong. + +@menu +* Basic internal-format API's:: +* The DFC API:: +* The Eistring API:: +@end menu + +@node Basic internal-format API's, The DFC API, Internal Text API's, Internal Text API's +@subsection Basic internal-format API's +@cindex basic internal-format API's +@cindex internal-format API's, basic +@cindex API's, basic internal-format + +These are simple functions and macros to convert between text +representation and characters, move forward and back in text, etc. + +#### Finish the rest of this. + +Use the following functions/macros on contiguous text in any of the +internal formats. Those that take a format arg work on all internal +formats; the others work only on the default (variable-width under Mule) +format. If the text you're operating on is known to come from a buffer, +use the buffer-level functions in buffer.h, which automatically know the +correct format and handle the gap. + +Some terminology: + +"itext" appearing in the macros means "internal-format text" -- type +@code{Ibyte *}. Operations on such pointers themselves, rather than on the +text being pointed to, have "itext" instead of "itext" in the macro +name. "ichar" in the macro names means an Ichar -- the representation +of a character as a single integer rather than a series of bytes, as part +of "itext". Many of the macros below are for converting between the +two representations of characters. + +Note also that we try to consistently distinguish between an "Ichar" and +a Lisp character. Stuff working with Lisp characters often just says +"char", so we consistently use "Ichar" when that's what we're working +with. + +@node The DFC API, The Eistring API, Basic internal-format API's, Internal Text API's +@subsection The DFC API +@cindex DFC API +@cindex API, DFC + +This is for conversion between internal and external text. Note that +there is also the "new DFC" API, which @strong{returns} a pointer to the +converted text (in alloca space), rather than storing it into a +variable. + +The macros below are used for converting data between different formats. +Generally, the data is textual, and the formats are related to +internationalization (e.g. converting between internal-format text and +UTF-8) -- but the mechanism is general, and could be used for anything, +e.g. decoding gzipped data. + +In general, conversion involves a source of data, a sink, the existing +format of the source data, and the desired format of the sink. The +macros below, however, always require that either the source or sink is +internal-format text. Therefore, in practice the conversions below +involve source, sink, an external format (specified by a coding system), +and the direction of conversion (internal->external or vice-versa). + +Sources and sinks can be raw data (sized or unsized -- when unsized, +input data is assumed to be null-terminated [double null-terminated for +Unicode-format data], and on output the length is not stored anywhere), +Lisp strings, Lisp buffers, lstreams, and opaque data objects. When the +output is raw data, the result can be allocated either with @code{alloca()} or +@code{malloc()}. (There is currently no provision for writing into a fixed +buffer. If you want this, use @code{alloca()} output and then copy the data -- +but be careful with the size! Unless you are very sure of the encoding +being used, upper bounds for the size are not in general computable.) +The obvious restrictions on source and sink types apply (e.g. Lisp +strings are a source and sink only for internal data). + +All raw data outputted will contain an extra null byte (two bytes for +Unicode -- currently, in fact, all output data, whether internal or +external, is double-null-terminated, but you can't count on this; see +below). This means that enough space is allocated to contain the extra +nulls; however, these nulls are not reflected in the returned output +size. + +The most basic macros are TO_EXTERNAL_FORMAT and TO_INTERNAL_FORMAT. +These can be used to convert between any kinds of sources or sinks. +However, 99% of conversions involve raw data or Lisp strings as both +source and sink, and usually data is output as @code{alloca()} rather than +@code{malloc()}. For this reason, convenience macros are defined for many types +of conversions involving raw data and/or Lisp strings, especially when +the output is an @code{alloca()}ed string. (When the destination is a +Lisp_String, there are other functions that should be used instead -- +@code{build_ext_string()} and @code{make_ext_string()}, for example.) The convenience +macros are of two types -- the older kind that store the result into a +specified variable, and the newer kind that return the result. The newer +kind of macros don't exist when the output is sized data, because that +would have two return values. NOTE: All convenience macros are +ultimately defined in terms of TO_EXTERNAL_FORMAT and TO_INTERNAL_FORMAT. +Thus, any comments below about the workings of these macros also apply to +all convenience macros. + +@example +TO_EXTERNAL_FORMAT (source_type, source, sink_type, sink, codesys) +TO_INTERNAL_FORMAT (source_type, source, sink_type, sink, codesys) +@end example + +Typical use is + +@example + TO_EXTERNAL_FORMAT (LISP_STRING, str, C_STRING_MALLOC, ptr, Qfile_name); +@end example + +which means that the contents of the lisp string @var{str} are written +to a malloc'ed memory area which will be pointed to by @var{ptr}, after the +function returns. The conversion will be done using the @code{file-name} +coding system (which will be controlled by the user indirectly by +setting or binding the variable @code{file-name-coding-system}). + +Some sources and sinks require two C variables to specify. We use +some preprocessor magic to allow different source and sink types, and +even different numbers of arguments to specify different types of +sources and sinks. + +So we can have a call that looks like + +@example + TO_INTERNAL_FORMAT (DATA, (ptr, len), + MALLOC, (ptr, len), + coding_system); +@end example + +The parenthesized argument pairs are required to make the +preprocessor magic work. + +NOTE: GC is inhibited during the entire operation of these macros. This +is because frequently the data to be converted comes from strings but +gets passed in as just DATA, and GC may move around the string data. If +we didn't inhibit GC, there'd have to be a lot of messy recoding, +alloca-copying of strings and other annoying stuff. + +The source or sink can be specified in one of these ways: + +@example +DATA, (ptr, len), // input data is a fixed buffer of size len +ALLOCA, (ptr, len), // output data is in a @code{ALLOCA()}ed buffer of size len +MALLOC, (ptr, len), // output data is in a @code{malloc()}ed buffer of size len +C_STRING_ALLOCA, ptr, // equivalent to ALLOCA (ptr, len_ignored) on output +C_STRING_MALLOC, ptr, // equivalent to MALLOC (ptr, len_ignored) on output +C_STRING, ptr, // equivalent to DATA, (ptr, strlen/wcslen (ptr)) + // on input (the Unicode version is used when correct) +LISP_STRING, string, // input or output is a Lisp_Object of type string +LISP_BUFFER, buffer, // output is written to (point) in lisp buffer +LISP_LSTREAM, lstream, // input or output is a Lisp_Object of type lstream +LISP_OPAQUE, object, // input or output is a Lisp_Object of type opaque +@end example + +When specifying the sink, use lvalues, since the macro will assign to them, +except when the sink is an lstream or a lisp buffer. + +For the sink types @code{ALLOCA} and @code{C_STRING_ALLOCA}, the resulting text is +stored in a stack-allocated buffer, which is automatically freed on +returning from the function. However, the sink types @code{MALLOC} and +@code{C_STRING_MALLOC} return @code{xmalloc()}ed memory. The caller is responsible +for freeing this memory using @code{xfree()}. + +The macros accept the kinds of sources and sinks appropriate for +internal and external data representation. See the type_checking_assert +macros below for the actual allowed types. + +Since some sources and sinks use one argument (a Lisp_Object) to +specify them, while others take a (pointer, length) pair, we use +some C preprocessor trickery to allow pair arguments to be specified +by parenthesizing them, as in the examples above. + +Anything prefixed by dfc_ (`data format conversion') is private. +They are only used to implement these macros. + +[[Using C_STRING* is appropriate for using with external APIs that +take null-terminated strings. For internal data, we should try to +be '\0'-clean - i.e. allow arbitrary data to contain embedded '\0'. + +Sometime in the future we might allow output to C_STRING_ALLOCA or +C_STRING_MALLOC _only_ with @code{TO_EXTERNAL_FORMAT()}, not +@code{TO_INTERNAL_FORMAT()}.]] + +The above comments are not true. Frequently (most of the time, in +fact), external strings come as zero-terminated entities, where the +zero-termination is the only way to find out the length. Even in +cases where you can get the length, most of the time the system will +still use the null to signal the end of the string, and there will +still be no way to either send in or receive a string with embedded +nulls. In such situations, it's pointless to track the length +because null bytes can never be in the string. We have a lot of +operations that make it easy to operate on zero-terminated strings, +and forcing the user the deal with the length everywhere would only +make the code uglier and more complicated, for no gain. --ben + +There is no problem using the same lvalue for source and sink. + +Also, when pointers are required, the code (currently at least) is +lax and allows any pointer types, either in the source or the sink. +This makes it possible, e.g., to deal with internal format data held +in char *'s or external format data held in WCHAR * (i.e. Unicode). + +Finally, whenever storage allocation is called for, extra space is +allocated for a terminating zero, and such a zero is stored in the +appropriate place, regardless of whether the source data was +specified using a length or was specified as zero-terminated. This +allows you to freely pass the resulting data, no matter how +obtained, to a routine that expects zero termination (modulo, of +course, that any embedded zeros in the resulting text will cause +truncation). In fact, currently two embedded zeros are allocated +and stored after the data result. This is to allow for the +possibility of storing a Unicode value on output, which needs the +two zeros. Currently, however, the two zeros are stored regardless +of whether the conversion is internal or external and regardless of +whether the external coding system is in fact Unicode. This +behavior may change in the future, and you cannot rely on this -- +the most you can rely on is that sink data in Unicode format will +have two terminating nulls, which combine to form one Unicode null +character. + +NOTE: You might ask, why are these not written as functions that +@strong{RETURN} the converted string, since that would allow them to be used +much more conveniently, without having to constantly declare temporary +variables? The answer is that in fact I originally did write the +routines that way, but that required either + +@itemize @bullet +@item +(a) calling @code{alloca()} inside of a function call, or +@item +(b) using expressions separated by commas and a global temporary variable, or +@item +(c) using the GCC extension (@{ ... @}). +@end itemize + +Turned out that all of the above had bugs, all caused by GCC (hence the +comments about "those GCC wankers" and "ream gcc up the ass"). As for +(a), some versions of GCC (especially on Intel platforms), which had +buggy implementations of @code{alloca()} that couldn't handle being called +inside of a function call -- they just decremented the stack right in the +middle of pushing args. Oops, crash with stack trashing, very bad. (b) +was an attempt to fix (a), and that led to further GCC crashes, esp. when +you had two such calls in a single subexpression, because GCC couldn't be +counted upon to follow even a minimally reasonable order of execution. +True, you can't count on one argument being evaluated before another, but +GCC would actually interleave them so that the temp var got stomped on by +one while the other was accessing it. So I tried (c), which was +problematic because that GCC extension has more bugs in it than a +termite's nest. + +So reluctantly I converted to the current way. Now, that was awhile ago +(c. 1994), and it appears that the bug involving alloca in function calls +has long since been fixed. More recently, I defined the new-dfc routines +down below, which DO allow exactly such convenience of returning your +args rather than store them in temp variables, and I also wrote a +configure check to see whether @code{alloca()} causes crashes inside of function +calls, and if so use the portable @code{alloca()} implementation in alloca.c. +If you define TEST_NEW_DFC, the old routines get written in terms of the +new ones, and I've had a beta put out with this on and it appeared to +this appears to cause no problems -- so we should consider +switching, and feel no compunctions about writing further such function- +like @code{alloca()} routines in lieu of statement-like ones. --ben + +@node The Eistring API, , The DFC API, Internal Text API's +@subsection The Eistring API +@cindex Eistring API +@cindex API, Eistring + +(This API is currently under-used) When doing simple things with +internal text, the basic internal-format API's are enough. But to do +things like delete or replace a substring, concatenate various strings, +etc. is difficult to do cleanly because of the allocation issues. +The Eistring API is designed to deal with this, and provides a clean +way of modifying and building up internal text. (Note that the former +lack of this API has meant that some code uses Lisp strings to do +similar manipulations, resulting in excess garbage and increased +garbage collection.) + +NOTE: The Eistring API is (or should be) Mule-correct even without +an ASCII-compatible internal representation. + +@example +#### NOTE: This is a work in progress. Neither the API nor especially +the implementation is finished. + +NOTE: An Eistring is a structure that makes it easy to work with +internally-formatted strings of data. It provides operations similar +in feel to the standard @code{strcpy()}, @code{strcat()}, @code{strlen()}, etc., but + +(a) it is Mule-correct +(b) it does dynamic allocation so you never have to worry about size + restrictions +(c) it comes in an @code{ALLOCA()} variety (all allocation is stack-local, + so there is no need to explicitly clean up) as well as a @code{malloc()} + variety +(d) it knows its own length, so it does not suffer from standard null + byte brain-damage -- but it null-terminates the data anyway, so + it can be passed to standard routines +(e) it provides a much more powerful set of operations and knows about + all the standard places where string data might reside: Lisp_Objects, + other Eistrings, Ibyte * data with or without an explicit length, + ASCII strings, Ichars, etc. +(f) it provides easy operations to convert to/from externally-formatted + data, and is easier to use than the standard TO_INTERNAL_FORMAT + and TO_EXTERNAL_FORMAT macros. (An Eistring can store both the internal + and external version of its data, but the external version is only + initialized or changed when you call @code{eito_external()}.) + +The idea is to make it as easy to write Mule-correct string manipulation +code as it is to write normal string manipulation code. We also make +the API sufficiently general that it can handle multiple internal data +formats (e.g. some fixed-width optimizing formats and a default variable +width format) and allows for @strong{ANY} data format we might choose in the +future for the default format, including UCS2. (In other words, we can't +assume that the internal format is ASCII-compatible and we can't assume +it doesn't have embedded null bytes. We do assume, however, that any +chosen format will have the concept of null-termination.) All of this is +hidden from the user. + +#### It is really too bad that we don't have a real object-oriented +language, or at least a language with polymorphism! + + + ********************************************** + * Declaration * + ********************************************** + +To declare an Eistring, either put one of the following in the local +variable section: + +DECLARE_EISTRING (name); + Declare a new Eistring and initialize it to the empy string. This + is a standard local variable declaration and can go anywhere in the + variable declaration section. NAME itself is declared as an + Eistring *, and its storage declared on the stack. + +DECLARE_EISTRING_MALLOC (name); + Declare and initialize a new Eistring, which uses @code{malloc()}ed + instead of @code{ALLOCA()}ed data. This is a standard local variable + declaration and can go anywhere in the variable declaration + section. Once you initialize the Eistring, you will have to free + it using @code{eifree()} to avoid memory leaks. You will need to use this + form if you are passing an Eistring to any function that modifies + it (otherwise, the modified data may be in stack space and get + overwritten when the function returns). + +or use + +Eistring ei; +void eiinit (Eistring *ei); +void eiinit_malloc (Eistring *einame); + If you need to put an Eistring elsewhere than in a local variable + declaration (e.g. in a structure), declare it as shown and then + call one of the init macros. + +Also note: + +void eifree (Eistring *ei); + If you declared an Eistring to use @code{malloc()} to hold its data, + or converted it to the heap using @code{eito_malloc()}, then this + releases any data in it and afterwards resets the Eistring + using @code{eiinit_malloc()}. Otherwise, it just resets the Eistring + using @code{eiinit()}. + + + ********************************************** + * Conventions * + ********************************************** + + - The names of the functions have been chosen, where possible, to + match the names of @code{str*()} functions in the standard C API. + - + + + ********************************************** + * Initialization * + ********************************************** + +void eireset (Eistring *eistr); + Initialize the Eistring to the empty string. + +void eicpy_* (Eistring *eistr, ...); + Initialize the Eistring from somewhere: + +void eicpy_ei (Eistring *eistr, Eistring *eistr2); + ... from another Eistring. +void eicpy_lstr (Eistring *eistr, Lisp_Object lisp_string); + ... from a Lisp_Object string. +void eicpy_ch (Eistring *eistr, Ichar ch); + ... from an Ichar (this can be a conventional C character). + +void eicpy_lstr_off (Eistring *eistr, Lisp_Object lisp_string, + Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen); + ... from a section of a Lisp_Object string. +void eicpy_lbuf (Eistring *eistr, Lisp_Object lisp_buf, + Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen); + ... from a section of a Lisp_Object buffer. +void eicpy_raw (Eistring *eistr, const Ibyte *data, Bytecount len); + ... from raw internal-format data in the default internal format. +void eicpy_rawz (Eistring *eistr, const Ibyte *data); + ... from raw internal-format data in the default internal format + that is "null-terminated" (the meaning of this depends on the nature + of the default internal format). +void eicpy_raw_fmt (Eistring *eistr, const Ibyte *data, Bytecount len, + Internal_Format intfmt, Lisp_Object object); + ... from raw internal-format data in the specified format. +void eicpy_rawz_fmt (Eistring *eistr, const Ibyte *data, + Internal_Format intfmt, Lisp_Object object); + ... from raw internal-format data in the specified format that is + "null-terminated" (the meaning of this depends on the nature of + the specific format). +void eicpy_c (Eistring *eistr, const Ascbyte *c_string); + ... from an ASCII null-terminated string. Non-ASCII characters in + the string are @strong{ILLEGAL} (read @code{abort()} with error-checking defined). +void eicpy_c_len (Eistring *eistr, const Ascbyte *c_string, len); + ... from an ASCII string, with length specified. Non-ASCII characters + in the string are @strong{ILLEGAL} (read @code{abort()} with error-checking defined). +void eicpy_ext (Eistring *eistr, const Extbyte *extdata, + Lisp_Object codesys); + ... from external null-terminated data, with coding system specified. +void eicpy_ext_len (Eistring *eistr, const Extbyte *extdata, + Bytecount extlen, Lisp_Object codesys); + ... from external data, with length and coding system specified. +void eicpy_lstream (Eistring *eistr, Lisp_Object lstream); + ... from an lstream; reads data till eof. Data must be in default + internal format; otherwise, interpose a decoding lstream. + + + ********************************************** + * Getting the data out of the Eistring * + ********************************************** + +Ibyte *eidata (Eistring *eistr); + Return a pointer to the raw data in an Eistring. This is NOT + a copy. + +Lisp_Object eimake_string (Eistring *eistr); + Make a Lisp string out of the Eistring. + +Lisp_Object eimake_string_off (Eistring *eistr, + Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen); + Make a Lisp string out of a section of the Eistring. + +void eicpyout_alloca (Eistring *eistr, LVALUE: Ibyte *ptr_out, + LVALUE: Bytecount len_out); + Make an @code{ALLOCA()} copy of the data in the Eistring, using the + default internal format. Due to the nature of @code{ALLOCA()}, this + must be a macro, with all lvalues passed in as parameters. + (More specifically, not all compilers correctly handle using + @code{ALLOCA()} as the argument to a function call -- GCC on x86 + didn't used to, for example.) A pointer to the @code{ALLOCA()}ed data + is stored in PTR_OUT, and the length of the data (not including + the terminating zero) is stored in LEN_OUT. + +void eicpyout_alloca_fmt (Eistring *eistr, LVALUE: Ibyte *ptr_out, + LVALUE: Bytecount len_out, + Internal_Format intfmt, Lisp_Object object); + Like @code{eicpyout_alloca()}, but converts to the specified internal + format. (No formats other than FORMAT_DEFAULT are currently + implemented, and you get an assertion failure if you try.) + +Ibyte *eicpyout_malloc (Eistring *eistr, Bytecount *intlen_out); + Make a @code{malloc()} copy of the data in the Eistring, using the + default internal format. This is a real function. No lvalues + passed in. Returns the new data, and stores the length (not + including the terminating zero) using INTLEN_OUT, unless it's + a NULL pointer. + +Ibyte *eicpyout_malloc_fmt (Eistring *eistr, Internal_Format intfmt, + Bytecount *intlen_out, Lisp_Object object); + Like @code{eicpyout_malloc()}, but converts to the specified internal + format. (No formats other than FORMAT_DEFAULT are currently + implemented, and you get an assertion failure if you try.) + + + ********************************************** + * Moving to the heap * + ********************************************** + +void eito_malloc (Eistring *eistr); + Move this Eistring to the heap. Its data will be stored in a + @code{malloc()}ed block rather than the stack. Subsequent changes to + this Eistring will @code{realloc()} the block as necessary. Use this + when you want the Eistring to remain in scope past the end of + this function call. You will have to manually free the data + in the Eistring using @code{eifree()}. + +void eito_alloca (Eistring *eistr); + Move this Eistring back to the stack, if it was moved to the + heap with @code{eito_malloc()}. This will automatically free any + heap-allocated data. + + + + ********************************************** + * Retrieving the length * + ********************************************** + +Bytecount eilen (Eistring *eistr); + Return the length of the internal data, in bytes. See also + @code{eiextlen()}, below. +Charcount eicharlen (Eistring *eistr); + Return the length of the internal data, in characters. + + + ********************************************** + * Working with positions * + ********************************************** + +Bytecount eicharpos_to_bytepos (Eistring *eistr, Charcount charpos); + Convert a char offset to a byte offset. +Charcount eibytepos_to_charpos (Eistring *eistr, Bytecount bytepos); + Convert a byte offset to a char offset. +Bytecount eiincpos (Eistring *eistr, Bytecount bytepos); + Increment the given position by one character. +Bytecount eiincpos_n (Eistring *eistr, Bytecount bytepos, Charcount n); + Increment the given position by N characters. +Bytecount eidecpos (Eistring *eistr, Bytecount bytepos); + Decrement the given position by one character. +Bytecount eidecpos_n (Eistring *eistr, Bytecount bytepos, Charcount n); + Deccrement the given position by N characters. + + + ********************************************** + * Getting the character at a position * + ********************************************** + +Ichar eigetch (Eistring *eistr, Bytecount bytepos); + Return the character at a particular byte offset. +Ichar eigetch_char (Eistring *eistr, Charcount charpos); + Return the character at a particular character offset. + + + ********************************************** + * Setting the character at a position * + ********************************************** + +Ichar eisetch (Eistring *eistr, Bytecount bytepos, Ichar chr); + Set the character at a particular byte offset. +Ichar eisetch_char (Eistring *eistr, Charcount charpos, Ichar chr); + Set the character at a particular character offset. + + + ********************************************** + * Concatenation * + ********************************************** + +void eicat_* (Eistring *eistr, ...); + Concatenate onto the end of the Eistring, with data coming from the + same places as above: + +void eicat_ei (Eistring *eistr, Eistring *eistr2); + ... from another Eistring. +void eicat_c (Eistring *eistr, Ascbyte *c_string); + ... from an ASCII null-terminated string. Non-ASCII characters in + the string are @strong{ILLEGAL} (read @code{abort()} with error-checking defined). +void eicat_raw (ei, const Ibyte *data, Bytecount len); + ... from raw internal-format data in the default internal format. +void eicat_rawz (ei, const Ibyte *data); + ... from raw internal-format data in the default internal format + that is "null-terminated" (the meaning of this depends on the nature + of the default internal format). +void eicat_lstr (ei, Lisp_Object lisp_string); + ... from a Lisp_Object string. +void eicat_ch (ei, Ichar ch); + ... from an Ichar. + +All except the first variety are convenience functions. +n the general case, create another Eistring from the source.) + + + ********************************************** + * Replacement * + ********************************************** + +void eisub_* (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, ...); + Replace a section of the Eistring, specifically: + +void eisub_ei (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, Eistring *eistr2); + ... with another Eistring. +void eisub_c (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, Ascbyte *c_string); + ... with an ASCII null-terminated string. Non-ASCII characters in + the string are @strong{ILLEGAL} (read @code{abort()} with error-checking defined). +void eisub_ch (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, Ichar ch); + ... with an Ichar. + +void eidel (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen); + Delete a section of the Eistring. + + + ********************************************** + * Converting to an external format * + ********************************************** + +void eito_external (Eistring *eistr, Lisp_Object codesys); + Convert the Eistring to an external format and store the result + in the string. NOTE: Further changes to the Eistring will @strong{NOT} + change the external data stored in the string. You will have to + call @code{eito_external()} again in such a case if you want the external + data. + +Extbyte *eiextdata (Eistring *eistr); + Return a pointer to the external data stored in the Eistring as + a result of a prior call to @code{eito_external()}. + +Bytecount eiextlen (Eistring *eistr); + Return the length in bytes of the external data stored in the + Eistring as a result of a prior call to @code{eito_external()}. + + + ********************************************** + * Searching in the Eistring for a character * + ********************************************** + +Bytecount eichr (Eistring *eistr, Ichar chr); +Charcount eichr_char (Eistring *eistr, Ichar chr); +Bytecount eichr_off (Eistring *eistr, Ichar chr, Bytecount off, + Charcount charoff); +Charcount eichr_off_char (Eistring *eistr, Ichar chr, Bytecount off, + Charcount charoff); +Bytecount eirchr (Eistring *eistr, Ichar chr); +Charcount eirchr_char (Eistring *eistr, Ichar chr); +Bytecount eirchr_off (Eistring *eistr, Ichar chr, Bytecount off, + Charcount charoff); +Charcount eirchr_off_char (Eistring *eistr, Ichar chr, Bytecount off, + Charcount charoff); + + + ********************************************** + * Searching in the Eistring for a string * + ********************************************** + +Bytecount eistr_ei (Eistring *eistr, Eistring *eistr2); +Charcount eistr_ei_char (Eistring *eistr, Eistring *eistr2); +Bytecount eistr_ei_off (Eistring *eistr, Eistring *eistr2, Bytecount off, + Charcount charoff); +Charcount eistr_ei_off_char (Eistring *eistr, Eistring *eistr2, + Bytecount off, Charcount charoff); +Bytecount eirstr_ei (Eistring *eistr, Eistring *eistr2); +Charcount eirstr_ei_char (Eistring *eistr, Eistring *eistr2); +Bytecount eirstr_ei_off (Eistring *eistr, Eistring *eistr2, Bytecount off, + Charcount charoff); +Charcount eirstr_ei_off_char (Eistring *eistr, Eistring *eistr2, + Bytecount off, Charcount charoff); + +Bytecount eistr_c (Eistring *eistr, Ascbyte *c_string); +Charcount eistr_c_char (Eistring *eistr, Ascbyte *c_string); +Bytecount eistr_c_off (Eistring *eistr, Ascbyte *c_string, Bytecount off, + Charcount charoff); +Charcount eistr_c_off_char (Eistring *eistr, Ascbyte *c_string, + Bytecount off, Charcount charoff); +Bytecount eirstr_c (Eistring *eistr, Ascbyte *c_string); +Charcount eirstr_c_char (Eistring *eistr, Ascbyte *c_string); +Bytecount eirstr_c_off (Eistring *eistr, Ascbyte *c_string, + Bytecount off, Charcount charoff); +Charcount eirstr_c_off_char (Eistring *eistr, Ascbyte *c_string, + Bytecount off, Charcount charoff); + + + ********************************************** + * Comparison * + ********************************************** + +int eicmp_* (Eistring *eistr, ...); +int eicmp_off_* (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, ...); +int eicasecmp_* (Eistring *eistr, ...); +int eicasecmp_off_* (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, ...); +int eicasecmp_i18n_* (Eistring *eistr, ...); +int eicasecmp_i18n_off_* (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, ...); + + Compare the Eistring with the other data. Return value same as + from strcmp. The @code{*} is either @code{ei} for another Eistring (in + which case @code{...} is an Eistring), or @code{c} for a pure-ASCII string + (in which case @code{...} is a pointer to that string). For anything + more complex, first create an Eistring out of the source. + Comparison is either simple (@code{eicmp_...}), ASCII case-folding + (@code{eicasecmp_...}), or multilingual case-folding + (@code{eicasecmp_i18n_...}). + + +More specifically, the prototypes are: + +int eicmp_ei (Eistring *eistr, Eistring *eistr2); +int eicmp_off_ei (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, Eistring *eistr2); +int eicasecmp_ei (Eistring *eistr, Eistring *eistr2); +int eicasecmp_off_ei (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, Eistring *eistr2); +int eicasecmp_i18n_ei (Eistring *eistr, Eistring *eistr2); +int eicasecmp_i18n_off_ei (Eistring *eistr, Bytecount off, + Charcount charoff, Bytecount len, + Charcount charlen, Eistring *eistr2); + +int eicmp_c (Eistring *eistr, Ascbyte *c_string); +int eicmp_off_c (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, Ascbyte *c_string); +int eicasecmp_c (Eistring *eistr, Ascbyte *c_string); +int eicasecmp_off_c (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, + Ascbyte *c_string); +int eicasecmp_i18n_c (Eistring *eistr, Ascbyte *c_string); +int eicasecmp_i18n_off_c (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, + Ascbyte *c_string); + + + ********************************************** + * Case-changing the Eistring * + ********************************************** + +void eilwr (Eistring *eistr); + Convert all characters in the Eistring to lowercase. +void eiupr (Eistring *eistr); + Convert all characters in the Eistring to uppercase. +@end example + +@node Coding for Mule, CCL, Internal Text API's, Multilingual Support +@section Coding for Mule +@cindex coding for Mule +@cindex Mule, coding for + +Although Mule support is not compiled by default in XEmacs, many people +are using it, and we consider it crucial that new code works correctly +with multibyte characters. This is not hard; it is only a matter of +following several simple user-interface guidelines. Even if you never +compile with Mule, with a little practice you will find it quite easy +to code Mule-correctly. + +Note that these guidelines are not necessarily tied to the current Mule +implementation; they are also a good idea to follow on the grounds of +code generalization for future I18N work. + +@menu +* Character-Related Data Types:: +* Working With Character and Byte Positions:: +* Conversion to and from External Data:: +* General Guidelines for Writing Mule-Aware Code:: +* An Example of Mule-Aware Code:: +* Mule-izing Code:: +@end menu + +@node Character-Related Data Types, Working With Character and Byte Positions, Coding for Mule, Coding for Mule +@subsection Character-Related Data Types +@cindex character-related data types +@cindex data types, character-related + +First, let's review the basic character-related datatypes used by +XEmacs. Note that some of the separate @code{typedef}s are not +mandatory, but they improve clarity of code a great deal, because one +glance at the declaration can tell the intended use of the variable. + +@table @code +@item Ichar +@cindex Ichar +An @code{Ichar} holds a single Emacs character. + +Obviously, the equality between characters and bytes is lost in the Mule +world. Characters can be represented by one or more bytes in the +buffer, and @code{Ichar} is a C type large enough to hold any +character. (This currently isn't quite true for ISO 10646, which +defines a character as a 31-bit non-negative quantity, while XEmacs +characters are only 30-bits. This is irrelevant, unless you are +considering using the ISO 10646 private groups to support really large +private character sets---in particular, the Mule character set!---in +a version of XEmacs using Unicode internally.) + +Without Mule support, an @code{Ichar} is equivalent to an +@code{unsigned char}. [[This doesn't seem to be true; @file{lisp.h} +unconditionally @samp{typedef}s @code{Ichar} to @code{int}.]] + +@item Ibyte +@cindex Ibyte +The data representing the text in a buffer or string is logically a set +of @code{Ibyte}s. + +XEmacs does not work with the same character formats all the time; when +reading characters from the outside, it decodes them to an internal +format, and likewise encodes them when writing. @code{Ibyte} (in fact +@code{unsigned char}) is the basic unit of XEmacs internal buffers and +strings format. An @code{Ibyte *} is the type that points at text +encoded in the variable-width internal encoding. + +One character can correspond to one or more @code{Ibyte}s. In the +current Mule implementation, an ASCII character is represented by the +same @code{Ibyte}, and other characters are represented by a sequence +of two or more @code{Ibyte}s. (This will also be true of an +implementation using UTF-8 as the internal encoding. In fact, only code +that implements character code conversions and a very few macros used to +implement motion by whole characters will notice the difference between +UTF-8 and the Mule encoding.) + +Without Mule support, there are exactly 256 characters, implicitly +Latin-1, and each character is represented using one @code{Ibyte}, and +there is a one-to-one correspondence between @code{Ibyte}s and +@code{Ichar}s. + +@item Charxpos +@item Charbpos +@itemx Charcount +@cindex Charxpos +@cindex Charbpos +@cindex Charcount +A @code{Charbpos} represents a character position in a buffer. A +@code{Charcount} represents a number (count) of characters. Logically, +subtracting two @code{Charbpos} values yields a @code{Charcount} value. +When representing a character position in a string, we just use +@code{Charcount} directly. The reason for having a separate typedef for +buffer positions is that they are 1-based, whereas string positions are +0-based and hence string counts and positions can be freely intermixed (a +string position is equivalent to the count of characters from the +beginning). When representing a character position that could be either +in a buffer or string (for example, in the extent code), @code{Charxpos} +is used. Although all of these are @code{typedef}ed to +@code{EMACS_INT}, we use them in preference to @code{EMACS_INT} to make +it clear what sort of position is being used. + +@code{Charxpos}, @code{Charbpos} and @code{Charcount} values are the +only ones that are ever visible to Lisp. + +@item Bytexpos +@itemx Bytecount +@cindex Bytebpos +@cindex Bytecount +A @code{Bytebpos} represents a byte position in a buffer. A +@code{Bytecount} represents the distance between two positions, in +bytes. Byte positions in strings use @code{Bytecount}, and for byte +positions that can be either in a buffer or string, @code{Bytexpos} is +used. The relationship between @code{Bytexpos}, @code{Bytebpos} and +@code{Bytecount} is the same as the relationship between +@code{Charxpos}, @code{Charbpos} and @code{Charcount}. + +@item Extbyte +@cindex Extbyte +When dealing with the outside world, XEmacs works with @code{Extbyte}s, +which are equivalent to @code{char}. The distance between two +@code{Extbyte}s is a @code{Bytecount}, since external text is a +byte-by-byte encoding. Extbytes occur mainly at the transition point +between internal text and external functions. XEmacs code should not, +if it can possibly avoid it, do any actual manipulation using external +text, since its format is completely unpredictable (it might not even be +ASCII-compatible). +@end table + +@node Working With Character and Byte Positions, Conversion to and from External Data, Character-Related Data Types, Coding for Mule +@subsection Working With Character and Byte Positions +@cindex character and byte positions, working with +@cindex byte positions, working with character and +@cindex positions, working with character and byte + +Now that we have defined the basic character-related types, we can look +at the macros and functions designed for work with them and for +conversion between them. Most of these macros are defined in +@file{buffer.h}, and we don't discuss all of them here, but only the +most important ones. Examining the existing code is the best way to +learn about them. + +@table @code +@item MAX_ICHAR_LEN +@cindex MAX_ICHAR_LEN +This preprocessor constant is the maximum number of buffer bytes to +represent an Emacs character in the variable width internal encoding. +It is useful when allocating temporary strings to keep a known number of +characters. For instance: + +@example +@group +@{ + Charcount cclen; + ... + @{ + /* Allocate place for @var{cclen} characters. */ + Ibyte *buf = (Ibyte *) alloca (cclen * MAX_ICHAR_LEN); +... +@end group +@end example + +If you followed the previous section, you can guess that, logically, +multiplying a @code{Charcount} value with @code{MAX_ICHAR_LEN} produces +a @code{Bytecount} value. + +In the current Mule implementation, @code{MAX_ICHAR_LEN} equals 4. +Without Mule, it is 1. In a mature Unicode-based XEmacs, it will also +be 4 (since all Unicode characters can be encoded in UTF-8 in 4 bytes or +less), but some versions may use up to 6, in order to use the large +private space provided by ISO 10646 to ``mirror'' the Mule code space. + +@item itext_ichar +@itemx set_itext_ichar +@cindex itext_ichar +@cindex set_itext_ichar +The @code{itext_ichar} macro takes a @code{Ibyte} pointer and +returns the @code{Ichar} stored at that position. If it were a +function, its prototype would be: + +@example +Ichar itext_ichar (Ibyte *p); +@end example + +@code{set_itext_ichar} stores an @code{Ichar} to the specified byte +position. It returns the number of bytes stored: + +@example +Bytecount set_itext_ichar (Ibyte *p, Ichar c); +@end example + +It is important to note that @code{set_itext_ichar} is safe only for +appending a character at the end of a buffer, not for overwriting a +character in the middle. This is because the width of characters +varies, and @code{set_itext_ichar} cannot resize the string if it +writes, say, a two-byte character where a single-byte character used to +reside. + +A typical use of @code{set_itext_ichar} can be demonstrated by this +example, which copies characters from buffer @var{buf} to a temporary +string of Ibytes. + +@example +@group +@{ + Charbpos pos; + for (pos = beg; pos < end; pos++) + @{ + Ichar c = BUF_FETCH_CHAR (buf, pos); + p += set_itext_ichar (buf, c); + @} +@} +@end group +@end example + +Note how @code{set_itext_ichar} is used to store the @code{Ichar} +and increment the counter, at the same time. + +@item INC_IBYTEPTR +@itemx DEC_IBYTEPTR +@cindex INC_IBYTEPTR +@cindex DEC_IBYTEPTR +These two macros increment and decrement an @code{Ibyte} pointer, +respectively. They will adjust the pointer by the appropriate number of +bytes according to the byte length of the character stored there. Both +macros assume that the memory address is located at the beginning of a +valid character. + +Without Mule support, @code{INC_IBYTEPTR (p)} and @code{DEC_IBYTEPTR (p)} +simply expand to @code{p++} and @code{p--}, respectively. + +@item bytecount_to_charcount +@cindex bytecount_to_charcount +Given a pointer to a text string and a length in bytes, return the +equivalent length in characters. + +@example +Charcount bytecount_to_charcount (Ibyte *p, Bytecount bc); +@end example + +@item charcount_to_bytecount +@cindex charcount_to_bytecount +Given a pointer to a text string and a length in characters, return the +equivalent length in bytes. + +@example +Bytecount charcount_to_bytecount (Ibyte *p, Charcount cc); +@end example + +@item itext_n_addr +@cindex itext_n_addr +Return a pointer to the beginning of the character offset @var{cc} (in +characters) from @var{p}. + +@example +Ibyte *itext_n_addr (Ibyte *p, Charcount cc); +@end example +@end table + +@node Conversion to and from External Data, General Guidelines for Writing Mule-Aware Code, Working With Character and Byte Positions, Coding for Mule +@subsection Conversion to and from External Data +@cindex conversion to and from external data +@cindex external data, conversion to and from + +When an external function, such as a C library function, returns a +@code{char} pointer, you should almost never treat it as @code{Ibyte}. +This is because these returned strings may contain 8bit characters which +can be misinterpreted by XEmacs, and cause a crash. Likewise, when +exporting a piece of internal text to the outside world, you should +always convert it to an appropriate external encoding, lest the internal +stuff (such as the infamous \201 characters) leak out. + +The interface to conversion between the internal and external +representations of text are the numerous conversion macros defined in +@file{buffer.h}. There used to be a fixed set of external formats +supported by these macros, but now any coding system can be used with +them. The coding system alias mechanism is used to create the +following logical coding systems, which replace the fixed external +formats. The (dontusethis-set-symbol-value-handler) mechanism was +enhanced to make this possible (more work on that is needed). + +Often useful coding systems: + +@table @code +@item Qbinary +This is the simplest format and is what we use in the absence of a more +appropriate format. This converts according to the @code{binary} coding +system: + +@enumerate a +@item +On input, bytes 0--255 are converted into (implicitly Latin-1) +characters 0--255. A non-Mule xemacs doesn't really know about +different character sets and the fonts to display them, so the bytes can +be treated as text in different 1-byte encodings by simply setting the +appropriate fonts. So in a sense, non-Mule xemacs is a multi-lingual +editor if, for example, different fonts are used to display text in +different buffers, faces, or windows. The specifier mechanism gives the +user complete control over this kind of behavior. +@item +On output, characters 0--255 are converted into bytes 0--255 and other +characters are converted into @samp{~}. +@end enumerate + +@item Qnative +Format used for the external Unix environment---@code{argv[]}, stuff +from @code{getenv()}, stuff from the @file{/etc/passwd} file, etc. +This is encoded according to the encoding specified by the current locale. +[[This is dangerous; current locale is user preference, and the system +is probably going to be something else. Is there anything we can do +about it?]] + +@item Qfile_name +Format used for filenames. This is normally the same as @code{Qnative}, +but the two should be distinguished for clarity and possible future +separation -- and also because @code{Qfile_name} can be changed using either +the @code{file-name-coding-system} or @code{pathname-coding-system} (now +obsolete) variables. + +@item Qctext +Compound-text format. This is the standard X11 format used for data +stored in properties, selections, and the like. This is an 8-bit +no-lock-shift ISO2022 coding system. This is a real coding system, +unlike @code{Qfile_name}, which is user-definable. + +@item Qmswindows_tstr +Used for external data in all MS Windows functions that are declared to +accept data of type @code{LPTSTR} or @code{LPCSTR}. This maps to either +@code{Qmswindows_multibyte} (a locale-specific encoding, same as +@code{Qnative}) or @code{Qmswindows_unicode}, depending on whether +XEmacs is being run under Windows 9X or Windows NT/2000/XP. +@end table + +Many other coding systems are provided by default. + +There are two fundamental macros to convert between external and +internal format, as well as various convenience macros to simplify the +most common operations. + +@code{TO_INTERNAL_FORMAT} converts external data to internal format, and +@code{TO_EXTERNAL_FORMAT} converts the other way around. The arguments +each of these receives are a source type, a source, a sink type, a sink, +and a coding system (or a symbol naming a coding system). + +A typical call looks like +@example +TO_EXTERNAL_FORMAT (LISP_STRING, str, C_STRING_MALLOC, ptr, Qfile_name); +@end example + +which means that the contents of the lisp string @code{str} are written +to a malloc'ed memory area which will be pointed to by @code{ptr}, after +the function returns. The conversion will be done using the +@code{file-name} coding system, which will be controlled by the user +indirectly by setting or binding the variable +@code{file-name-coding-system}. + +Some sources and sinks require two C variables to specify. We use some +preprocessor magic to allow different source and sink types, and even +different numbers of arguments to specify different types of sources and +sinks. + +So we can have a call that looks like +@example +TO_INTERNAL_FORMAT (DATA, (ptr, len), + MALLOC, (ptr, len), + coding_system); +@end example + +The parenthesized argument pairs are required to make the preprocessor +magic work. + +Here are the different source and sink types: + +@table @code +@item @code{DATA, (ptr, len),} +input data is a fixed buffer of size @var{len} at address @var{ptr} +@item @code{ALLOCA, (ptr, len),} +output data is placed in an @code{alloca()}ed buffer of size @var{len} pointed to by @var{ptr} +@item @code{MALLOC, (ptr, len),} +output data is in a @code{malloc()}ed buffer of size @var{len} pointed to by @var{ptr} +@item @code{C_STRING_ALLOCA, ptr,} +equivalent to @code{ALLOCA (ptr, len_ignored)} on output. +@item @code{C_STRING_MALLOC, ptr,} +equivalent to @code{MALLOC (ptr, len_ignored)} on output +@item @code{C_STRING, ptr,} +equivalent to @code{DATA, (ptr, strlen/wcslen (ptr))} on input +@item @code{LISP_STRING, string,} +input or output is a Lisp_Object of type string +@item @code{LISP_BUFFER, buffer,} +output is written to @code{(point)} in lisp buffer @var{buffer} +@item @code{LISP_LSTREAM, lstream,} +input or output is a Lisp_Object of type lstream +@item @code{LISP_OPAQUE, object,} +input or output is a Lisp_Object of type opaque +@end table + +A source type of @code{C_STRING} or a sink type of +@code{C_STRING_ALLOCA} or @code{C_STRING_MALLOC} is appropriate where +the external API is not '\0'-byte-clean -- i.e. it expects strings to be +terminated with a null byte. For external API's that are in fact +'\0'-byte-clean, we should of course not use these. + +The sinks to be specified must be lvalues, unless they are the lisp +object types @code{LISP_LSTREAM} or @code{LISP_BUFFER}. + +There is no problem using the same lvalue for source and sink. + +Garbage collection is inhibited during these conversion operations, so +it is OK to pass in data from Lisp strings using @code{XSTRING_DATA}. + +For the sink types @code{ALLOCA} and @code{C_STRING_ALLOCA}, the +resulting text is stored in a stack-allocated buffer, which is +automatically freed on returning from the function. However, the sink +types @code{MALLOC} and @code{C_STRING_MALLOC} return @code{xmalloc()}ed +memory. The caller is responsible for freeing this memory using +@code{xfree()}. + +Note that it doesn't make sense for @code{LISP_STRING} to be a source +for @code{TO_INTERNAL_FORMAT} or a sink for @code{TO_EXTERNAL_FORMAT}. +You'll get an assertion failure if you try. + +99% of conversions involve raw data or Lisp strings as both source and +sink, and usually data is output as @code{alloca()}, or sometimes +@code{xmalloc()}. For this reason, convenience macros are defined for +many types of conversions involving raw data and/or Lisp strings, +especially when the output is an @code{alloca()}ed string. (When the +destination is a Lisp string, there are other functions that should be +used instead -- @code{build_ext_string()} and @code{make_ext_string()}, +for example.) The convenience macros are of two types -- the older kind +that store the result into a specified variable, and the newer kind that +return the result. The newer kind of macros don't exist when the output +is sized data, because that would have two return values. NOTE: All +convenience macros are ultimately defined in terms of +@code{TO_EXTERNAL_FORMAT} and @code{TO_INTERNAL_FORMAT}. Thus, any +comments above about the workings of these macros also apply to all +convenience macros. + +A typical old-style convenience macro is + +@example + C_STRING_TO_EXTERNAL (in, out, codesys); +@end example + +This is equivalent to + +@example + TO_EXTERNAL_FORMAT (C_STRING, in, C_STRING_ALLOCA, out, codesys); +@end example + +but is easier to write and somewhat clearer, since it clearly identifies +the arguments without the clutter of having the preprocessor types mixed +in. + +The new-style equivalent is @code{NEW_C_STRING_TO_EXTERNAL (src, +codesys)}, which @emph{returns} the converted data (still in +@code{alloca()} space). This is far more convenient for most +operations. + +@node General Guidelines for Writing Mule-Aware Code, An Example of Mule-Aware Code, Conversion to and from External Data, Coding for Mule +@subsection General Guidelines for Writing Mule-Aware Code +@cindex writing Mule-aware code, general guidelines for +@cindex Mule-aware code, general guidelines for writing +@cindex code, general guidelines for writing Mule-aware + +This section contains some general guidance on how to write Mule-aware +code, as well as some pitfalls you should avoid. + +@table @emph +@item Never use @code{char} and @code{char *}. +In XEmacs, the use of @code{char} and @code{char *} is almost always a +mistake. If you want to manipulate an Emacs character from ``C'', use +@code{Ichar}. If you want to examine a specific octet in the internal +format, use @code{Ibyte}. If you want a Lisp-visible character, use a +@code{Lisp_Object} and @code{make_char}. If you want a pointer to move +through the internal text, use @code{Ibyte *}. Also note that you +almost certainly do not need @code{Ichar *}. Other typedefs to clarify +the use of @code{char} are @code{Char_ASCII}, @code{Char_Binary}, +@code{UChar_Binary}, and @code{CIbyte}. + +@item Be careful not to confuse @code{Charcount}, @code{Bytecount}, @code{Charbpos} and @code{Bytebpos}. +The whole point of using different types is to avoid confusion about the +use of certain variables. Lest this effect be nullified, you need to be +careful about using the right types. + +@item Always convert external data +It is extremely important to always convert external data, because +XEmacs can crash if unexpected 8-bit sequences are copied to its internal +buffers literally. + +This means that when a system function, such as @code{readdir}, returns +a string, you normally need to convert it using one of the conversion macros +described in the previous chapter, before passing it further to Lisp. + +Actually, most of the basic system functions that accept '\0'-terminated +string arguments, like @code{stat()} and @code{open()}, have +@strong{encapsulated} equivalents that do the internal to external +conversion themselves. The encapsulated equivalents have a @code{qxe_} +prefix and have string arguments of type @code{Ibyte *}, and you can +pass internally encoded data to them, often from a Lisp string using +@code{XSTRING_DATA}. (A better design might be to provide versions that +accept Lisp strings directly.) [[Really? Then they'd either take +@code{Lisp_Object}s and need to check type, or they'd take +@code{Lisp_String}s, and violate the rules about passing any of the +specific Lisp types.]] + +Also note that many internal functions, such as @code{make_string}, +accept Ibytes, which removes the need for them to convert the data they +receive. This increases efficiency because that way external data needs +to be decoded only once, when it is read. After that, it is passed +around in internal format. + +@item Do all work in internal format +External-formatted data is completely unpredictable in its format. It +may be fixed-width Unicode (not even ASCII compatible); it may be a +modal encoding, in +which case some occurrences of (e.g.) the slash character may be part of +two-byte Asian-language characters, and a naive attempt to split apart a +pathname by slashes will fail; etc. Internal-format text should be +converted to external format only at the point where an external API is +actually called, and the first thing done after receiving +external-format text from an external API should be to convert it to +internal text. +@end table + +@node An Example of Mule-Aware Code, Mule-izing Code, General Guidelines for Writing Mule-Aware Code, Coding for Mule +@subsection An Example of Mule-Aware Code +@cindex code, an example of Mule-aware +@cindex Mule-aware code, an example of + +As an example of Mule-aware code, we will analyze the @code{string} +function, which conses up a Lisp string from the character arguments it +receives. Here is the definition, pasted from @code{alloc.c}: + +@example +@group +DEFUN ("string", Fstring, 0, MANY, 0, /* +Concatenate all the argument characters and make the result a string. +*/ + (int nargs, Lisp_Object *args)) +@{ + Ibyte *storage = alloca_array (Ibyte, nargs * MAX_ICHAR_LEN); + Ibyte *p = storage; + + for (; nargs; nargs--, args++) + @{ + Lisp_Object lisp_char = *args; + CHECK_CHAR_COERCE_INT (lisp_char); + p += set_itext_ichar (p, XCHAR (lisp_char)); + @} + return make_string (storage, p - storage); +@} +@end group +@end example + +Now we can analyze the source line by line. + +Obviously, string will be as long as there are arguments to the +function. This is why we allocate @code{MAX_ICHAR_LEN} * @var{nargs} +bytes on the stack, i.e. the worst-case number of bytes for @var{nargs} +@code{Ichar}s to fit in the string. + +Then, the loop checks that each element is a character, converting +integers in the process. Like many other functions in XEmacs, this +function silently accepts integers where characters are expected, for +historical and compatibility reasons. Unless you know what you are +doing, @code{CHECK_CHAR} will also suffice. @code{XCHAR (lisp_char)} +extracts the @code{Ichar} from the @code{Lisp_Object}, and +@code{set_itext_ichar} stores it to storage, increasing @code{p} in +the process. + +Other instructive examples of correct coding under Mule can be found all +over the XEmacs code. For starters, I recommend +@code{Fnormalize_menu_item_name} in @file{menubar.c}. After you have +understood this section of the manual and studied the examples, you can +proceed writing new Mule-aware code. + +@node Mule-izing Code, , An Example of Mule-Aware Code, Coding for Mule +@subsection Mule-izing Code + +A lot of code is written without Mule in mind, and needs to be made +Mule-correct or "Mule-ized". There is really no substitute for +line-by-line analysis when doing this, but the following checklist can +help: + +@itemize @bullet +@item +Check all uses of @code{XSTRING_DATA}. +@item +Check all uses of @code{build_string} and @code{make_string}. +@item +Check all uses of @code{tolower} and @code{toupper}. +@item +Check object print methods. +@item +Check for use of functions such as @code{write_c_string}, +@code{write_fmt_string}, @code{stderr_out}, @code{stdout_out}. +@item +Check all occurrences of @code{char} and correct to one of the other +typedefs described above. +@item +Check all existing uses of @code{TO_EXTERNAL_FORMAT}, +@code{TO_INTERNAL_FORMAT}, and any convenience macros (grep for +@samp{EXTERNAL_TO}, @samp{TO_EXTERNAL}, and @samp{TO_SIZED_EXTERNAL}). +@item +In Windows code, string literals may need to be encapsulated with @code{XETEXT}. +@end itemize + +@node CCL, Microsoft Windows-Related Multilingual Issues, Coding for Mule, Multilingual Support +@section CCL +@cindex CCL + +@example +MACHINE CODE: + +The machine code consists of a vector of 32-bit words. +The first such word specifies the start of the EOF section of the code; +this is the code executed to handle any stuff that needs to be done +(e.g. designating back to ASCII and left-to-right mode) after all +other encoded/decoded data has been written out. This is not used for +charset CCL programs. + +REGISTER: 0..7 -- referred by RRR or rrr + +OPERATOR BIT FIELD (27-bit): XXXXXXXXXXXXXXX RRR TTTTT + TTTTT (5-bit): operator type + RRR (3-bit): register number + XXXXXXXXXXXXXXXX (15-bit): + CCCCCCCCCCCCCCC: constant or address + 000000000000rrr: register number + +AAAA: 00000 + + 00001 - + 00010 * + 00011 / + 00100 % + 00101 & + 00110 | + 00111 ~ + + 01000 << + 01001 >> + 01010 <8 + 01011 >8 + 01100 // + 01101 not used + 01110 not used + 01111 not used + + 10000 < + 10001 > + 10010 == + 10011 <= + 10100 >= + 10101 != + +OPERATORS: TTTTT RRR XX.. + +SetCS: 00000 RRR C...C RRR = C...C +SetCL: 00001 RRR ..... RRR = c...c + c.............c +SetR: 00010 RRR ..rrr RRR = rrr +SetA: 00011 RRR ..rrr RRR = array[rrr] + C.............C size of array = C...C + c.............c contents = c...c + +Jump: 00100 000 c...c jump to c...c +JumpCond: 00101 RRR c...c if (!RRR) jump to c...c +WriteJump: 00110 RRR c...c Write1 RRR, jump to c...c +WriteReadJump: 00111 RRR c...c Write1, Read1 RRR, jump to c...c +WriteCJump: 01000 000 c...c Write1 C...C, jump to c...c + C...C +WriteCReadJump: 01001 RRR c...c Write1 C...C, Read1 RRR, + C.............C and jump to c...c +WriteSJump: 01010 000 c...c WriteS, jump to c...c + C.............C + S.............S + ... +WriteSReadJump: 01011 RRR c...c WriteS, Read1 RRR, jump to c...c + C.............C + S.............S + ... +WriteAReadJump: 01100 RRR c...c WriteA, Read1 RRR, jump to c...c + C.............C size of array = C...C + c.............c contents = c...c + ... +Branch: 01101 RRR C...C if (RRR >= 0 && RRR < C..) + c.............c branch to (RRR+1)th address +Read1: 01110 RRR ... read 1-byte to RRR +Read2: 01111 RRR ..rrr read 2-byte to RRR and rrr +ReadBranch: 10000 RRR C...C Read1 and Branch + c.............c + ... +Write1: 10001 RRR ..... write 1-byte RRR +Write2: 10010 RRR ..rrr write 2-byte RRR and rrr +WriteC: 10011 000 ..... write 1-char C...CC + C.............C +WriteS: 10100 000 ..... write C..-byte of string + C.............C + S.............S + ... +WriteA: 10101 RRR ..... write array[RRR] + C.............C size of array = C...C + c.............c contents = c...c + ... +End: 10110 000 ..... terminate the execution + +SetSelfCS: 10111 RRR C...C RRR AAAAA= C...C + ..........AAAAA +SetSelfCL: 11000 RRR ..... RRR AAAAA= c...c + c.............c + ..........AAAAA +SetSelfR: 11001 RRR ..Rrr RRR AAAAA= rrr + ..........AAAAA +SetExprCL: 11010 RRR ..Rrr RRR = rrr AAAAA c...c + c.............c + ..........AAAAA +SetExprR: 11011 RRR ..rrr RRR = rrr AAAAA Rrr + ............Rrr + ..........AAAAA +JumpCondC: 11100 RRR c...c if !(RRR AAAAA C..) jump to c...c + C.............C + ..........AAAAA +JumpCondR: 11101 RRR c...c if !(RRR AAAAA rrr) jump to c...c + ............rrr + ..........AAAAA +ReadJumpCondC: 11110 RRR c...c Read1 and JumpCondC + C.............C + ..........AAAAA +ReadJumpCondR: 11111 RRR c...c Read1 and JumpCondR + ............rrr + ..........AAAAA +@end example + +@node Microsoft Windows-Related Multilingual Issues, Modules for Internationalization, CCL, Multilingual Support +@section Microsoft Windows-Related Multilingual Issues +@cindex Microsoft Windows-related multilingual issues +@cindex Windows-related multilingual issues +@cindex multilingual issues, Windows-related + +@menu +* Microsoft Documentation:: +* Locales:: +* More about code pages:: +* More about locales:: +* Unicode support under Windows:: +* The golden rules of writing Unicode-safe code:: +* The format of the locale in setlocale():: +* Random other Windows I18N docs:: +@end menu + +@node Microsoft Documentation, Locales, Microsoft Windows-Related Multilingual Issues, Microsoft Windows-Related Multilingual Issues +@subsection Microsoft Documentation +@cindex Microsoft documentation + +Documentation on international support in Windows is scattered throughout MSDN. +Here are some good places to look: + +@enumerate +@item +C Runtime (CRT) intl support + +@enumerate +@item +Visual Tools and Languages -> Visual Studio 6.0 Documentation -> Visual C++ Documentation -> Using Visual C++ -> Run-Time Library Reference -> Internationalization +@item +Visual Tools and Languages -> Visual Studio 6.0 Documentation -> Visual C++ Documentation -> Using Visual C++ -> Run-Time Library Reference -> Global Constants -> Locale Categories +@item +Visual Tools and Languages -> Visual Studio 6.0 Documentation -> Visual C++ Documentation -> Using Visual C++ -> Run-Time Library Reference -> Appendixes -> Language and Country/Region Strings +@item +Visual Tools and Languages -> Visual Studio 6.0 Documentation -> Visual C++ Documentation -> Using Visual C++ -> Run-Time Library Reference -> Appendixes -> Generic-Text Mappings +@item +Function documentation for various functions: +Visual Tools and Languages -> Visual Studio 6.0 Documentation -> Visual C++ Documentation -> Using Visual C++ -> Run-Time Library Reference -> Alphabetic Function Reference +e.g. _setmbcp(), setlocale(), strcoll functions +@end enumerate + +@item +Win32 API intl support + +@enumerate +@item +Platform SDK Documentation -> Base Services -> International Features +@item +Platform SDK Documentation -> User Interface Services -> Windows User Interface -> User Input -> Keyboard Input -> Character Messages -> International Features +@item +Backgrounders -> Windows Platform -> Windows 2000 -> International Support in Microsoft Windows 2000 +@end enumerate + +@item +Microsoft Layer for Unicode + +Platform SDK Documentation -> Windows API -> Windows 95/98/Me Programming -> Windows 95/98/Me Overviews -> Microsoft Layer for Unicode on Windows 95/98/Me Systems + +@item +Look in the CRT sources! They come with VC++. See win32.c. +@end enumerate + +@node Locales, More about code pages, Microsoft Documentation, Microsoft Windows-Related Multilingual Issues +@subsection Locales, code pages, and other concepts of "language" +@cindex locales, code pages, and other concepts of "language" + +First, make sure you clearly understand the difference between the C +runtime library (CRT) and the Win32 API! See win32.c. + +There are various different ways of representing the vague concept +of "language", and it can be very confusing. So: + +@itemize @bullet +@item +The CRT library has the concept of "locale", which is a +combination of language and country, and which controls the way +currency and dates are displayed, the encoding of data, etc. + +@item +XEmacs has the concept of "language environment", more or less +like a locale; although currently in most cases it just refers to +the language, and no sub-language distinctions are +made. (Exceptions are with Chinese, which has different language +environments for Taiwan and mainland China, due to the different +encodings and writing systems.) + +@item +Windows has a number of different language concepts: + +@enumerate +@item +There are "languages" and "sublanguages", which correspond to +the languages and countries of the C library -- e.g. LANG_ENGLISH +and SUBLANG_ENGLISH_US. These are identified by 8-bit integers, +called the "primary language identifier" and "sublanguage +identifier", respectively. These are combined into a 16-bit +integer or "language identifier" by MAKELANGID(). + +@item +The language identifier in turn is combined with a "sort +identifier" (and optionally a "sort version") to yield a 32-bit +integer called a "locale identifier" (type LCID), which identifies +locales -- the primary means of distinguishing language/regional +settings and similar to C library locales. + +@item +A "code page" combines the XEmacs concepts of "charset" and "coding +system". It logically encompasses + +@itemize @minus +@item +a set of supported characters +@item +an enumeration associating each character with a code point, which +is a number or number pair; there may be disjoint ranges of numbers +supported +@item +a way of encoding a series of characters into a string of bytes +@end itemize + +Note that the first two properties correspond to an XEmacs "charset" +and the latter an XEmacs "coding system". + +Traditional encodings are either simple one-byte encodings, or +combination one-byte/two-byte encodings (aka MBCS encodings, where MBCS +stands for "Multibyte Character Set") with the following properties: + +@itemize @minus +@item +all characters are encoded as a one-byte or two-byte sequence +@item +the encoding is stateless (non-modal) +@item +the lower 128 bytes are compatible with ASCII +@item +in the higher bytes, the value of the first byte ("lead byte") +determines whether a second byte follows +@item +the values used for second bytes may overlap those used for first +bytes, and (in some encodings) include values in the low half; thus, +moving backwards is hard, and pure-ASCII algorithms (e.g. finding the +next slash) will fail unless rewritten to be MBCS-aware (neither of +these problems exist in UTF-8 or in the XEmacs internal string +encoding) +@end itemize + +Recent code pages, however, do not necessarily follow these properties -- +code pages have been expanded to include arbitrary encodings, such as +UTF-8 (may have more than two bytes per character) and ISO-2022-JP +(complex modal encoding). + +@item +Every Windows locale has four associated code pages: ANSI (an +international standard or some Microsoft-created approximation; the +native code page under Windows), OEM (a DOS encoding, still used in the +FAT file system), Mac (an encoding used on the Macintosh) and EBCDIC (a +non-ASCII-compatible encoding used on IBM mainframes, originally based +on the BCD or "binary-coded decimal" encoding of numbers). All code +pages associated with a locale follow (as far as I know) the properties +listed above for traditional code pages. More than one locale can share +a code page -- e.g. all the Western European languages, including +English, do. + +@item +Windows also has an "input locale identifier" (aka "keyboard +layout id") or HKL, which is a 32-bit integer composed of the +16-bit language identifier and a 16-bit "device identifier", which +originally specified a particular keyboard layout (e.g. the locale +"US English" can have the QWERTY layout, the Dvorak layout, etc.), +but has been expanded to include speech-to-text converters and +other non-keyboard ways of inputting text. Note that both the HKL +and LCID share the language identifier in the lower 16 bits, and in +both cases a 0 in the upper 16 bits means "default" (sort order or +device), providing a way to convert between HKL's, LCID's, and +language identifiers (i.e. language/sublanguage pairs). The +default keyboard layout for a language is (as far as I can +determine) established using the Regional Settings control panel +applet, where you can add input locales as combinations of language +(actually language/sublanguage) and layout; presumably if you list +only one input locale with a particular language, the corresponding +layout is the default for that language. But what if you list more +than one? You can specify a single default input locale, but there +appears to be no way to do so on a per-language basis. +@end enumerate +@end itemize + +@node More about code pages, More about locales, Locales, Microsoft Windows-Related Multilingual Issues +@subsection More about code pages +@cindex more about code pages + +Here is what MSDN says about code pages (article "Code Pages"): + +@quotation +A code page is a character set, which can include numbers, +punctuation marks, and other glyphs. Different languages and locales +may use different code pages. For example, ANSI code page 1252 is +used for American English and most European languages; OEM code page +932 is used for Japanese Kanji. + +A code page can be represented in a table as a mapping of characters +to single-byte values or multibyte values. Many code pages share the +ASCII character set for characters in the range 0x00 ?0x7F. + +The Microsoft run-time library uses the following types of code pages: + +-- System-default ANSI code page. By default, at startup the run-time +system automatically sets the multibyte code page to the +system-default ANSI code page, which is obtained from the operating +system. The call + +setlocale ( LC_ALL, "" ); + +also sets the locale to the system-default ANSI code page. + +-- Locale code page. The behavior of a number of run-time routines is +dependent on the current locale setting, which includes the locale +code page. (For more information, see Locale-Dependent Routines.) By +default, all locale-dependent routines in the Microsoft run-time +library use the code page that corresponds to the ¡ë?locale. At +run-time you can change or query the locale code page in use with a +call to setlocale. + +-- Multibyte code page. The behavior of most of the multibyte-character +routines in the run-time library depends on the current multibyte +code page setting. By default, these routines use the system-default +ANSI code page. At run-time you can query and change the multibyte +code page with _getmbcp and _setmbcp, respectively. + +-- The "C" locale is defined by ANSI to correspond to the locale in +which C programs have traditionally executed. The code page for the +"C" locale (¡ë?code page) corresponds to the ASCII character +set. For example, in the "C" locale, islower returns true for the +values 0x61 ?0x7A only. In another locale, islower may return true +for these as well as other values, as defined by that locale. + +Under "Locale-Dependent Routines" we notice the following setlocale +dependencies: + +atof, atoi, atol (LC_NUMERIC) +is Routines (LC_CTYPE) +isleadbyte (LC_CTYPE) +localeconv (LC_MONETARY, LC_NUMERIC) +MB_CUR_MAX (LC_CTYPE) +_mbccpy (LC_CTYPE) +_mbclen (LC_CTYPE) +mblen (LC_CTYPE ) +_mbstrlen (LC_CTYPE) +mbstowcs (LC_CTYPE) +mbtowc (LC_CTYPE) +printf (LC_NUMERIC, for radix character output) +scanf (LC_NUMERIC, for radix character recognition) +setlocale/_wsetlocale (Not applicable) +strcoll (LC_COLLATE) +_stricoll/_wcsicoll (LC_COLLATE) +_strncoll/_wcsncoll (LC_COLLATE) +_strnicoll/_wcsnicoll (LC_COLLATE) +strftime, wcsftime (LC_TIME) +_strlwr (LC_CTYPE) +strtod/wcstod/strol/wcstol/strtoul/wcstoul (LC_NUMERIC, for radix character recognition) +_strupr (LC_CTYPE) +strxfrm/wcsxfrm (LC_COLLATE) +tolower/towlower (LC_CTYPE) +toupper/towupper (LC_CTYPE) +wcstombs (LC_CTYPE) +wctomb (LC_CTYPE) +_wtoi/_wtol (LC_NUMERIC) +@end quotation + +NOTE: The above documentation doesn't clearly explain the "locale code +page" and "multibyte code page". These are two different values, +maintained respectively in the CRT global variables __lc_codepage and +__mbcodepage. Calling e.g. setlocale (LC_ALL, "JAPANESE") sets @strong{ONLY} +__lc_codepage to 932 (the code page for Japanese), and leaves +__mbcodepage unchanged (usually 1252, i.e. Windows-ANSI). You'd have to +call _setmbcp() to change __mbcodepage. Figuring out from the +documentation which routines use which code page is not so obvious. But: + +@itemize @bullet +@item +from "Interpretation of Multibyte-Character Sequences" it appears that +all "multibyte-character routines" use the multibyte code page except for +mblen(), _mbstrlen(), mbstowcs(), mbtowc(), wcstombs(), and wctomb(). + +@item +from "_setmbcp": "The multibyte code page also affects +multibyte-character processing by the following run-time library +routines: _exec functions _mktemp _stat _fullpath _spawn functions +_tempnam _makepath _splitpath tmpnam. In addition, all run-time library +routines that receive multibyte-character argv or envp program arguments +as parameters (such as the _exec and _spawn families) process these +strings according to the multibyte code page. Hence these routines are +also affected by a call to _setmbcp that changes the multibyte code +page." +@end itemize + +Summary: from looking at the CRT source (which comes with VC++) and +carefully looking through the docs, it appears that: + +@itemize @bullet +@item +the "locale code page" is used by all of the routines listed above +under "Locale-Dependent Routines" (EXCEPT _mbccpy() and _mbclen()), +as well as any other place that converts between multibyte and Unicode +strings, e.g. the startup code. +@item +the "multibyte code page" is used in all of the *mb*() routines +except mblen(), _mbstrlen(), mbstowcs(), mbtowc(), wcstombs(), +and wctomb(); also _exec*(), _spawn*(), _mktemp(), _stat(), _fullpath(), +_tempnam(), _makepath(), _splitpath(), tmpnam(), and similar functions +without the leading underscore. +@end itemize + +@node More about locales, Unicode support under Windows, More about code pages, Microsoft Windows-Related Multilingual Issues +@subsection More about locales +@cindex more about locales + +In addition to the locale defined by the CRT, Windows (i.e. the Win32 API) +defines various locales: + +@itemize @bullet +@item +The system-default locale is the locale defined under "Language +settings for the system" in the "Regional Options" control panel. This +is NOT user-specific, and changing it requires a reboot (at least under +Windows 2000). The ANSI code page of the system-default locale is +returned by GetACP(), and you can specify this code page in calls +e.g. to MultiByteToWideChar with the constant CP_ACP. + +@item +The user-default locale is the locale defined under "Settings for the +current user" in the "Regional Options" control panel. + +@item +There is a thread-local locale set by SetThreadLocale. #### What is this +used for? +@end itemize + +The Win32 API has a bunch of multibyte functions -- all of those that +end with ...A(), and on which we spend so much effort in +intl-encap-win32.c. These appear to ALWAYS use the ANSI code page of +the system-default locale (GetACP(), CP_ACP). Note that this applies +also, for example, to the encoding of filenames in all file-handling +routines, including the CRT ones such as open(), because they pass their +args unchanged to the Win32 API. + +@node Unicode support under Windows, The golden rules of writing Unicode-safe code, More about locales, Microsoft Windows-Related Multilingual Issues +@subsection Unicode support under Windows +@cindex unicode support under windows + +Basically, the whole concept of locales and code pages is broken, because +it is extremely messy to support and does not allow for documents that use +multiple languages simultaneously. Unicode was designed in response to +this, the idea being to create a single character set that could be used to +encode all the world's languages. Windows has supported Unicode since the +beginning of the Win32 API. Internally, every code page has an associated +table to convert the characters of that code page to and from Unicode, and +the Win32 API itself probably (perhaps always) uses Unicode internally. + +Under Windows there are two different versions of all library routines that +accept or return text, those that handle Unicode text and those handling +"multibyte" text, i.e. variable-width ASCII-compatible text in some +national format such as EUC or Shift-JIS. Because Windows 95 basically +doesn't support Unicode but Windows NT does, and Microsoft doesn't provide +any way of writing a single binary that will work on both systems and still +use Unicode when it's available (although see below, Microsoft Layer for +Unicode), we need to provide a way of run-time conditionalizing so you +could have one binary for both systems. "Unicode-splitting" refers to +writing code that will handle this properly. This means using +Qmswindows_tstr as the external conversion format, calling the appropriate +qxe...() Unicode-split version of library functions, and doing other things +in certain cases, e.g. when a qxe() function is not present. + +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 @bullet +@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, and +also with types, where the generic types have names beginning with T -- +TCHAR, LPTSTR, etc.. 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 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 (you can force use of the A calls on NT, +e.g. for testing purposes, using the command- line switch -nuni aka +-no-unicode-lib-calls), 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. +@end itemize + +NOTE NOTE NOTE: As of August 2001, Microsoft (finally! See my nasty +comment above) released their own Unicode-encapsulation library, called +Microsoft Layer for Unicode on Windows 95/98/Me Systems. It tries to be +more transparent than we are, in that + +@itemize @bullet +@item +its routines do ANSI/Unicode string translation, while we don't, for +efficiency (we already have to do internal/external conversion so it's +no extra burden to do the proper conversion directly rather than always +converting to Unicode and then doing a second conversion to ANSI as +necessary) + +@item +rather than requiring separately-named routines (qxeFooBar), they +physically override the existing routines at the link level. it also +appears that they do this BADLY, in that if you link with the MLU, you +get an application that runs ONLY on Win9x!!! (hint -- use +GetProcAddress()). there's still no way to create a single binary! +fucking losers. + +@item +they assume you compile with UNICODE defined, so there's no need for the +application to explicitly use ...W structures, as we require. + +@item +they also intercept windows procedures to deal with notify messages as +necessary, which we don't do yet. + +@item +they (of course) don't use Extbyte. +@end itemize + +at some point (especially when they fix the single-binary problem!), we +should consider switching. for the meantime, we'll stick with what i've +already written. perhaps we should think about adopting some of the +greater transparency they have; but i opted against transparency on +purpose, to make the code easier to follow for someone who's not familiar +with it. until our library is really complete and bug-free, we should +think twice before doing this. + +According to Microsoft documentation, only the following functions are +provided under Windows 9x to support Unicode (see MSDN page "Windows +95/98/Me General Limitations"): + +EnumResourceLanguagesW +EnumResourceNamesW +EnumResourceTypesW +ExtTextOutW +FindResourceW +FindResourceExW +GetCharWidthW +GetCommandLineW +GetTextExtentPointW +GetTextExtentPoint32W +lstrcatW +lstrcpyW +lstrlenW +MessageBoxW +MessageBoxExW +MultiByteToWideChar +TextOutW +WideCharToMultiByte + +also maybe GetTextExtentExPoint? (KB Q125671 "Unicode Functions Supported +by Windows 95") + +Q210341 says this in addition: + +@quotation +SUMMARY: + +Although Windows 95 is an eight-bit ANSI, or for Far East Windows, a +Multibyte (MBCS) character set operating system, it implements a few +Unicode functions. Windows 98 has added support for a few more +functions and there are techniques to implement additional Unicode +support. + +MORE INFORMATION: + +Windows 95 is natively an eight-bit character code operating +system. That is, it fundamentally processes all character strings one +byte at a time. Far East versions of Windows 95 are called Multibyte +Character Set (MBCS) systems because they use a signal or lead byte +combined with a second trailing byte to expand the character code +range beyond the 256 limitation of a one-byte representation. + +The Unicode standard offers application developers an opportunity to +work with text without the limitations of character set based +systems. For more information on the Unicode standard see the +"References" section of this article. Windows NT is a fully Unicode +capable operating system so it may be desirable to write software that +supports Unicode on Windows 95. + +Even though Windows 95 and Windows 98 are not Unicode based, they do +provide some limited Unicode functionality. Drawing of Unicode text is +possible because the TrueType fonts that are used by Windows are +encoded using Unicode. Therefore, a small subset of Win32 functions +have wide character (Unicode) equivalents that are implemented in +Windows 95. To review the list of these functions that was first +published for Windows 95 see the white paper listed in the +"References" section of this article. + +The Quick Info information in the Platform SDK describes the following +wide character functions as implemented on Windows 95: + +[same list as above minus GetTextExtentExPoint, and minus lstrcpy/lstrcat] + +For Windows 98, there have been two more functions implemented: + +[lstrcpyW/lstrcatW] + +Also available to applications on Windows 95 and later is the +CF_UNICODETEXT clipboard format for exchanging/converting Unicode text +across the clipboard. See Nadine Kano's book listed in the +"References" section of this article. + +With this API subset, an application can read, write, display, and +convert Unicode data. However, in some cases an application developer +working with Unicode may find a need to work directly with the glyphs +in the TrueType font file. + +Such a case arises if a software developer would like to use the +services of the GetGlyphOutline() function. Unfortunately, there is no +wide character implementation of this function on Windows 95. However, +this function does work with TrueType glyph indices so the solution is +convert the Unicode character code to a glyph index. + +A developer might also want to take advantage of the TrueType Open +tables of a font to perform ligature or contextual glyph +substitution. To do this, the application would need to work with +glyph indices. See the "References" section of this article for more +information on converting Unicode to glyph indices. + +REFERENCES: + +For additional information about Unicode and the GetGlyphOutline +function, click the article number below to view the article in the +Microsoft Knowledge Base: + +241358 PRB: The GetGlyphOutlineW Function Fails on Windows 95 and +Windows 98 + +For additional information about converting Unicode character codes, +click the article number below to view the article in the Microsoft +Knowledge Base: + +241020 HOWTO: Translate Unicode Character Codes to TrueType Glyph +Indices in Windows 95 + +For information on writing applications for world wide markets, please +see the following book: + +Developing International Software for Windows 95 and Windows NT by +Nadine Kano. +ISBN 1-55615-840-8 +Microsoft Press. +Also available on MSDN in the Books section. + +Background white paper: Differences in Win32 API Implementations Among +Windows Operating Systems by Noel Nyman. + +Available on MSDN in the Windows Platform Guidelines section +@end quotation + +However, the C runtime library provides some additional support (according +to the CRT sources, as the docs are not very clear on this): + +@itemize @bullet +@item +wmain() is completely supported, and appropriate Unicode-formatted argv +and envp will always be passed. +@item +Likewise, wWinMain() is completely supported. (NOTE: The docs are not at +all clear on how these various entry points interact, and implies that +a windows-subsystem program "must" use WinMain(), while a console- +subsystem program "must" use main(), and a program compiled with UNICODE +(which we don't, see above) "must" use the w*() versions, while a program +not compiled this way "must" use the plain versions. In fact it appears +that the CRT provides four different compiler entry points, namely +w?(main|WinMain)CRTStartup, and we simply choose the one we like using +the appropriate link flag. +@item +_wenviron, _wputenv +@end itemize + +NOTE: + +@itemize @bullet +@item +wsetargv.obj uses routines that were buggily left out of MSVCRT; anyway, +from looking at the source, it does NOT correctly work under Win 9x as +it blindly calls the Unicode version of Unicode-split API's such as +FindFirstFile) + +@item +the w*() file routines are @strong{NOT} supported -- or at least, they blindly +call the ...W() versions of the Win32 API calls. +@end itemize + +@node The golden rules of writing Unicode-safe code, The format of the locale in setlocale(), Unicode support under Windows, Microsoft Windows-Related Multilingual Issues +@subsection The golden rules of writing Unicode-safe code +@cindex the golden rules of writing unicode-safe code + +@itemize @bullet +@item +There are no preprocessor games going on. + +@item +Do not set the UNICODE constant. + +@item +You need to change your code to call the Windows API prefixed with "qxe" +functions (when they exist) and use the ...W structs instead of the +generic ones. String arguments in the qxe functions are of type Extbyte +*. + +@item +You code is responsible for conversion of text arguments. We try to +handle everything else -- the argument differences, the copying back and +forth of structures, etc. Use Qmswindows_tstr and macros such as +C_STRING_TO_TSTR. You are also responsible for interpreting and +specifying string sizes, which have not been changed. Usually these are +in characters, meaning you need to divide by XETCHAR_SIZE. (But, some +functions want sizes in bytes, even with Unicode strings. Look in the +documentation.) Use XETEXT when specifying string constants, so that +they show up in Unicode as necessary. + +@item +If you need to process external strings (in general you should not do +this; do all your manipulations in internal format and convert at the +point of entry into or exit from the function), use the xet...() +functions. + +@item +If you have to declare a fixed array to hold a string coming from +Windows (and hence either multibyte or Unicode), declare it of type +Extbyte[] and multiply the size by MAX_XETCHAR_SIZE. +@end itemize + +@node The format of the locale in setlocale(), Random other Windows I18N docs, The golden rules of writing Unicode-safe code, Microsoft Windows-Related Multilingual Issues +@subsection The format of the locale in setlocale() +@cindex the format of the locale in setlocale() + +It appears that under Unix the standard format for the string in +setlocale() involves two-letter language and country abbreviations, e.g. +ja or ja_jp or ja_jp.euc for Japanese. Windows (MSDN article "Language +Strings" in the run-time reference appendix, see doc list above) speaks +of "(primary) language" and "sublanguage" (usually a country, but in the +case of Chinese the sublanguage is "simplified" or "traditional"). It +is highly flexible in what it takes, and thankfully it canonicalizes the +result to a unique form "Language_Country.Encoding". It allows (note +that all specifications can be in any case): + +@itemize @bullet +@item +the full "language_country.encoding" specification or just +language_country", in which case the default encoding will be chosen. + +@item +a three-letter acronym, consisting of the ISO-standard two-letter +language abbreviation followed by a third letter indicating the +sublanguage. + +@item +just a language name, e.g. "dutch", standing for the combination of +the language with "default" as sublanguage, referring to the default +(often "prototypical") country for that language (in this case the +Netherlands). You can abbreviate the name by removing any number of +letters from the end. Ambiguity is not a problem: Even specifying +just a single letter is valid providing any language starting with +that letter exists, but the result may not be what you want (e.g. "c" +maps to "catalan", not "chinese", "czech", etc.). The way of +resolving ambiguity appears fairly random -- it's not alphabetical +("a" maps to "arabic" not "albanian"). + +@item +a combination of language and sublanguage separated by a hyphen, +e.g. "dutch-belgian"; note that the sublanguage designator in this +case is NOT necessarily the same as the country, e.g. "belgian" vs. +"belgium". "dutch-belgium" (or even "dutch-belg") does @strong{NOT} get you +the right result, but returns "Dutch_Netherlands.1252" instead! This +is because, although you may not abbreviate the result, Windows +accepts any unknown value in the sublanguage field and treats it as +equivalent to "default". Note also that the if the sublanguage name +has underscores in it, you need to change them to spaces, e.g. +"spanish-dominican republic". + +@item +sometimes, just a sublanguage name, e.g. "belgian", standing for +the combination of one of the languages spoken in that region and +the sublanguage of the region -- in this case Dutch. Note that +there is no guarantee of "protypicality" in this case in choice of +language! You could hardly say that Dutch (aka Flemish) is more +prototypical of Belgium than French. You cannot abbreviate this +form, if it's allowed at all. +@end itemize + +In addition: + +@itemize @bullet +@item +note further that you are not limited to the language/sublanguage +combinations predefined by Windows. You can set weird combinations +like "Chinese_Kenya.1255" (Chinese spoken in Kenya, represented by +Windows-1255, i.e. Hebrew!) and Windows don't complain, despite the +language-encoding inconsistency. You can also make up a weird +combination and leave out the encoding, e.g. "Chinese_Qatar", which +maps to "Chinese_Qatar.1256", where Windows-1256 is Arabic -- i.e. it +appears to be choosing the encoding based on a default for the +country. + +@item +note also that the names for countries are often not what you expect. +"urdu_pakistan" fails, and just "urdu" shows why, as it maps to +"Urdu_Islamic Republic of Pakistan.1256". That is, some countries +exist in their full name, and the canonicalized form with underscore +is not very forgiving in its handling of country specifications. +Similarly, Uzbekistan is "Republic of Uzbekistan", and "China" is +"People's Republic of China" -- but in this latter case, unlike the +other two, just "China" works as an alias, e.g. "uzbek_china" maps +to "Uzbek_People's Republic of China.936". + +@item +note that just the two-letter ISO language code is NOT allowed. +Sometimes you'll get lucky (e.g. "fr" does map to "france"), but +sometimes you'll get no match (e.g. "pl"), and sometimes you'll get +really unlucky in that the call will succeed but with the wrong +language (e.g. "es" maps to "estonian", not "spanish"). +@end itemize + +As an example, MSDN article "Language Strings" indicates that German +(default) can be specified using "deu" or "german"; German (Austrian) +with "dea" or "german-austrian"; German (Swiss) with "des", +"german-swiss", or "swiss"; French (Swiss) with "french-swiss" or "frs"; +and English (USA) with "american", "american english", +"american-english", "english-american", "english-us", "english-usa", +"enu", "us", or "usa". This is not, of course, an exhaustive list even +for just the given locales -- just "english" works in practice because +English (Default) maps to English (USA). (#### Is this always the case?) + +Given the canonicalization, we don't have to worry too much about the +different kinds of inputs to setlocale() -- unlike for Unix, where no +canonicalization is usually performed, the particular locales that +exist vary tremendously from OS to OS, and we need to parse the +uncanonicalized locale spec, directly from the user, to figure out the +encoding to use, making various guesses if not enough information is +present. Yuck! The tricky thing under Windows is figuring how to +deal with the sublang. It appears that the trick of simply passing the +text of the manifest constant itself of the sublang, with appropriate +hacking (e.g. of underscore to space), works most of the time. + +@node Random other Windows I18N docs, , The format of the locale in setlocale(), Microsoft Windows-Related Multilingual Issues +@subsection Random other Windows I18N docs +@cindex random other windows i18n docs + +Introduction to Internationalization Issues in the Win32 API + +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 +TCHARs. There is a type LPTSTR which is defined to be a string of +TCHARs and another type LPCTSTR which is a const string of TCHARs. The +theory is that any program that uses TCHARs 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. + +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. + +@node Modules for Internationalization, , Microsoft Windows-Related Multilingual Issues, Multilingual Support +@section Modules for Internationalization +@cindex modules for internationalization +@cindex internationalization, modules for + +@example +@file{mule-canna.c} +@file{mule-ccl.c} +@file{mule-charset.c} +@file{mule-charset.h} +@file{file-coding.c} +@file{file-coding.h} +@file{mule-coding.c} +@file{mule-mcpath.c} +@file{mule-mcpath.h} +@file{mule-wnnfns.c} +@file{mule.c} +@end example + +These files implement the MULE (Asian-language) support. Note that MULE +actually provides a general interface for all sorts of languages, not +just Asian languages (although they are generally the most complicated +to support). This code is still in beta. + +@file{mule-charset.*} and @file{file-coding.*} provide the heart of the +XEmacs MULE support. @file{mule-charset.*} implements the @dfn{charset} +Lisp object type, which encapsulates a character set (an ordered one- or +two-dimensional set of characters, such as US ASCII or JISX0208 Japanese +Kanji). + +@file{file-coding.*} implements the @dfn{coding-system} Lisp object +type, which encapsulates a method of converting between different +encodings. An encoding is a representation of a stream of characters, +possibly from multiple character sets, using a stream of bytes or words, +and defines (e.g.) which escape sequences are used to specify particular +character sets, how the indices for a character are converted into bytes +(sometimes this involves setting the high bit; sometimes complicated +rearranging of the values takes place, as in the Shift-JIS encoding), +etc. It also contains some generic coding system implementations, such +as the binary (no-conversion) coding system and a sample gzip coding system. + +@file{mule-coding.c} contains the implementations of text coding systems. + +@file{mule-ccl.c} provides the CCL (Code Conversion Language) +interpreter. CCL is similar in spirit to Lisp byte code and is used to +implement converters for custom encodings. + +@file{mule-canna.c} and @file{mule-wnnfns.c} implement interfaces to +external programs used to implement the Canna and WNN input methods, +respectively. This is currently in beta. + +@file{mule-mcpath.c} provides some functions to allow for pathnames +containing extended characters. This code is fragmentary, obsolete, and +completely non-working. Instead, @code{pathname-coding-system} is used +to specify conversions of names of files and directories. The standard +C I/O functions like @samp{open()} are wrapped so that conversion occurs +automatically. + +@file{mule.c} contains a few miscellaneous things. It currently seems +to be unused and probably should be removed. + + + +@example +@file{intl.c} +@end example + +This provides some miscellaneous internationalization code for +implementing message translation and interfacing to the Ximp input +method. None of this code is currently working. + + + +@example +@file{iso-wide.h} +@end example + +This contains leftover code from an earlier implementation of +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 +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 @code{nil}. +@end table + +@node Modules for the Basic Displayable Lisp Objects, , The Window Object, Consoles; Devices; Frames; Windows +@section Modules for the Basic Displayable Lisp Objects +@cindex modules for the basic displayable Lisp objects +@cindex displayable Lisp objects, modules for the basic +@cindex Lisp objects, modules for the basic displayable +@cindex objects, modules for the basic displayable Lisp + +@example +@file{console-msw.c} +@file{console-msw.h} +@file{console-stream.c} +@file{console-stream.h} +@file{console-tty.c} +@file{console-tty.h} +@file{console-x.c} +@file{console-x.h} +@file{console.c} +@file{console.h} +@end example + +These modules implement the @dfn{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. + +@strong{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. + + + +@example +@file{device-msw.c} +@file{device-tty.c} +@file{device-x.c} +@file{device.c} +@file{device.h} +@end example + +These modules implement the @dfn{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. + +@strong{This abstraction is probably broken} (as of late 2004), at least +for X consoles, with the advent of the @strong{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 +@emph{client-side} code. These glyphs are then transmitted to the +server as sets of trapezoids, and displayed by the @strong{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 @emph{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 (@emph{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. + +@enumerate +@item +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). + +@item +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. +@end enumerate + + + +@example +@file{frame-msw.c} +@file{frame-tty.c} +@file{frame-x.c} +@file{frame.c} +@file{frame.h} +@end example + +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 @file{frame-*} files implement the @dfn{frame} Lisp object type and +provide the generic and device-type-specific operations on frames +(e.g. raising, lowering, resizing, moving, etc.). + + + +@example +@file{window.c} +@file{window.h} +@end example + +@cindex window (in Emacs) +@cindex pane +Each frame consists of one or more non-overlapping @dfn{windows} (better +known as @dfn{panes} in standard window-system terminology) in which a +buffer's text can be displayed. Windows can also have scrollbars +displayed around their edges. + +@file{window.c} and @file{window.h} implement the @dfn{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. + +@node The Redisplay Mechanism, Extents, Consoles; Devices; Frames; Windows, Top +@chapter The Redisplay Mechanism +@cindex redisplay mechanism, the + + 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: + +@enumerate +@item +It Is Better To Be Correct Than Fast. +@item +Thou Shalt Not Run Elisp From Within Redisplay. +@item +It Is Better To Be Fast Than Not To Be. +@end enumerate + +@menu +* Critical Redisplay Sections:: +* Line Start Cache:: +* Redisplay Piece by Piece:: +* Modules for the Redisplay Mechanism:: +* Modules for other Display-Related Lisp Objects:: +@end menu + +@node Critical Redisplay Sections, Line Start Cache, The Redisplay Mechanism, The Redisplay Mechanism +@section Critical Redisplay Sections +@cindex redisplay sections, critical +@cindex critical redisplay sections + + +@strong{The following paragraphs are way out-of-date and inaccurate.} + +Within this section, we are defenseless and assume that the +following cannot happen: + +@enumerate +@item +garbage collection +@item +Lisp code evaluation +@item +frame size changes +@end enumerate + +We ensure (3) by calling @code{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 @code{Fsignal()} is called during this critical section, we +will @code{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. + +@strong{Begin up-to-date stuff} + +@subsection Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT + +These are now fixed as of November 10, 2004. + +@subheading Crash -- reentrant @code{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. + +@example + +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 #<INTERNAL OBJECT (XEmacs bug?) (opaque, size=0) 0x1468938> ...) + # (unwind-protect ...) + # bind (inhibit-quit) + window-end(#<window on "signal.c<2>" 0x5e4a> t) + # (unwind-protect ...) + # bind (buffer we-are-screwed check-text-props window) + lazy-lock-fontify-window(#<window on "signal.c<2>" 0x5e4a>) + # bind (walk-windows-current walk-windows-start arg which-devices which-frames + minibuf function) + walk-windows(lazy-lock-fontify-window no-minibuf #<mswindows-frame "emacs" 0x5 +e49>) + # (unwind-protect ...) + # bind (ssf65112 tick frame) + lazy-lock-maybe-fontify-frame(#<mswindows-frame "emacs" 0x5e49>) + # 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 #<INTERNAL OBJECT (XEmacs bug?) (opaque, size=0) 0x1468938> ...) + # (unwind-protect ...) + # (unwind-protect ...) + # bind (inhibit-quit) + # (unwind-protect ...) + # (unwind-protect ...) + # bind (inhibit-quit) + (next-event "[internal]") + # (condition-case ... . error) + # (catch top-level ...) +@end example + +@subsubheading Another Lisp trace of a similar situation (C stack trace not available): + +@example +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((#<window on "*grep*" 0x1a5f9>)) + (dispatch-event "[internal]") + # (unwind-protect ...) + # (catch #<INTERNAL OBJECT (XEmacs bug?) (opaque, size=0) 0x1468270> ...) + # (unwind-protect ...) + # (unwind-protect ...) + # (catch #<INTERNAL OBJECT (XEmacs bug?) (opaque, size=0) 0x1468270> ...) + # (unwind-protect ...) + # bind (inhibit-quit) + window-end(#<window on "*grep*" 0x1a5f9> t) + # (unwind-protect ...) + # bind (buffer we-are-screwed check-text-props window) + lazy-lock-fontify-window(#<window on "*grep*" 0x1a5f9>) + # bind (walk-windows-current walk-windows-start arg which-devices which-frames + minibuf function) + walk-windows(lazy-lock-fontify-window no-minibuf #<mswindows-frame "emacs" 0x1 +9f64>) + # (unwind-protect ...) + # bind (ssf65112 tick frame) + lazy-lock-maybe-fontify-frame(#<mswindows-frame "emacs" 0x19f64>) + # 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 #<INTERNAL OBJECT (XEmacs bug?) (opaque, size=0) 0x1468270> ...) + # (unwind-protect ...) + # (unwind-protect ...) + # bind (inhibit-quit) + # (unwind-protect ...) + # (unwind-protect ...) + # bind (inhibit-quit) + (next-event "[internal]") + # (condition-case ... . error) + # (catch top-level ...) +@end example + +@subheading Crash -- reentrant @code{generate_displayable_area()} + +Original code said [Tricky tricky tricky. +@code{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() + +@node Line Start Cache, Redisplay Piece by Piece, Critical Redisplay Sections, The Redisplay Mechanism +@section Line Start Cache +@cindex 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: + +@itemize @bullet +@item +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. +@item +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. +@end itemize + + In case you're wondering, the Second Golden Rule of Redisplay is not +applicable. + +@node Redisplay Piece by Piece, Modules for the Redisplay Mechanism, Line Start Cache, The Redisplay Mechanism +@section Redisplay Piece by Piece +@cindex 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: + +@enumerate +@item +Determine desired display in area that needs redisplay. +Implemented by @code{redisplay.c} +@item +Compare desired display with current display +Implemented by @code{redisplay-output.c} +@item +Output changes Implemented by @code{redisplay-output.c}, +@code{redisplay-x.c}, @code{redisplay-msw.c} and @code{redisplay-tty.c} +@end enumerate + +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 @code{display_line} structures. Each +@code{display_line} consists of a set of @code{display_block}'s and each +@code{display_block} contains a number of @code{rune}'s. Generally +dynarr's of @code{display_line}'s are held by each window representing +the current display and the desired display. + +The @code{display_line} structures are tightly tied to buffers which +presents a problem for redisplay as this connection is bogus for the +modeline. Hence the @code{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 @code{display_line} generation are in +@code{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 @code{create_text_block}. Instead we use +@code{create_text_string_block} which performs the same function as +@code{create_text_block} but for strings. Many of the complexities of +@code{create_text_block} to do with cursor handling and selective +display have been removed. + +@node Modules for the Redisplay Mechanism, Modules for other Display-Related Lisp Objects, Redisplay Piece by Piece, The Redisplay Mechanism +@section Modules for the Redisplay Mechanism +@cindex modules for the redisplay mechanism +@cindex redisplay mechanism, modules for the + +@example +@file{redisplay-output.c} +@file{redisplay-msw.c} +@file{redisplay-tty.c} +@file{redisplay-x.c} +@file{redisplay.c} +@file{redisplay.h} +@end example + +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. + +@file{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. + +@file{redisplay-output.c} goes through the redisplay structures and converts +them into calls to device-specific methods to actually output the screen +changes. + +@file{redisplay-x.c} and @file{redisplay-tty.c} are two implementations +of these redisplay output methods, for X frames and TTY frames, +respectively. + + + +@example +@file{indent.c} +@end example + +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. + + + +@example +@file{termcap.c} +@file{terminfo.c} +@file{tparam.c} +@end example + +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. + + + +@example +@file{cm.c} +@file{cm.h} +@end example + +These files provide some miscellaneous TTY-output functions and should +probably be merged into @file{redisplay-tty.c}. + + + +@node Modules for other Display-Related Lisp Objects, , Modules for the Redisplay Mechanism, The Redisplay Mechanism +@section Modules for other Display-Related Lisp Objects +@cindex modules for other display-related Lisp objects +@cindex display-related Lisp objects, modules for other +@cindex Lisp objects, modules for other display-related + +@example +@file{faces.c} +@file{faces.h} +@end example + + + +@example +@file{bitmaps.h} +@file{glyphs-eimage.c} +@file{glyphs-msw.c} +@file{glyphs-msw.h} +@file{glyphs-widget.c} +@file{glyphs-x.c} +@file{glyphs-x.h} +@file{glyphs.c} +@file{glyphs.h} +@end example + + + +@example +@file{objects-msw.c} +@file{objects-msw.h} +@file{objects-tty.c} +@file{objects-tty.h} +@file{objects-x.c} +@file{objects-x.h} +@file{objects.c} +@file{objects.h} +@end example + + + +@example +@file{menubar-msw.c} +@file{menubar-msw.h} +@file{menubar-x.c} +@file{menubar.c} +@file{menubar.h} +@end example + + + +@example +@file{scrollbar-msw.c} +@file{scrollbar-msw.h} +@file{scrollbar-x.c} +@file{scrollbar-x.h} +@file{scrollbar.c} +@file{scrollbar.h} +@end example + + + +@example +@file{toolbar-msw.c} +@file{toolbar-x.c} +@file{toolbar.c} +@file{toolbar.h} +@end example + + + +@example +@file{font-lock.c} +@end example + +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. + + + +@example +@file{dgif_lib.c} +@file{gif_err.c} +@file{gif_lib.h} +@file{gifalloc.c} +@end example + +These modules decode GIF-format image files, for use with glyphs. +These files were removed due to Unisys patent infringement concerns. + + +@node Extents, Faces, The Redisplay Mechanism, Top +@chapter Extents +@cindex 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. +@end menu + +@node Introduction to Extents, Extent Ordering, Extents, Extents +@section Introduction to Extents +@cindex extents, introduction to + + 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 @file{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.) + +@node Extent Ordering, Format of the Extent Info, Introduction to Extents, Extents +@section Extent Ordering +@cindex 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 @dfn{display} order is as follows: + +@example +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 +@end example + + So if two extents begin at the same position, the larger of them is the +earlier one in the display order (@code{EXTENT_LESS} is true). + + For the e-order, the same thing holds: + +@example +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 +@end example + + So if two extents end at the same position, the smaller of them is the +earlier one in the e-order (@code{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''. + +@node Format of the Extent Info, Zero-Length Extents, Extent Ordering, Extents +@section Format of the Extent Info +@cindex extent info, format of the + + An extent-info structure consists of a list of the buffer or string's +extents and a @dfn{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 @code{_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 @code{_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 @dfn{display order}) and the other is +ordered by end index (the @dfn{e-order}). Note that positions in an +extent list should logically be conceived of as referring @emph{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: + +@enumerate +@item +They are space efficient, as there is no need for next/previous pointers. + +@item +If the items in them are sorted, locating an item is fast -- @math{O(log N)}. + +@item +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. + +@item +Code to manipulate them is relatively simple to write. +@end enumerate + +An alternative would be balanced binary trees, which have guaranteed +@math{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. + +@node Zero-Length Extents, Mathematics of Extent Ordering, Format of the Extent Info, Extents +@section Zero-Length Extents +@cindex zero-length extents +@cindex extents, zero-length + + 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 @code{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: + +@enumerate +@item +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. + +@item +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. +@end enumerate + + 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. + +@node Mathematics of Extent Ordering, Extent Fragments, Zero-Length Extents, Extents +@section Mathematics of Extent Ordering +@cindex mathematics of extent ordering +@cindex extent mathematics +@cindex extent ordering + +@cindex display order of extents +@cindex extents, display order + 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 + +@enumerate +@item +Locate where an extent would go if inserted into the list. +@item +Insert an extent into the list. +@item +Remove an extent from the list. +@item +Map over all the extents that overlap a range. +@end enumerate + + (4) requires being able to determine the first and last extents +that overlap a range. + + NOTE: @dfn{overlap} is used as follows: + +@itemize @bullet +@item +two ranges overlap if they have at least one point in common. +Whether the endpoints are open or closed makes a difference here. +@item +a point overlaps a range if the point is contained within the +range; this is equivalent to treating a point @math{P} as the range +@math{[P, P]}. +@item +In the case of an @emph{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 @code{map-extents} maps over, since @code{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. +@end itemize + +First, define @math{>}, @math{<}, @math{<=}, etc. as applied to extents +to mean comparison according to the display order. Comparison between +an extent @math{E} and an index @math{I} means comparison between +@math{E} and the range @math{[I, I]}. + +Also define @math{e>}, @math{e<}, @math{e<=}, etc. to mean comparison +according to the e-order. + +For any range @math{R}, define @math{R(0)} to be the starting index of +the range and @math{R(1)} to be the ending index of the range. + +For any extent @math{E}, define @math{E(next)} to be the extent directly +following @math{E}, and @math{E(prev)} to be the extent directly +preceding @math{E}. Assume @math{E(next)} and @math{E(prev)} can be +determined from @math{E} in constant time. (This is because we store +the extent list as a doubly linked list.) + +Similarly, define @math{E(e-next)} and @math{E(e-prev)} to be the +extents directly following and preceding @math{E} in the e-order. + +Now: + +Let @math{R} be a range. +Let @math{F} be the first extent overlapping @math{R}. +Let @math{L} be the last extent overlapping @math{R}. + +Theorem 1: @math{R(1)} lies between @math{L} and @math{L(next)}, +i.e. @math{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 @math{L} just by looking at where we would +insert @math{R(1)} into the list, and if we know @math{F} and are moving +forward over extents, we can easily determine when we've hit @math{L} by +comparing the extent we're at to @math{R(1)}. + +@example +Theorem 2: @math{F(e-prev) e< [1, R(0)] e<= F}. +@end example + + This is the analog of Theorem 1, and applies because the e-order +sorts by increasing ending index. + + Therefore, @math{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 @math{O(log N)}, +since we are using gap arrays to manage extents. + + Define a @dfn{stack of extents} (or @dfn{SOE}) as the set of extents +(ordered in display order and e-order, just like for normal extent +lists) that overlap an index @math{I}. + +Now: + +Let @math{I} be an index, let @math{S} be the stack of extents on +@math{I} and let @math{F} be the first extent in @math{S}. + +Theorem 3: The first extent in @math{S} is the first extent that overlaps +any range @math{[I, J]}. + +Proof: Any extent that overlaps @math{[I, J]} but does not include +@math{I} must have a start index @math{> I}, and thus be greater than +any extent in @math{S}. + +Therefore, finding the first extent that overlaps a range @math{R} is +the same as finding the first extent that overlaps @math{R(0)}. + +Theorem 4: Let @math{I2} be an index such that @math{I2 > I}, and let +@math{F2} be the first extent that overlaps @math{I2}. Then, either +@math{F2} is in @math{S} or @math{F2} is greater than any extent in +@math{S}. + +Proof: If @math{F2} does not include @math{I} then its start index is +greater than @math{I} and thus it is greater than any extent in +@math{S}, including @math{F}. Otherwise, @math{F2} includes @math{I} +and thus is in @math{S}, and thus @math{F2 >= F}. + +@node Extent Fragments, , Mathematics of Extent Ordering, Extents +@section Extent Fragments +@cindex extent fragments +@cindex fragments, extent + + Imagine that the buffer is divided up into contiguous, non-overlapping +@dfn{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 @dfn{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. + +@node Faces, Glyphs, Extents, Top +@chapter Faces +@cindex faces + +Not yet documented. + +@node Glyphs, Specifiers, Faces, Top +@chapter Glyphs +@cindex 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. + +@c #### find a place for this discussion +@c The decision to make image specifiers a separate type is debatable. +@c In fact, the design decision to create a separate image specifier +@c type, rather than make glyphs themselves be specifiers, is +@c debatable---the other properties of glyphs are rarely used and could +@c conceivably have been incorporated into the glyph's instantiator. +@c The rarely used glyph types (buffer, pointer, icon) could also have +@c been incorporated into the instantiator. + +Glyphs are lazily instantiated by calling one of the glyph +functions. This usually occurs within redisplay when +@code{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 @code{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. + +@section Glyph Instantiation +@cindex glyph instantiation +@cindex instantiation, glyph + +Glyph instantiation is a hairy topic and requires some explanation. The +guts of glyph instantiation is contained within +@code{image_instantiate}. A glyph contains an image which is a +specifier. When a glyph function - for instance @code{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: + +@itemize @bullet +@item +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 @code{image_validate} and at a simple level validates +keyword value pairs. +@item +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 - +@code{image_copy_instantiator} - which will selectively copy values. +This is controlled by the way that a keyword is defined either using +@code{IIFORMAT_VALID_KEYWORD} or +@code{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. +@item +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 +@code{image_going_to_add} and @code{normalize_image_instantiator}. +@item +Instantiation. When an image instance is actually required for display +it is instantiated using @code{image_instantiate}. This involves calling +instantiate methods that are specific to the type of image being +instantiated. +@end itemize + +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 @dfn{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 +@dfn{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. + +@section Widget-Glyphs +@cindex widget-glyphs + +@section Widget-Glyphs in the MS-Windows Environment +@cindex widget-glyphs in the MS-Windows environment +@cindex MS-Windows environment, widget-glyphs in the + +To Do + +@section Widget-Glyphs in the X Environment +@cindex widget-glyphs in the X environment +@cindex X environment, widget-glyphs in the + +Widget-glyphs under X make heavy use of lwlib (@pxref{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 @file{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. + +@node Specifiers, Menus, Glyphs, Top +@chapter Specifiers +@cindex specifiers + +Not yet documented. + +Specifiers are documented in depth in the Lisp Reference manual. +@xref{Specifiers,,, lispref, XEmacs Lisp Reference Manual}. The code in +@file{specifier.c} is pretty straightforward. + +@node Menus, Events and the Event Loop, Specifiers, Top +@chapter Menus +@cindex menus + + A menu is set by setting the value of the variable +@code{current-menubar} (which may be buffer-local) and then calling +@code{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 +@code{current-menubar} is described in @file{menubar.c}. + + Internally the data in current-menubar is parsed into a tree of +@code{widget_value's} (defined in @file{lwlib.h}); this is accomplished +by the recursive function @code{menu_item_descriptor_to_widget_value()}, +called by @code{compute_menubar_data()}. Such a tree is deallocated +using @code{free_widget_value()}. + + @code{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 + +@enumerate +@item +@code{set-menubar-dirty-flag} was called since the last redisplay. (This +function sets the C variable menubar_has_changed.) +@item +The buffer displayed in the screen has changed. +@item +The screen has no menubar currently displayed. +@end enumerate + + @code{set_screen_menubar()} is called for each such screen. This +function calls @code{compute_menubar_data()} to create the tree of +widget_value's, then calls @code{lw_create_widget()}, +@code{lw_modify_all_widgets()}, and/or @code{lw_destroy_all_widgets()} +to create the X-Toolkit widget associated with the menu. + + @code{update_psheets()}, the other external entry point, actually +changes the menus being displayed. It uses the widgets fixed by +@code{update_screen_menubars()} and calls various X functions to ensure +that the menus are displayed properly. + + The menubar widget is set up so that @code{pre_activate_callback()} is +called when the menu is first selected (i.e. mouse button goes down), +and @code{menubar_selection_callback()} is called when an item is +selected. @code{pre_activate_callback()} calls the function in +activate-menubar-hook, which can change the menubar (this is described +in @file{menubar.c}). If the menubar is changed, +@code{set_screen_menubars()} is called. +@code{menubar_selection_callback()} enqueues a menu event, putting in it +a function to call (either @code{eval} or @code{call-interactively}) and +its argument, which is the callback function or form given in the menu's +description. + +@node Events and the Event Loop, Asynchronous Events; Quit Checking, Menus, Top +@chapter Events and the Event Loop +@cindex events and the event loop +@cindex event loop, events and the + +@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:: +@end menu + +@node Introduction to Events, Main Loop, Events and the Event Loop, Events and the Event Loop +@section Introduction to Events +@cindex events, introduction to + + 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 @dfn{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 @dfn{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 @file{events.h}; I'll discuss them +later. + +@node Main Loop, Specifics of the Event Gathering Mechanism, Introduction to Events, Events and the Event Loop +@section Main Loop +@cindex main loop +@cindex events, main loop + + The @dfn{command loop} is the top-level loop that the editor is always +running. It loops endlessly, calling @code{next-event} to retrieve an +event and @code{dispatch-event} to execute it. @code{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, @code{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. @code{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 @dfn{command builder}. +This is documented elsewhere. + + The guts of the command loop are in @code{command_loop_1()}. This +function doesn't catch errors, though---that's the job of +@code{command_loop_2()}, which is a condition-case (i.e. error-trapping) +wrapper around @code{command_loop_1()}. @code{command_loop_1()} never +returns, but may get thrown out of. + + When an error occurs, @code{cmd_error()} is called, which usually +invokes the Lisp error handler in @code{command-error}; however, a +default error handler is provided if @code{command-error} is @code{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 +@code{command_loop_2()} will finish and @code{command_loop_2()} will +reinvoke @code{command_loop_1()}. + + @code{command_loop_2()} is invoked from three places: from +@code{initial_command_loop()} (called from @code{main()} at the end of +internal initialization), from the Lisp function @code{recursive-edit}, +and from @code{call_command_loop()}. + + @code{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 +@code{execute-kbd-macro} for macros and @code{exit} for minibuffers. +Note also that the low-level minibuffer-entering function, +@code{read-minibuffer-internal}, provides its own error handling and +does not need @code{command_loop_2()}'s error encapsulation; so it tells +@code{call_command_loop()} to invoke @code{command_loop_1()} directly.) + + Note that both read-minibuffer-internal and recursive-edit set up a +catch for @code{exit}; this is why @code{abort-recursive-edit}, which +throws to this catch, exits out of either one. + + @code{initial_command_loop()}, called from @code{main()}, sets up a +catch for @code{top-level} when invoking @code{command_loop_2()}, +allowing functions to throw all the way to the top level if they really +need to. Before invoking @code{command_loop_2()}, +@code{initial_command_loop()} calls @code{top_level_1()}, which handles +all of the startup stuff (creating the initial frame, handling the +command-line options, loading the user's @file{.emacs} file, etc.). The +function that actually does this is in Lisp and is pointed to by the +variable @code{top-level}; normally this function is +@code{normal-top-level}. @code{top_level_1()} is just an error-handling +wrapper similar to @code{command_loop_2()}. Note also that +@code{initial_command_loop()} sets up a catch for @code{top-level} when +invoking @code{top_level_1()}, just like when it invokes +@code{command_loop_2()}. + +@node Specifics of the Event Gathering Mechanism, Specifics About the Emacs Event, Main Loop, Events and the Event Loop +@section Specifics of the Event Gathering Mechanism +@cindex event gathering mechanism, specifics of the + + 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): + +@noindent +@example + 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 @code{select()} in @code{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? @code{emacs_tty_next_event()} + | | + | | + | | + V V + --->------<---- + | + | [collected in @code{event_stream_next_event()}; + | SIGINT is converted using @code{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, @code{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 + | @code{next_event_internal()}] + | + unread- unread- event from | + command- command- keyboard else, call + events event macro @code{next_event_internal()} + | | | | + | | | | + | | | | + V V V V + --------->----------------------<------------ + | + | [collected in @code{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 @code{next-event} + and then dispatches the event + using @code{dispatch-event} @end example -This module implements various Lisp primitives for upcasing, downcasing -and capitalizing strings or regions of buffers. +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 @file{event-tty.c} and @file{event-Xt.c}, +respectively), the TTY event loop @emph{only} handles TTY consoles, +while the Xt event loop handles @emph{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): @example -rangetab.c +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 @code{select()} in + | | | @code{_XtWaitForSomething()}, called + | | | from @code{XtAppProcessEvent()}, called + | | | in @code{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 @code{Xt_what_callback()} + event sets flags + queue | + | | + | | + | | + | | + ---->-----------<-------- + | + | + | [collected and converted as appropriate in + | @code{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? @code{emacs_Xt_next_event()} + | | + | | + | | + V V + --->-------<---- + | + | [collected in @code{event_stream_next_event()}; + | SIGINT is converted using @code{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, @code{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 + | @code{next_event_internal()}] + | + unread- unread- event from | + command- command- keyboard else, call + events event macro @code{next_event_internal()} + | | | | + | | | | + | | | | + V V V V + --------->----------------------<------------ + | + | [collected in @code{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 @code{next-event} + and then dispatches the event + using @code{dispatch-event} @end example -This module implements the @dfn{range table} Lisp object type, which -provides for a mapping from ranges of integers to arbitrary Lisp -objects. +@node Specifics About the Emacs Event, Event Queues, Specifics of the Event Gathering Mechanism, Events and the Event Loop +@section Specifics About the Emacs Event +@cindex event, specifics about the Lisp object +@node Event Queues, Event Stream Callback Routines, Specifics About the Emacs Event, Events and the Event Loop +@section Event Queues +@cindex event queues +@cindex queues, event + +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 +@code{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 @strong{AFTER} an event has been read from +@code{next_event_internal()}, when it needs to be pushed back. This +includes, for example, @code{accept-process-output}, @code{sleep-for} +and @code{wait_delaying_user_input()}. Eval events and the like, +generated by @code{enqueue-eval-event}, +@code{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. @code{enqueue-eval-event}, +for example, could certainly push onto the dispatch queue, and all +callbacks maybe should. @code{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. + + +@node Event Stream Callback Routines, Other Event Loop Functions, Event Queues, Events and the Event Loop +@section Event Stream Callback Routines +@cindex event stream callback routines +@cindex callback routines, event stream + +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 @strong{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: -@example -opaque.c -opaque.h -@end example +@table @code +@item 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 @code{Fdiscard_input()}. + +@item 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 +@code{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 +@strong{must} return 0. Otherwise various undesirable effects will +occur, such as redisplay not occurring until the next event occurs. + +@item 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 @code{next_event_cb} never returns an +event of type "magic", this will never be used. + +@item format_magic_event_cb +Called with a magic event; print a representation of the innards of the +event to @var{PSTREAM}. + +@item compare_magic_event_cb +Called with two magic events; return non-zero if the innards of the two +are equal, zero otherwise. + +@item hash_magic_event_cb +Called with a magic event; return a hash of the innards of the event. + +@item add_timeout_cb +Called with an @var{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. + +@item remove_timeout_cb +Called with an int, the id number of a wakeup to discard. This id +number must have been returned by the @code{add_timeout_cb}. If the given +wakeup has already expired, this should do nothing. + +@item select_process_cb +@item 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. + +@item select_console_cb +@item 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. + +@item select_device_cb +@item unselect_device_cb +These callbacks are used by Unixoid event loops (those that use @code{select()} +and file descriptors and have a separate input fd per device). + +@item create_io_streams_cb +@item 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. + +@item quitp_cb +A handler function called from the @code{QUIT} macro which should check +whether the quit character has been typed. On systems with SIGIO, this +will not be called unless the @code{sigio_happened} flag is true (it is set +from the SIGIO handler). +@end table -This module implements the @dfn{opaque} Lisp object type, an -internal-only Lisp object that encapsulates an arbitrary block of memory -so that it can be managed by the Lisp allocation system. To create an -opaque object, you call @code{make_opaque()}, passing a pointer to a -block of memory. An object is created that is big enough to hold the -memory, which is copied into the object's storage. The object will then -stick around as long as you keep pointers to it, after which it will be -automatically reclaimed. +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. -@cindex mark method -Opaque objects can also have an arbitrary @dfn{mark method} associated -with them, in case the block of memory contains other Lisp objects that -need to be marked for garbage-collection purposes. (If you need other -object methods, such as a finalize method, you should just go ahead and -create a new Lisp object type---it's not hard.) +@node Other Event Loop Functions, Stream Pairs, Event Stream Callback Routines, Events and the Event Loop +@section Other Event Loop Functions +@cindex event loop functions, other + @code{detect_input_pending()} and @code{input-pending-p} look for +input by calling @code{event_stream->event_pending_p} and looking in +@code{[V]unread-command-event} and the @code{command_event_queue} (they +do not check for an executing keyboard macro, though). + @code{discard-input} cancels any command events pending (and any +keyboard macros currently executing), and puts the others onto the +@code{command_event_queue}. There is a comment about a ``race +condition'', which is not a good sign. -@example -abbrev.c -@end example + @code{next-command-event} and @code{read-char} are higher-level +interfaces to @code{next-event}. @code{next-command-event} gets the +next @dfn{command} event (i.e. keypress, mouse event, menu selection, +or scrollbar action), calling @code{dispatch-event} on any others. +@code{read-char} calls @code{next-command-event} and uses +@code{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. -This function provides a few primitives for doing dynamic abbreviation -expansion. In XEmacs, most of the code for this has been moved into -Lisp. Some C code remains for speed and because the primitive -@code{self-insert-command} (which is executed for all self-inserting -characters) hooks into the abbrev mechanism. (@code{self-insert-command} -is itself in C only for speed.) +@node Stream Pairs, Converting Events, Other Event Loop Functions, Events and the Event Loop +@section Stream Pairs +@cindex stream pairs +@cindex pairs, stream + +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 @code{create_io_streams} function must call +appropriate function to get file descriptors given HANDLEs, so that these +descriptors may be passed to @code{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, @code{USID_ERROR}, indicates +that the stream pair cannot be created. The second, +@code{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 +@code{get_process_from_usid}, this value should always be returned, to +prevent accumulating useless information on USID to process +relationship. +@node Converting Events, Dispatching Events; The Command Builder, Stream Pairs, Events and the Event Loop +@section Converting Events +@cindex converting events +@cindex events, converting + @code{character_to_event()}, @code{event_to_character()}, +@code{event-to-character}, and @code{character-to-event} convert between +characters and keypress events corresponding to the characters. If the +event was not a keypress, @code{event_to_character()} returns -1 and +@code{event-to-character} returns @code{nil}. These functions convert +between character representation and the split-up event representation +(keysym plus mod keys). -@example -doc.c -@end example +@node Dispatching Events; The Command Builder, Focus Handling, Converting Events, Events and the Event Loop +@section Dispatching Events; The Command Builder +@cindex dispatching events; the command builder +@cindex events; the command builder, dispatching +@cindex command builder, dispatching events; the -This function provides primitives for retrieving the documentation -strings of functions and variables. These documentation strings contain -certain special markers that get dynamically expanded (e.g. a -reverse-lookup is performed on some named functions to retrieve their -current key bindings). Some documentation strings (in particular, for -the built-in primitives and pre-loaded Lisp functions) are stored -externally in a file @file{DOC} in the @file{lib-src/} directory and -need to be fetched from that file. (Part of the build stage involves -building this file, and another part involves constructing an index for -this file and embedding it into the executable, so that the functions in -@file{doc.c} do not have to search the entire @file{DOC} file to find -the appropriate documentation string.) +Not yet documented. +@node Focus Handling, Editor-Level Control Flow Modules, Dispatching Events; The Command Builder, Events and the Event Loop +@section Focus Handling +@cindex focus handling + +Ben's capsule lecture on focus: + +In GNU Emacs @code{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 @code{select-device} or @code{select-console}. +Whenever an event comes in (including a keyboard event), its frame is +selected; therefore, evaluating @code{select-frame} in @samp{*scratch*} +won't cause any effects because the next received event (in the same +frame) will cause a switch back to the frame displaying +@samp{*scratch*}. + +Whenever a focus-change event is received from the window manager, it +generates a @code{switch-frame} event, which causes the Lisp function +@code{handle-switch-frame} to get run. This basically just runs +@code{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 @code{switch-frame} (and then +maybe call @code{handle-switch-frame}, or something ...). + +In XEmacs, we @strong{do} change the window-manager frame focus as a +result of @code{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 @code{switch-frame} event visible but instead have +@code{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 @code{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 +@code{select-frame} (but not if @code{handle-switch-frame} is called), +and saves and restores the frame focus in window configurations, +etc. etc. All of this logic is heavily @code{#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 @file{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 @code{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. +@node Editor-Level Control Flow Modules, , Focus Handling, Events and the Event Loop +@section Editor-Level Control Flow Modules +@cindex control flow modules, editor-level +@cindex modules, editor-level control flow @example -md5.c +@file{event-Xt.c} +@file{event-msw.c} +@file{event-stream.c} +@file{event-tty.c} +@file{events-mod.h} +@file{gpmevent.c} +@file{gpmevent.h} +@file{events.c} +@file{events.h} @end example -This function provides a Lisp primitive that implements the MD5 secure -hashing scheme, used to create a large hash value of a string of data such that -the data cannot be derived from the hash value. This is used for -various security applications on the Internet. - - - - -@node Modules for Interfacing with the Operating System -@section Modules for Interfacing with the Operating System -@cindex modules for interfacing with the operating system -@cindex interfacing with the operating system, modules for -@cindex operating system, modules for interfacing with the - -@example -process.el -process.c -process.h -@end example +These implement the handling of events (user input and other system +notifications). -These modules allow XEmacs to spawn and communicate with subprocesses -and network connections. +@file{events.c} and @file{events.h} define the @dfn{event} Lisp object +type and primitives for manipulating it. -@cindex synchronous subprocesses -@cindex subprocesses, synchronous - @file{process.el} implements (through the @code{call-process} -primitive) what are called @dfn{synchronous subprocesses}. This means -that XEmacs runs a program, waits till it's done, and retrieves its -output. A typical example might be calling the @file{ls} program to get -a directory listing. +@file{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 +@code{next-event} and @code{dispatch-event}, as well as related +primitives such as @code{sit-for}, @code{sleep-for}, and +@code{accept-process-output}. (@file{event-stream.c} is one of the +hairiest and trickiest modules in XEmacs. Beware! You can easily mess +things up here.) -@cindex asynchronous subprocesses -@cindex subprocesses, asynchronous - @file{process.c} and @file{process.h} implement @dfn{asynchronous -subprocesses}. This means that XEmacs starts a program and then -continues normally, not waiting for the process to finish. Data can be -sent to the process or retrieved from it as it's running. This is used -for the @code{shell} command (which provides a front end onto a shell -program such as @file{csh}), the mail and news readers implemented in -XEmacs, etc. The result of calling @code{start-process} to start a -subprocess is a process object, a particular kind of object used to -communicate with the subprocess. You can send data to the process by -passing the process object and the data to @code{send-process}, and you -can specify what happens to data retrieved from the process by setting -properties of the process object. (When the process sends data, XEmacs -receives a process event, which says that there is data ready. When -@code{dispatch-event} is called on this event, it reads the data from -the process and does something with it, as specified by the process -object's properties. Typically, this means inserting the data into a -buffer or calling a function.) Another property of the process object is -called the @dfn{sentinel}, which is a function that is called when the -process terminates. +@file{event-Xt.c} and @file{event-tty.c} implement the low-level +interfaces onto retrieving events from Xt (the X toolkit) and from TTY's +(using @code{read()} and @code{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; +@file{event-Xt.c} and @file{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. -@cindex network connections - Process objects are also used for network connections (connections to a -process running on another machine). Network connections are started -with @code{open-network-stream} but otherwise work just like -subprocesses. +Note that the choice of whether to use @file{event-Xt.c} or +@file{event-tty.c} is made at compile time! Or at the very latest, it +is made at startup time. @file{event-Xt.c} handles events for +@emph{both} X and TTY frames; @file{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. @example -sysdep.c -sysdep.h +@file{keymap.c} +@file{keymap.h} @end example - These modules implement most of the low-level, messy operating-system -interface code. This includes various device control (ioctl) operations -for file descriptors, TTY's, pseudo-terminals, etc. (usually this stuff -is fairly system-dependent; thus the name of this module), and emulation -of standard library functions and system calls on systems that don't -provide them or have broken versions. +@file{keymap.c} and @file{keymap.h} define the @dfn{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; @code{dispatch-event} looks up events in the +relevant keymaps.) @example -sysdir.h -sysfile.h -sysfloat.h -sysproc.h -syspwd.h -syssignal.h -systime.h -systty.h -syswait.h +@file{cmdloop.c} @end example -These header files provide consistent interfaces onto system-dependent -header files and system calls. The idea is that, instead of including a -standard header file like @file{<sys/param.h>} (which may or may not -exist on various systems) or having to worry about whether all system -provide a particular preprocessor constant, or having to deal with the -four different paradigms for manipulating signals, you just include the -appropriate @file{sys*.h} header file, which includes all the right -system header files, defines and missing preprocessor constants, -provides a uniform interface onto system calls, etc. - -@file{sysdir.h} provides a uniform interface onto directory-querying -functions. (In some cases, this is in conjunction with emulation -functions in @file{sysdep.c}.) - -@file{sysfile.h} includes all the necessary header files for standard -system calls (e.g. @code{read()}), ensures that all necessary -@code{open()} and @code{stat()} preprocessor constants are defined, and -possibly (usually) substitutes sugared versions of @code{read()}, -@code{write()}, etc. that automatically restart interrupted I/O -operations. - -@file{sysfloat.h} includes the necessary header files for floating-point -operations. - -@file{sysproc.h} includes the necessary header files for calling -@code{select()}, @code{fork()}, @code{execve()}, socket operations, and -the like, and ensures that the @code{FD_*()} macros for descriptor-set -manipulations are available. - -@file{syspwd.h} includes the necessary header files for obtaining -information from @file{/etc/passwd} (the functions are emulated under -VMS). - -@file{syssignal.h} includes the necessary header files for -signal-handling and provides a uniform interface onto the different -signal-handling and signal-blocking paradigms. +@file{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 +@file{event-stream.c}. -@file{systime.h} includes the necessary header files and provides -uniform interfaces for retrieving the time of day, setting file -access/modification times, getting the amount of time used by the XEmacs -process, etc. -@file{systty.h} buffers against the infinitude of different ways of -controlling TTY's. -@file{syswait.h} provides a uniform way of retrieving the exit status -from a @code{wait()}ed-on process (some systems use a union, others use -an int). +@example +@file{macros.c} +@file{macros.h} +@end example + +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 @file{event-stream.c}. @example -hpplay.c -libsst.c -libsst.h -libst.h -linuxplay.c -nas.c -sgiplay.c -sound.c -sunplay.c +@file{minibuf.c} @end example -These files implement the ability to play various sounds on some types -of computers. You have to configure your XEmacs with sound support in -order to get this capability. +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 @file{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{sound.c} provides the generic interface. It implements various -Lisp primitives and variables that let you specify which sounds should -be played in certain conditions. (The conditions are identified by -symbols, which are passed to @code{ding} to make a sound. Various -standard functions call this function at certain times; if sound support -does not exist, a simple beep results. -@cindex native sound -@cindex sound, native -@file{sgiplay.c}, @file{sunplay.c}, @file{hpplay.c}, and -@file{linuxplay.c} interface to the machine's speaker for various -different kind of machines. This is called @dfn{native} sound. +@node Asynchronous Events; Quit Checking, Lstreams, Events and the Event Loop, Top +@chapter Asynchronous Events; Quit Checking +@cindex asynchronous events; quit checking +@cindex asynchronous events -@cindex sound, network -@cindex network sound -@cindex NAS -@file{nas.c} interfaces to a computer somewhere else on the network -using the NAS (Network Audio Server) protocol, playing sounds on that -machine. This allows you to run XEmacs on a remote machine, with its -display set to your local machine, and have the sounds be made on your -local machine, provided that you have a NAS server running on your local -machine. +@menu +* Signal Handling:: +* Control-G (Quit) Checking:: +* Profiling:: +* Asynchronous Timeouts:: +* Exiting:: +@end menu -@file{libsst.c}, @file{libsst.h}, and @file{libst.h} provide some -additional functions for playing sound on a Sun SPARC but are not -currently in use. +@node Signal Handling, Control-G (Quit) Checking, Asynchronous Events; Quit Checking, Asynchronous Events; Quit Checking +@section Signal Handling +@cindex signal handling + +@node Control-G (Quit) Checking, Profiling, Signal Handling, Asynchronous Events; Quit Checking +@section Control-G (Quit) Checking +@cindex Control-g checking +@cindex C-g checking +@cindex quit checking +@cindex QUIT checking +@cindex critical quit + +@emph{Note}: The code to handle QUIT is divided between @file{lisp.h} +and @file{signal.c}. There is also some special-case code in the async +timer code in @file{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: +@enumerate +@item -@example -tooltalk.c -tooltalk.h -@end example +Scattered throughout the XEmacs core code are calls to the macro QUIT; +This macro checks to see whether a @kbd{C-g} has recently been pressed +and not yet handled, and if so, it handles the @kbd{C-g} by calling +@code{signal_quit()}, which invokes the standard @code{Fsignal()} code, +with the error being @code{Qquit}. Lisp code can establish handlers +for this (using @code{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 @code{condition-case} is established that catches @strong{all} calls +to @code{signal}, including this one.) + +@item +How does the QUIT macro check to see whether @kbd{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 @kbd{C-g}: it searched +through all the pending (i.e. not yet delivered to XEmacs yet) +X events for one that matched @kbd{C-g}. When it saw a match, it set +Vquit_flag to Qt. On TTY's, @kbd{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 @code{Vquit_flag} and used +this as an indication to call @code{signal_quit()}. What @code{signal_quit()} +actually does is set @code{Vquit_flag} to Qnil (so that we won't get +repeated interruptions from a single @kbd{C-g} press) and then calls +the equivalent of (signal 'quit nil). + +@item +Another complication is introduced in that Vquit_flag is actually +exported to Lisp as @code{quit-flag}. This allows users some level of +control over whether and when @kbd{C-g} is processed as quit, esp. in +combination with @code{inhibit-quit}. This is another Lisp variable, +and if set to non-nil, it inhibits @code{signal_quit()} from getting +called, meaning that the @kbd{C-g} gets essentially ignored. But not +completely: Because the resetting of @code{quit-flag} happens only +in @code{signal_quit()}, which isn't getting called, the @kbd{C-g} press is +still noticed, and as soon as @code{inhibit-quit} is set back to nil, +a quit will be signalled at the next QUIT macro. Thus, what +@code{inhibit-quit} really does is defer quits until after the quit- +inhibitted period. + +@item +Another consideration, introduced by XEmacs, is critical quitting. If +you press @kbd{Control-Shift-G} instead of just @kbd{C-g}, +@code{quit-flag} is set to @code{critical} instead of to t. When QUIT +processes this value, it @strong{ignores} the value of +@code{inhibit-quit}. This allows you to quit even out of a +quit-inhibitted section of code! Furthermore, when @code{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 @code{debug-on-quit} is set to t). + +@item +Well, I explained above about how @code{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 @kbd{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. -These two modules implement an interface to the ToolTalk protocol, which -is an interprocess communication protocol implemented on some versions -of Unix. ToolTalk is a high-level protocol that allows processes to -register themselves as providers of particular services; other processes -can then request a service without knowing or caring exactly who is -providing the service. It is similar in spirit to the DDE protocol -provided under Microsoft Windows. ToolTalk is a part of the new CDE -(Common Desktop Environment) specification and is used to connect the -parts of the SPARCWorks development environment. +@item +Now, let's look at QUIT again. +@item +UNFINISHED. Note, however, that as of the point when this comment got +committed to CVS (mid-2001), the interaction between reading @kbd{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 @kbd{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. @code{accept-process-output} and +@code{wait_delaying_user_events()}.) Formerly, this was supposed to +happen, but didn't always due to a bizarre and broken scheme, documented +in @code{next_event_internal} like this: -@example -getloadavg.c -@end example +@quotation +If we read a @kbd{C-g}, then set @code{quit-flag} but do not discard the +@kbd{C-g}. The callers of @code{next_event_internal()} will do one of +two things: -This module provides the ability to retrieve the system's current load -average. (The way to do this is highly system-specific, unfortunately, -and requires a lot of special-case code.) +@enumerate +@item +set @code{Vquit_flag} to Qnil. (@code{next-event} does this.) This will +cause the ^G to be treated as a normal keystroke. +@item +not change @code{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 @code{Vquit_flag} was set. +@end enumerate +@end quotation +This required weirdness in @code{enqueue_command_event_1} like this: -@example -sunpro.c -@end example +@quotation +put the event on the typeahead queue, unless the event is the quit char, +in which case the @code{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. +@end quotation -This module provides a small amount of code used internally at Sun to -keep statistics on the usage of XEmacs. +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 @code{next_event_internal()} or any callers when @kbd{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 +@code{next_event_internal()} that want @kbd{C-g} read as a user event +call @code{begin_dont_check_for_quit()}. @code{next_event_internal()}, +when it gets a @kbd{C-g}, simply sets @code{Vquit_flag} (just as when a +@kbd{C-g} is detected during the operation of @code{QUIT} or +@code{QUITP}), and then tries to @code{QUIT}. This will fail if blocked +by the previous call, at which point @code{next_event_internal()} will +return the @kbd{C-g} as an event. To unblock things, first set +@code{Vquit_flag} to nil (it was set to t when the @kbd{C-g} was read, +and if we don't reset it, the next call to @code{QUIT} will quit), and +then @code{unbind_to()} the depth returned by +@code{begin_dont_check_for_quit()}. It makes no difference is +@code{QUIT} is called a zillion times in @code{next_event_internal()} or +anywhere else, because it's blocked and will never signal. +@end enumerate +@subsection 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: + +@subheading Crash -- reentrant @code{re_match_2()} + +@example + /* 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 +@end example + +[explain dont_check_for_quit() et al] + +@node Profiling, Asynchronous Timeouts, Control-G (Quit) Checking, Asynchronous Events; Quit Checking +@section Profiling +@cindex profiling +@cindex SIGPROF + +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 @code{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 @code{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, @code{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 @code{puthash()}), could be +deadly. To avoid this, we make sure, at points where it's safe +(e.g. @code{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 @code{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 @code{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 +@code{start-profile} was called, so when @code{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 @code{profile_increase_call_count()} +function is called from @code{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 @strong{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. + +@node Asynchronous Timeouts, Exiting, Profiling, Asynchronous Events; Quit Checking +@section Asynchronous Timeouts +@cindex asynchronous timeouts + +@node Exiting, , Asynchronous Timeouts, Asynchronous Events; Quit Checking +@section Exiting +@cindex exiting +@cindex crash +@cindex hang +@cindex core dump +@cindex Armageddon +@cindex exits, expected and unexpected +@cindex unexpected exits +@cindex expected exits + +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 +@kbd{C-x C-c}. This runs @code{save-buffers-kill-emacs}, which saves +any necessary buffers, and then exits using the primitive +@code{kill-emacs}. -@example -broken-sun.h -strcmp.c -strcpy.c -sunOS-fix.c -@end example +However, unexpected exits occur in a few different ways: -These files provide replacement functions and prototypes to fix numerous -bugs in early releases of SunOS 4.1. +@itemize @bullet +@item +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 @strong{extremely} careful what we do. + +@item +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. +@end itemize +Currently, both unexpected exit scenarios described above set +@code{preparing_for_armageddon} to indicate that nonessential and possibly +dangerous things should not be done, specifically: +@itemize @minus +@item +no garbage collection. +@item +no hooks are run. +@item +no messages of any sort from autosaving. +@item +autosaving tries harder, ignoring certain failures. +@item +existing frames are not deleted. +@end itemize -@example -hftctl.c -@end example +(Also, all places that set @code{preparing_for_armageddon} also +set @code{dont_check_for_quit}. This happens separately because it's +also necessary to set other variables to make absolutely sure +no quitting happens.) -This module provides some terminal-control code necessary on versions of -AIX prior to 4.1. +In the first scenario above (the access violation), we also set +@code{fatal_error_in_progress}. This causes more things to not happen: +@itemize @minus +@item +assertion failures do not abort. +@item +printing code does not do code conversion or gettext when +printing to stdout/stderr. +@end itemize +@node Lstreams, Subprocesses, Asynchronous Events; Quit Checking, Top +@chapter Lstreams +@cindex lstreams -@node Modules for Interfacing with X Windows -@section Modules for Interfacing with X Windows -@cindex modules for interfacing with X Windows -@cindex interfacing with X Windows, modules for -@cindex X Windows, modules for interfacing with + An @dfn{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. -@example -Emacs.ad.h -@end example +@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. +@end menu -A file generated from @file{Emacs.ad}, which contains XEmacs-supplied -fallback resources (so that XEmacs has pretty defaults). +@node Creating an Lstream, Lstream Types, Lstreams, Lstreams +@section Creating an Lstream +@cindex lstream, creating an +Lstreams come in different types, depending on what is being interfaced +to. Although the primitive for creating new lstreams is +@code{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 @var{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. -@example -EmacsFrame.c -EmacsFrame.h -EmacsFrameP.h -@end example + @var{mode} is a string, one of -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. +@table @code +@item "r" + Open for reading. +@item "w" + Open for writing. +@item "rc" + Open for reading, but ``read'' never returns partial MULE characters. +@item "wc" + Open for writing, but never writes partial MULE characters. +@end table -@strong{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. +@node Lstream Types, Lstream Functions, Creating an Lstream, Lstreams +@section Lstream Types +@cindex lstream types +@cindex types, lstream +@table @asis +@item stdio +@item filedesc -@example -EmacsManager.c -EmacsManager.h -EmacsManagerP.h -@end example +@item lisp-string -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. +@item fixed-buffer +@item resizing-buffer -@example -EmacsShell-sub.c -EmacsShell.c -EmacsShell.h -EmacsShellP.h -@end example +@item dynarr -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. +@item lisp-buffer +@item print +@item decoding -@example -xgccache.c -xgccache.h -@end example +@item encoding +@end table -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. +@node Lstream Functions, Lstream Methods, Lstream Types, Lstreams +@section Lstream Functions +@cindex lstream functions + +@deftypefun {Lstream *} Lstream_new (Lstream_implementation *@var{imp}, const char *@var{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). +@end deftypefun + +@deftypefun void Lstream_set_buffering (Lstream *@var{lstr}, Lstream_buffering @var{buffering}, int @var{buffering_size}) +Change the buffering of a stream. See @file{lstream.h}. By default the +buffering is @code{STREAM_BLOCK_BUFFERED}. +@end deftypefun + +@deftypefun int Lstream_flush (Lstream *@var{lstr}) +Flush out any pending unwritten data in the stream. Clear any buffered +input data. Returns 0 on success, -1 on error. +@end deftypefun + +@deftypefn Macro int Lstream_putc (Lstream *@var{stream}, int @var{c}) +Write out one byte to the stream. This is a macro and so it is very +efficient. The @var{c} argument is only evaluated once but the @var{stream} +argument is evaluated more than once. Returns 0 on success, -1 on +error. +@end deftypefn + +@deftypefn Macro int Lstream_getc (Lstream *@var{stream}) +Read one byte from the stream. This is a macro and so it is very +efficient. The @var{stream} argument is evaluated more than once. Return +value is -1 for EOF or error. +@end deftypefn + +@deftypefn Macro void Lstream_ungetc (Lstream *@var{stream}, int @var{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 @var{c} argument is only evaluated once but the @var{stream} +argument is evaluated more than once. +@end deftypefn + +@deftypefun int Lstream_fputc (Lstream *@var{stream}, int @var{c}) +@deftypefunx int Lstream_fgetc (Lstream *@var{stream}) +@deftypefunx void Lstream_fungetc (Lstream *@var{stream}, int @var{c}) +Function equivalents of the above macros. +@end deftypefun +@deftypefun Bytecount Lstream_read (Lstream *@var{stream}, void *@var{data}, Bytecount @var{size}) +Read @var{size} bytes of @var{data} from the stream. Return the number +of bytes read. 0 means EOF. -1 means an error occurred and no bytes +were read. +@end deftypefun +@deftypefun Bytecount Lstream_write (Lstream *@var{stream}, void *@var{data}, Bytecount @var{size}) +Write @var{size} bytes of @var{data} to the stream. Return the number +of bytes written. -1 means an error occurred and no bytes were written. +@end deftypefun -@example -select-msw.c -select-x.c -select.c -select.h -@end example +@deftypefun void Lstream_unread (Lstream *@var{stream}, void *@var{data}, Bytecount @var{size}) +Push back @var{size} bytes of @var{data} onto the input queue. The next +call to @code{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. +@end deftypefun -@cindex selections - This module provides an interface to the X Window System's concept of -@dfn{selections}, the standard way for X applications to communicate -with each other. +@deftypefun int Lstream_close (Lstream *@var{stream}) +Close the stream. All data will be flushed out. +@end deftypefun +@deftypefun void Lstream_reopen (Lstream *@var{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. +@end deftypefun +@deftypefun void Lstream_rewind (Lstream *@var{stream}) +Rewind the stream to the beginning. +@end deftypefun -@example -xintrinsic.h -xintrinsicp.h -xmmanagerp.h -xmprimitivep.h -@end example +@node Lstream Methods, , Lstream Functions, Lstreams +@section Lstream Methods +@cindex lstream methods -These header files are similar in spirit to the @file{sys*.h} files and buffer -against different implementations of Xt and Motif. +@deftypefn {Lstream Method} Bytecount reader (Lstream *@var{stream}, unsigned char *@var{data}, Bytecount @var{size}) +Read some data from the stream's end and store it into @var{data}, which +can hold @var{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 @var{size} is less than +this granularity. (This will happen frequently for streams that need to +return whole characters, because @code{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 @code{Lstream_read()} with a very small size. -@itemize @bullet -@item -@file{xintrinsic.h} should be included in place of @file{<Intrinsic.h>}. -@item -@file{xintrinsicp.h} should be included in place of @file{<IntrinsicP.h>}. -@item -@file{xmmanagerp.h} should be included in place of @file{<XmManagerP.h>}. -@item -@file{xmprimitivep.h} should be included in place of @file{<XmPrimitiveP.h>}. -@end itemize +This function can be @code{NULL} if the stream is output-only. +@end deftypefn +@deftypefn {Lstream Method} Bytecount writer (Lstream *@var{stream}, const unsigned char *@var{data}, Bytecount @var{size}) +Send some data to the stream's end. Data to be sent is in @var{data} +and is @var{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 +@code{EWOULDBLOCK} errors.) This function can be @code{NULL} if the +stream is input-only. +@end deftypefn +@deftypefn {Lstream Method} int rewinder (Lstream *@var{stream}) +Rewind the stream. If this is @code{NULL}, the stream is not seekable. +@end deftypefn -@example -xmu.c -xmu.h -@end example +@deftypefn {Lstream Method} int seekable_p (Lstream *@var{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. +@end deftypefn -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. +@deftypefn {Lstream Method} int flusher (Lstream *@var{stream}) +Perform any additional operations necessary to flush the data in this +stream. +@end deftypefn +@deftypefn {Lstream Method} int pseudo_closer (Lstream *@var{stream}) +@end deftypefn +@deftypefn {Lstream Method} int closer (Lstream *@var{stream}) +Perform any additional operations necessary to close this stream down. +May be @code{NULL}. This function is called when @code{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. +@end deftypefn -@example -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 -@end example +@deftypefn {Lstream Method} Lisp_Object marker (Lisp_Object @var{lstream}, void (*@var{markfun}) (Lisp_Object)) +Mark this object for garbage collection. Same semantics as a standard +@code{Lisp_Object} marker. This function can be @code{NULL}. +@end deftypefn -@cindex external widget - These files provide the @dfn{external widget} interface, which allows an -XEmacs frame to appear as a widget in another application. To do this, -you have to configure with @samp{--external-widget}. +@node Subprocesses, Interface to MS Windows, Lstreams, Top +@chapter Subprocesses +@cindex subprocesses -@file{ExternalShell*} provides the server (XEmacs) side of the -connection. + The fields of a process are: -@file{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. +@table @code +@item name +A string, the name of the process. -@file{extw-*} is common code that is used for both the client and server. +@item command +A list containing the command arguments that were used to start this +process. -Don't touch this code; something is liable to break if you do. +@item filter +A function used to accept output from the process instead of a buffer, +or @code{nil}. +@item sentinel +A function called whenever the process receives a signal, or @code{nil}. +@item buffer +The associated buffer of the process. -@node Modules for Internationalization -@section Modules for Internationalization -@cindex modules for internationalization -@cindex internationalization, modules for +@item pid +An integer, the Unix process @sc{id}. -@example -mule-canna.c -mule-ccl.c -mule-charset.c -mule-charset.h -file-coding.c -file-coding.h -mule-coding.c -mule-mcpath.c -mule-mcpath.h -mule-wnnfns.c -mule.c -@end example +@item childp +A flag, non-@code{nil} if this is really a child process. +It is @code{nil} for a network connection. -These files implement the MULE (Asian-language) support. Note that MULE -actually provides a general interface for all sorts of languages, not -just Asian languages (although they are generally the most complicated -to support). This code is still in beta. +@item 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. -@file{mule-charset.*} and @file{file-coding.*} provide the heart of the -XEmacs MULE support. @file{mule-charset.*} implements the @dfn{charset} -Lisp object type, which encapsulates a character set (an ordered one- or -two-dimensional set of characters, such as US ASCII or JISX0208 Japanese -Kanji). +@item kill_without_query +If this is non-@code{nil}, killing XEmacs while this process is still +running does not ask for confirmation about killing the process. -@file{file-coding.*} implements the @dfn{coding-system} Lisp object -type, which encapsulates a method of converting between different -encodings. An encoding is a representation of a stream of characters, -possibly from multiple character sets, using a stream of bytes or words, -and defines (e.g.) which escape sequences are used to specify particular -character sets, how the indices for a character are converted into bytes -(sometimes this involves setting the high bit; sometimes complicated -rearranging of the values takes place, as in the Shift-JIS encoding), -etc. It also contains some generic coding system implementations, such -as the binary (no-conversion) coding system and a sample gzip coding system. +@item raw_status_low +@itemx raw_status_high +These two fields record 16 bits each of the process status returned by +the @code{wait} system call. -@file{mule-coding.c} contains the implementations of text coding systems. +@item status +The process status, as @code{process-status} should return it. -@file{mule-ccl.c} provides the CCL (Code Conversion Language) -interpreter. CCL is similar in spirit to Lisp byte code and is used to -implement converters for custom encodings. +@item tick +@itemx 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. -@file{mule-canna.c} and @file{mule-wnnfns.c} implement interfaces to -external programs used to implement the Canna and WNN input methods, -respectively. This is currently in beta. +@item pty_flag +Non-@code{nil} if communication with the subprocess uses a @sc{pty}; +@code{nil} if it uses a pipe. -@file{mule-mcpath.c} provides some functions to allow for pathnames -containing extended characters. This code is fragmentary, obsolete, and -completely non-working. Instead, @code{pathname-coding-system} is used -to specify conversions of names of files and directories. The standard -C I/O functions like @samp{open()} are wrapped so that conversion occurs -automatically. +@item infd +The file descriptor for input from the process. -@file{mule.c} contains a few miscellaneous things. It currently seems -to be unused and probably should be removed. +@item outfd +The file descriptor for output to the process. +@item 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 +@code{-1}.) +@item tty_name +The name of the terminal that the subprocess is using, +or @code{nil} if it is using pipes. +@end table -@example -intl.c -@end example +@node Interface to MS Windows, Interface to the X Window System, Subprocesses, Top +@chapter Interface to MS Windows +@cindex MS Windows, interface to +@cindex Windows, interface to -This provides some miscellaneous internationalization code for -implementing message translation and interfacing to the Ximp input -method. None of this code is currently working. +@menu +* Different kinds of Windows environments:: +* Windows Build Flags:: +* Windows I18N Introduction:: +* Modules for Interfacing with MS Windows:: +@end menu +@node Different kinds of Windows environments, Windows Build Flags, Interface to MS Windows, Interface to MS Windows +@section Different kinds of Windows environments +@cindex different kinds of Windows environments +@cindex Windows environments, different kinds of +@cindex MS Windows environments, different kinds of + +@subsubheading (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 @file{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 @code{CreateFile()} +and @code{ReadFile()}, process-creation calls such as @code{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 @code{open()}, @code{read()}, @code{fork()}, @code{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 @code{fopen()} and @code{fread()}) as well +as various other utility functions, such as string-manipulation routines +(e.g. @code{strcpy()} and @code{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 @file{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, @file{cygwin1.dll}, +which makes calls to the Win32 API services in @file{kernel32.dll}. Cygwin +also provides its own implementation of the C runtime library, called +@code{newlib} (@file{libcygwin.a}; @file{libc.a} and @file{libm.a} are symlinked to it), which is +implemented on top of the Unix system calls provided in @file{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: + +@subsubheading (b) CRT is not the same as VC++ + +Note that the CRT is @strong{NOT} (completely) part of VC++. True, if you link +statically, the CRT (in the form of @file{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 @file{MSVCRT.DLL} +(or @file{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. + +@subsubheading (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. + +@subsubheading (d) MinGW is not the same as Cygwin + +As described in (b), Microsoft's version of the CRT (@file{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 +@file{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 @file{MSVCRT.DLL} rather than @file{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. + +@subsubheading (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 @file{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 @file{USER32.DLL} and @file{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 +@file{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: +@table @asis +@item Native OS + native windowing +We call @code{CreateProcess()} to run subprocesses +(@file{process-nt.c}), and @code{CreateWindowEx()} to create a top-level +window (@file{frame-msw.c}). We use @file{nt/xemacs.mak} to compile +with VC++, linking with the Windows CRT (@file{MSVCRT.DLL} or +@file{LIBC.LIB}) and with the various Win32 DLL's (@file{KERNEL32.DLL}, +@file{USER32.DLL}, @file{GDI32.DLL}); or we use +@file{src/Makefile[.in.in]} to compile with GCC, telling it +(e.g. -mno-cygwin, see @file{s/mingw32.h}) to use MinGW (which will end +up linking with @file{MSVCRT.DLL}), and linking GCC with -lshell32 +-lgdi32 -luser32 etc. (see @file{configure.in}). + +@item Cygwin + native windowing +We call @code{fork()}/@code{execve()} to run subprocesses +(@file{process-unix.c}), and @code{CreateWindowEx()} to create a +top-level window (@file{frame-msw.c}). We use +@file{src/Makefile[in.in]} to compile with GCC (it will end up linking +with @file{CYGWIN1.DLL}) and link GCC with -lshell32 -lgdi32 -luser32 +etc. (see @file{configure.in}). + +@item Cygwin + X11 +We call @code{fork()}/@code{execve()} to run subprocesses +(@file{process-unix.c}), and @code{XtCreatePopupShell()} to create a +top-level window (@file{frame-x.c}). We use @file{src/Makefile[.in.in]} +to compile with GCC (it will end up linking with @file{CYGWIN1.DLL}) and +link GCC with -lXt, -lX11, etc. (see @file{configure.in}). + +Finally, if native OS + X11 were possible, it might look something like + +@item [Native OS + X11] +We call @code{CreateProcess()} to run subprocesses +(@file{process-nt.c}), and @code{XtCreatePopupShell()} to create a +top-level window (@file{frame-x.c}). We use @file{nt/xemacs.mak} to +compile with VC++, linking with the Windows CRT (@file{MSVCRT.DLL} or +@file{LIBC.LIB}) and with the various X11 DLL's (@file{XT.DLL}, +@file{XLIB.DLL}, etc.); or we use @file{src/Makefile[.in.in]} to compile with +GCC, telling it (e.g. -mno-cygwin, see @file{s/mingw32.h}) to use MinGW +(which will end up linking with @file{MSVCRT.DLL}), and linking GCC with +-lXt, -lX11, etc. (see @file{configure.in}). +@end table -@example -iso-wide.h -@end example +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. + +@node Windows Build Flags, Windows I18N Introduction, Different kinds of Windows environments, Interface to MS Windows +@section Windows Build Flags +@cindex Windows build flags +@cindex MS Windows build flags +@cindex build flags, Windows -This contains leftover code from an earlier implementation of -Asian-language support, and is not currently used. +@table @code +@item CYGWIN +for Cygwin-only stuff. +@item 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. +@item HAVE_X_WINDOWS +for X Windows (regardless of whether under MS Win) +@item 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. +@end table +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: + +@c @multitable {Old Constant} {determine whether this code is really specific to MS-DOS (and not Windows -- e.g. DJGPP code} +@multitable @columnfractions .25 .75 +@item Old Constant @tab New Constant +@item ---------------------------------------------------------------- +@item @code{WINDOWSNT} +@tab @code{WIN32_NATIVE} +@item @code{WIN32} +@tab @code{WIN32_NATIVE} +@item @code{_WIN32} +@tab @code{WIN32_NATIVE} +@item @code{HAVE_WIN32} +@tab @code{WIN32_NATIVE} +@item @code{DOS_NT} +@tab @code{WIN32_NATIVE} +@item @code{HAVE_NTGUI} +@tab @code{WIN32_NATIVE}, unless it ends up already bracketed by this +@item @code{HAVE_FACES} +@tab always true +@item @code{MSDOS} +@tab 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 @code{WIN32_NATIVE} (we do not support MS-DOS w/DOS Extender +under XEmacs) +@item @code{__CYGWIN__} +@tab @code{CYGWIN} +@item @code{__CYGWIN32__} +@tab @code{CYGWIN} +@item @code{__MINGW32__} +@tab @code{MINGW} +@end multitable + +@node Windows I18N Introduction, Modules for Interfacing with MS Windows, Windows Build Flags, Interface to MS Windows +@section Windows I18N Introduction +@cindex Windows I18N +@cindex I18N, Windows +@cindex MS Windows I18N + +@strong{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 @code{@dfn{TCHAR}} which specifies +a generic character, either 8 bits or 16 bits. Generally @code{TCHAR} +is defined to be the same as the simple C type @code{char}, unless the +preprocessor constant @code{UNICODE} is defined, in which case +@code{TCHAR} is defined to be @code{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 @code{TCHAR}s. There is a type +@code{LPTSTR} which is defined to be a string of @code{TCHAR}s and +another type @code{LPCTSTR} which is a const string of @code{TCHAR}s. +The theory is that any program that uses @code{TCHAR}s exclusively to +represent characters and does not make assumptions about the size of a +@code{TCHAR} or the way that the characters are encoded should work +transparently regardless of whether the @code{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 @code{A} (which stands for ANSI, and means multibyte +strings) or @code{W} (which stands for wide, and means Unicode strings). +The mapping is, of course, controlled by the same @code{UNICODE} +preprocessor constant. Generally all structures containing strings in +them actually map to one of two different kinds of structures, with +either an @code{A} or a @code{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 @code{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 @code{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 @strong{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 @code{external_data_format}, which is +declared in @file{lisp.h}, is expanded to contain three new formats, +which are @code{FORMAT_LOCALE}, @code{FORMAT_UNICODE} and +@code{FORMAT_TSTR}. @code{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. @code{FORMAT_UNICODE} +of course causes encoding into Unicode and @code{FORMAT_TSTR} logically +maps to either @code{FORMAT_LOCALE} or @code{FORMAT_UNICODE} depending +on the @code{UNICODE} preprocessor constant. + +Under Unix the behavior of @code{FORMAT_TSTR} is undefined and this +particular format should not be used. Under Windows however +@code{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 @code{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 @code{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 @code{L} (causing it to be a wide string) depending on the +@code{UNICODE} preprocessor constant. + +By the way, if you're wondering what happened to @code{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. + +@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 +@cindex MS Windows, modules for interfacing with +@cindex Windows, modules for interfacing with + +There are two different general Windows-related include files in src. + +Uses are approximately: + +@table @file +@item syswindows.h +Wrapper around @file{<windows.h>}, 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. + +@item console-msw.h +Used on both Cygwin and native Windows, but only when native window +system (as opposed to X) chosen. Includes @file{syswindows.h}. +@end table +Summary of files: +@table @file +@item console-msw.h +include file for native windowing (otherwise, @file{console-x.h}, etc.) +@item console-msw.c, frame-msw.c, etc. +native windowing, as above +@item process-nt.c +subprocess support for native OS (otherwise, @file{process-unix.c}) +@item nt.c +support routines used under native OS +@item win32.c +support routines used under both OS environments +@item syswindows.h +support header for both environments +@item nt/xemacs.mak +Makefile for VC++ (otherwise, @file{src/Makefile.in.in}) +@item s/windowsnt.h +s header for basic native-OS defines, VC++ compiler +@item s/mingw32.h +s header for basic native-OS defines, GCC/MinGW compiler +@item s/cygwin.h +s header for basic Cygwin defines +@item s/win32-native.h +s header for basic native-OS defines, all compilers +@item s/win32-common.h +s header for defines for both OS environments +@item intl-win32.c +internationalization functions for both OS environments +@item intl-encap-win32.c +Unicode encapsulation functions for both OS environments +@item intl-auto-encap-win32.c +Auto-generated Unicode encapsulation functions +@item intl-auto-encap-win32.h +Auto-generated Unicode encapsulation headers +@end table -@node Modules for Regression Testing -@section Modules for Regression Testing -@cindex modules for regression testing -@cindex regression testing, modules for +@node Interface to the X Window System, Dumping, Interface to MS Windows, Top +@chapter Interface to the X Window System +@cindex X Window System, interface to the + +Mostly undocumented. -@example -test-harness.el -base64-tests.el -byte-compiler-tests.el -case-tests.el -ccl-tests.el -c-tests.el -database-tests.el -extent-tests.el -hash-table-tests.el -lisp-tests.el -md5-tests.el -mule-tests.el -regexp-tests.el -symbol-tests.el -syntax-tests.el -tag-tests.el -weak-tests.el -@end example +@menu +* Lucid Widget Library:: An interface to various widget sets. +* Modules for Interfacing with X Windows:: +@end menu -@file{test-harness.el} defines the macros @code{Assert}, -@code{Check-Error}, @code{Check-Error-Message}, and -@code{Check-Message}. The other files are test files, testing various -XEmacs facilities. @xref{Regression Testing XEmacs}. +@node Lucid Widget Library, Modules for Interfacing with X Windows, Interface to the X Window System, Interface to the X Window System +@section Lucid Widget Library +@cindex Lucid Widget Library +@cindex widget library, Lucid +@cindex library, Lucid Widget +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). -@node Allocation of Objects in XEmacs Lisp, Dumping, A Summary of the Various XEmacs Modules, Top -@chapter Allocation of Objects in XEmacs Lisp -@cindex allocation of objects in XEmacs Lisp -@cindex objects in XEmacs Lisp, allocation of -@cindex Lisp objects, allocation of in XEmacs +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 -* Introduction to Allocation:: -* Garbage Collection:: -* GCPROing:: -* Garbage Collection - Step by Step:: -* Integers and Characters:: -* Allocation from Frob Blocks:: -* lrecords:: -* Low-level allocation:: -* Cons:: -* Vector:: -* Bit Vector:: -* Symbol:: -* Marker:: -* String:: -* Compiled Function:: +* Generic Widget Interface:: The lwlib generic widget interface. +* Scrollbars:: +* Menubars:: +* Checkboxes and Radio Buttons:: +* Progress Bars:: +* Tab Controls:: @end menu -@node Introduction to Allocation -@section Introduction to Allocation -@cindex allocation, introduction to +@node Generic Widget Interface, Scrollbars, Lucid Widget Library, Lucid Widget Library +@subsection Generic Widget Interface +@cindex widget interface, generic - Emacs Lisp, like all Lisps, has garbage collection. This means that -the programmer never has to explicitly free (destroy) an object; it -happens automatically when the object becomes inaccessible. Most -experts agree that garbage collection is a necessity in a modern, -high-level language. Its omission from C stems from the fact that C was -originally designed to be a nice abstract layer on top of assembly -language, for writing kernels and basic system utilities rather than -large applications. +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. - Lisp objects can be created by any of a number of Lisp primitives. -Most object types have one or a small number of basic primitives -for creating objects. For conses, the basic primitive is @code{cons}; -for vectors, the primitives are @code{make-vector} and @code{vector}; for -symbols, the primitives are @code{make-symbol} and @code{intern}; etc. -Some Lisp objects, especially those that are primarily used internally, -have no corresponding Lisp primitives. Every Lisp object, though, -has at least one C primitive for creating it. +For each toolkit widget, lwlib maintains a tree of @code{widget_values} +which mirror the hierarchical state of Xt widgets (including Motif, +Athena, 3D Athena, and Falk's widget sets). Each @code{widget_value} +has @code{contents} member, which points to the head of a linked list of +its children. The linked list of siblings is chained through the +@code{next} member of @code{widget_value}. - Recall from section (VII) that a Lisp object, as stored in a 32-bit or -64-bit word, has a few tag bits, and a ``value'' that occupies the -remainder of the bits. We can separate the different Lisp object types -into three broad categories: +@example + +-----------+ + | composite | + +-----------+ + | + | contents + V + +-------+ next +-------+ next +-------+ + | child |----->| child |----->| child | + +-------+ +-------+ +-------+ + | + | contents + V + +-------------+ next +-------------+ + | grand child |----->| grand child | + +-------------+ +-------------+ -@itemize @bullet -@item -(a) Those for whom the value directly represents the contents of the -Lisp object. Only two types are in this category: integers and -characters. No special allocation or garbage collection is necessary -for such objects. Lisp objects of these types do not need to be -@code{GCPRO}ed. -@end itemize +The @code{widget_value} hierarchy of a composite widget with two simple +children and one composite child. +@end example - In the remaining two categories, the type is stored in the object -itself. The tag for all such objects is the generic @dfn{lrecord} -(Lisp_Type_Record) tag. The first bytes of the object's structure are an -integer (actually a char) characterising the object's type and some -flags, in particular the mark bit used for garbage collection. A -structure describing the type is accessible thru the -lrecord_implementation_table indexed with said integer. This structure -includes the method pointers and a pointer to a string naming the type. +The @code{widget_instance} structure maintains the inverse view of the +tree. As for the @code{widget_value}, siblings are chained through the +@code{next} member. However, rather than naming children, the +@code{widget_instance} tree links to parents. -@itemize @bullet -@item -(b) Those lrecords that are allocated in frob blocks (see above). This -includes the objects that are most common and relatively small, and -includes conses, strings, subrs, floats, compiled functions, symbols, -extents, events, and markers. With the cleanup of frob blocks done in -19.12, it's not terribly hard to add more objects to this category, but -it's a bit trickier than adding an object type to type (c) (esp. if the -object needs a finalization method), and is not likely to save much -space unless the object is small and there are many of them. (In fact, -if there are very few of them, it might actually waste space.) -@item -(c) Those lrecords that are individually @code{malloc()}ed. These are -called @dfn{lcrecords}. All other types are in this category. Adding a -new type to this category is comparatively easy, and all types added -since 19.8 (when the current allocation scheme was devised, by Richard -Mlynarik), with the exception of the character type, have been in this -category. -@end itemize +@example + +-----------+ + | composite | + +-----------+ + A + | parent + | + +-------+ next +-------+ next +-------+ + | child |----->| child |----->| child | + +-------+ +-------+ +-------+ + A + | parent + | + +-------------+ next +-------------+ + | grand child |----->| grand child | + +-------------+ +-------------+ - Note that bit vectors are a bit of a special case. They are -simple lrecords as in category (b), but are individually @code{malloc()}ed -like vectors. You can basically view them as exactly like vectors -except that their type is stored in lrecord fashion rather than -in directly-tagged fashion. +The @code{widget_value} hierarchy of a composite widget with two simple +children and one composite child. +@end example +This permits widgets derived from different toolkits to be updated and +manipulated generically by the lwlib library. For instance +@code{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 @code{widget_value} by walking the +@code{widget_value} tree. This has desirable properties. For example, +@code{lw_modify_all_widgets} is called from @file{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. -@node Garbage Collection -@section Garbage Collection -@cindex garbage collection +The @code{widget_instance} structure also contains a pointer to the root +of its tree. Widget instances are further confi -@cindex mark and sweep - Garbage collection is simple in theory but tricky to implement. -Emacs Lisp uses the oldest garbage collection method, called -@dfn{mark and sweep}. Garbage collection begins by starting with -all accessible locations (i.e. all variables and other slots where -Lisp objects might occur) and recursively traversing all objects -accessible from those slots, marking each one that is found. -We then go through all of memory and free each object that is -not marked, and unmarking each object that is marked. Note -that ``all of memory'' means all currently allocated objects. -Traversing all these objects means traversing all frob blocks, -all vectors (which are chained in one big list), and all -lcrecords (which are likewise chained). - Garbage collection can be invoked explicitly by calling -@code{garbage-collect} but is also called automatically by @code{eval}, -once a certain amount of memory has been allocated since the last -garbage collection (according to @code{gc-cons-threshold}). +@node Scrollbars, Menubars, Generic Widget Interface, Lucid Widget Library +@subsection Scrollbars +@cindex scrollbars +@node Menubars, Checkboxes and Radio Buttons, Scrollbars, Lucid Widget Library +@subsection Menubars +@cindex menubars -@node GCPROing -@section @code{GCPRO}ing -@cindex @code{GCPRO}ing -@cindex garbage collection protection -@cindex protection, garbage collection +@node Checkboxes and Radio Buttons, Progress Bars, Menubars, Lucid Widget Library +@subsection Checkboxes and Radio Buttons +@cindex checkboxes and radio buttons +@cindex radio buttons, checkboxes and +@cindex buttons, checkboxes and radio -@code{GCPRO}ing is one of the ugliest and trickiest parts of Emacs -internals. The basic idea is that whenever garbage collection -occurs, all in-use objects must be reachable somehow or -other from one of the roots of accessibility. The roots -of accessibility are: +@node Progress Bars, Tab Controls, Checkboxes and Radio Buttons, Lucid Widget Library +@subsection Progress Bars +@cindex progress bars +@cindex bars, progress -@enumerate -@item -All objects that have been @code{staticpro()}d or -@code{staticpro_nodump()}ed. This is used for any global C variables -that hold Lisp objects. A call to @code{staticpro()} happens implicitly -as a result of any symbols declared with @code{defsymbol()} and any -variables declared with @code{DEFVAR_FOO()}. You need to explicitly -call @code{staticpro()} (in the @code{vars_of_foo()} method of a module) -for other global C variables holding Lisp objects. (This typically -includes internal lists and such things.). Use -@code{staticpro_nodump()} only in the rare cases when you do not want -the pointed variable to be saved at dump time but rather recompute it at -startup. +@node Tab Controls, , Progress Bars, Lucid Widget Library +@subsection Tab Controls +@cindex tab controls -Note that @code{obarray} is one of the @code{staticpro()}d things. -Therefore, all functions and variables get marked through this. -@item -Any shadowed bindings that are sitting on the @code{specpdl} stack. -@item -Any objects sitting in currently active (Lisp) stack frames, -catches, and condition cases. -@item -A couple of special-case places where active objects are -located. -@item -Anything currently marked with @code{GCPRO}. -@end enumerate - Marking with @code{GCPRO} is necessary because some C functions (quite -a lot, in fact), allocate objects during their operation. Quite -frequently, there will be no other pointer to the object while the -function is running, and if a garbage collection occurs and the object -needs to be referenced again, bad things will happen. The solution is -to mark those references with @code{GCPRO}. Note that it is a -@emph{reference} that is marked with @code{GCPRO}, not an object. If -you declare a @code{Lisp_Object} variable, assign to it, @code{GCPRO} -it, and then assign to it again, the first object assigned @emph{is not} -protected, while the second object @emph{is} protected. Unfortunately -@code{GCPRO}ing is easy to forget, and there is basically no way around -this problem. Here are some rules, though: +@node Modules for Interfacing with X Windows, , Lucid Widget Library, Interface to the X Window System +@section Modules for Interfacing with X Windows +@cindex modules for interfacing with X Windows +@cindex interfacing with X Windows, modules for +@cindex X Windows, modules for interfacing with -@enumerate -@item -A garbage collection can occur whenever anything calls @code{Feval}, or -whenever a @code{QUIT} can occur where execution can continue past -this. (Remember, this is almost anywhere.) Note that @code{Fsignal} can -GC, and it can return (even though it normally doesn't). This means -that you must @code{GCPRO} before calling most of the error functions, -including the @samp{CONCHECK} family of macros, if references occur -after the call. +@example +Emacs.ad.h +@end example -@item -You @emph{must} @code{UNGCPRO} anything that's @code{GCPRO}ed, and you -@emph{must not} @code{UNGCPRO} if you haven't @code{GCPRO}ed. Getting -either of these wrong will lead to crashes, often in completely random -places unrelated to where the problem lies. There are some functions -(@code{Fsignal} is the canonical example) which may or may not return. -In these cases, the function is responsible for cleaning up the -@code{GCPRO}s if it doesn't return, so you should treat it as an -ordinary function. +A file generated from @file{Emacs.ad}, which contains XEmacs-supplied +fallback resources (so that XEmacs has pretty defaults). -@item -For every @code{GCPRO@var{n}}, there have to be declarations of -@code{struct gcpro gcpro1, gcpro2, ..., gcpro@var{n}}. -@item -The way this actually works is that all currently active @code{GCPRO}s -are chained through the @code{struct gcpro} local variables, with the -variable @samp{gcprolist} pointing to the head of the list and the nth -local @code{gcpro} variable pointing to the first @code{gcpro} variable -in the next enclosing stack frame. Each @code{GCPRO}ed thing is an -lvalue, and the @code{struct gcpro} local variable contains a pointer to -this lvalue. This is why things will mess up badly if you don't pair up -the @code{GCPRO}s and @code{UNGCPRO}s---you will end up with -@code{gcprolist}s containing pointers to @code{struct gcpro}s or local -@code{Lisp_Object} variables in no-longer-active stack frames. -@item -It is actually possible for a single @code{struct gcpro} to -protect a contiguous array of any number of values, rather than -just a single lvalue. To effect this, call @code{GCPRO@var{n}} as usual on -the first object in the array and then set @code{gcpro@var{n}.nvars}. +@example +EmacsFrame.c +EmacsFrame.h +EmacsFrameP.h +@end example -@item -@strong{Strings are relocated.} What this means in practice is that the -pointer obtained using @code{XSTRING_DATA()} is liable to change at any -time, and you should never keep it around past any function call, or -pass it as an argument to any function that might cause a garbage -collection. This is why a number of functions accept either a -``non-relocatable'' @code{char *} pointer or a relocatable Lisp string, -and only access the Lisp string's data at the very last minute. In some -cases, you may end up having to @code{alloca()} some space and copy the -string's data into it. +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. -@item -By convention, if you have to nest @code{GCPRO}'s, use @code{NGCPRO@var{n}} -(along with @code{struct gcpro ngcpro1, ngcpro2}, etc.), @code{NNGCPRO@var{n}}, -etc. This avoids compiler warnings about shadowed locals. +@strong{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. -@item -It is @emph{always} better to err on the side of extra @code{GCPRO}s -rather than too few. The extra cycles spent on this are -almost never going to make a whit of difference in the -speed of anything. -@item -The general rule to follow is that caller, not callee, @code{GCPRO}s. -That is, you should not have to explicitly @code{GCPRO} any Lisp objects -that are passed in as parameters. -One exception from this rule is if you ever plan to change the parameter -value, and store a new object in it. In that case, you @emph{must} -@code{GCPRO} the parameter, because otherwise the new object will not be -protected. +@example +EmacsManager.c +EmacsManager.h +EmacsManagerP.h +@end example -So, if you create any Lisp objects (remember, this happens in all sorts -of circumstances, e.g. with @code{Fcons()}, etc.), you are responsible -for @code{GCPRO}ing them, unless you are @emph{absolutely sure} that -there's no possibility that a garbage-collection can occur while you -need to use the object. Even then, consider @code{GCPRO}ing. +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. -@item -If you have the @emph{least smidgeon of doubt} about whether -you need to @code{GCPRO}, you should @code{GCPRO}. -@item -Beware of @code{GCPRO}ing something that is uninitialized. If you have -any shade of doubt about this, initialize all your variables to @code{Qnil}. +@example +EmacsShell-sub.c +EmacsShell.c +EmacsShell.h +EmacsShellP.h +@end example -@item -Be careful of traps, like calling @code{Fcons()} in the argument to -another function. By the ``caller protects'' law, you should be -@code{GCPRO}ing the newly-created cons, but you aren't. A certain -number of functions that are commonly called on freshly created stuff -(e.g. @code{nconc2()}, @code{Fsignal()}), break the ``caller protects'' -law and go ahead and @code{GCPRO} their arguments so as to simplify -things, but make sure and check if it's OK whenever doing something like -this. +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. -@item -Once again, remember to @code{GCPRO}! Bugs resulting from insufficient -@code{GCPRO}ing are intermittent and extremely difficult to track down, -often showing up in crashes inside of @code{garbage-collect} or in -weirdly corrupted objects or even in incorrect values in a totally -different section of code. -@end enumerate -If you don't understand whether to @code{GCPRO} in a particular -instance, ask on the mailing lists. A general hint is that @code{prog1} -is the canonical example. -@cindex garbage collection, conservative -@cindex conservative garbage collection - Given the extremely error-prone nature of the @code{GCPRO} scheme, and -the difficulties in tracking down, it should be considered a deficiency -in the XEmacs code. A solution to this problem would involve -implementing so-called @dfn{conservative} garbage collection for the C -stack. That involves looking through all of stack memory and treating -anything that looks like a reference to an object as a reference. This -will result in a few objects not getting collected when they should, but -it obviates the need for @code{GCPRO}ing, and allows garbage collection -to happen at any point at all, such as during object allocation. +@example +xgccache.c +xgccache.h +@end example -@node Garbage Collection - Step by Step -@section Garbage Collection - Step by Step -@cindex garbage collection - step by step +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. -@menu -* Invocation:: -* garbage_collect_1:: -* mark_object:: -* gc_sweep:: -* sweep_lcrecords_1:: -* compact_string_chars:: -* sweep_strings:: -* sweep_bit_vectors_1:: -@end menu -@node Invocation -@subsection Invocation -@cindex garbage collection, invocation -The first thing that anyone should know about garbage collection is: -when and how the garbage collector is invoked. One might think that this -could happen every time new memory is allocated, e.g. new objects are -created, but this is @emph{not} the case. Instead, we have the following -situation: +@example +select-msw.c +select-x.c +select.c +select.h +@end example -The entry point of any process of garbage collection is an invocation -of the function @code{garbage_collect_1} in file @code{alloc.c}. The -invocation can occur @emph{explicitly} by calling the function -@code{Fgarbage_collect} (in addition this function provides information -about the freed memory), or can occur @emph{implicitly} in four different -situations: -@enumerate -@item -In function @code{main_1} in file @code{emacs.c}. This function is called -at each startup of xemacs. The garbage collection is invoked after all -initial creations are completed, but only if a special internal error -checking-constant @code{ERROR_CHECK_GC} is defined. -@item -In function @code{disksave_object_finalization} in file -@code{alloc.c}. The only purpose of this function is to clear the -objects from memory which need not be stored with xemacs when we dump out -an executable. This is only done by @code{Fdump_emacs} or by -@code{Fdump_emacs_data} respectively (both in @code{emacs.c}). The -actual clearing is accomplished by making these objects unreachable and -starting a garbage collection. The function is only used while building -xemacs. -@item -In function @code{Feval / eval} in file @code{eval.c}. Each time the -well known and often used function eval is called to evaluate a form, -one of the first things that could happen, is a potential call of -@code{garbage_collect_1}. There exist three global variables, -@code{consing_since_gc} (counts the created cons-cells since the last -garbage collection), @code{gc_cons_threshold} (a specified threshold -after which a garbage collection occurs) and @code{always_gc}. If -@code{always_gc} is set or if the threshold is exceeded, the garbage -collection will start. -@item -In function @code{Ffuncall / funcall} in file @code{eval.c}. This -function evaluates calls of elisp functions and works according to -@code{Feval}. -@end enumerate +@cindex selections + This module provides an interface to the X Window System's concept of +@dfn{selections}, the standard way for X applications to communicate +with each other. -The upshot is that garbage collection can basically occur everywhere -@code{Feval}, respectively @code{Ffuncall}, is used - either directly or -through another function. Since calls to these two functions are hidden -in various other functions, many calls to @code{garbage_collect_1} are -not obviously foreseeable, and therefore unexpected. Instances where -they are used that are worth remembering are various elisp commands, as -for example @code{or}, @code{and}, @code{if}, @code{cond}, @code{while}, -@code{setq}, etc., miscellaneous @code{gui_item_...} functions, -everything related to @code{eval} (@code{Feval_buffer}, @code{call0}, -...) and inside @code{Fsignal}. The latter is used to handle signals, as -for example the ones raised by every @code{QUIT}-macro triggered after -pressing Ctrl-g. -@node garbage_collect_1 -@subsection @code{garbage_collect_1} -@cindex @code{garbage_collect_1} -We can now describe exactly what happens after the invocation takes -place. -@enumerate -@item -There are several cases in which the garbage collector is left immediately: -when we are already garbage collecting (@code{gc_in_progress}), when -the garbage collection is somehow forbidden -(@code{gc_currently_forbidden}), when we are currently displaying something -(@code{in_display}) or when we are preparing for the armageddon of the -whole system (@code{preparing_for_armageddon}). -@item -Next the correct frame in which to put -all the output occurring during garbage collecting is determined. In -order to be able to restore the old display's state after displaying the -message, some data about the current cursor position has to be -saved. The variables @code{pre_gc_cursor} and @code{cursor_changed} take -care of that. -@item -The state of @code{gc_currently_forbidden} must be restored after -the garbage collection, no matter what happens during the process. We -accomplish this by @code{record_unwind_protect}ing the suitable function -@code{restore_gc_inhibit} together with the current value of -@code{gc_currently_forbidden}. -@item -If we are concurrently running an interactive xemacs session, the next step -is simply to show the garbage collector's cursor/message. -@item -The following steps are the intrinsic steps of the garbage collector, -therefore @code{gc_in_progress} is set. -@item -For debugging purposes, it is possible to copy the current C stack -frame. However, this seems to be a currently unused feature. -@item -Before actually starting to go over all live objects, references to -objects that are no longer used are pruned. We only have to do this for events -(@code{clear_event_resource}) and for specifiers -(@code{cleanup_specifiers}). -@item -Now the mark phase begins and marks all accessible elements. In order to -start from -all slots that serve as roots of accessibility, the function -@code{mark_object} is called for each root individually to go out from -there to mark all reachable objects. All roots that are traversed are -shown in their processed order: +@example +xintrinsic.h +xintrinsicp.h +xmmanagerp.h +xmprimitivep.h +@end example + +These header files are similar in spirit to the @file{sys*.h} files and buffer +against different implementations of Xt and Motif. + @itemize @bullet @item -all constant symbols and static variables that are registered via -@code{staticpro}@ in the dynarr @code{staticpros}. -@xref{Adding Global Lisp Variables}. -@item -all Lisp objects that are created in C functions and that must be -protected from freeing them. They are registered in the global -list @code{gcprolist}. -@xref{GCPROing}. -@item -all local variables (i.e. their name fields @code{symbol} and old -values @code{old_values}) that are bound during the evaluation by the Lisp -engine. They are stored in @code{specbinding} structs pushed on a stack -called @code{specpdl}. -@xref{Dynamic Binding; The specbinding Stack; Unwind-Protects}. -@item -all catch blocks that the Lisp engine encounters during the evaluation -cause the creation of structs @code{catchtag} inserted in the list -@code{catchlist}. Their tag (@code{tag}) and value (@code{val} fields -are freshly created objects and therefore have to be marked. -@xref{Catch and Throw}. +@file{xintrinsic.h} should be included in place of @file{<Intrinsic.h>}. @item -every function application pushes new structs @code{backtrace} -on the call stack of the Lisp engine (@code{backtrace_list}). The unique -parts that have to be marked are the fields for each function -(@code{function}) and all their arguments (@code{args}). -@xref{Evaluation}. +@file{xintrinsicp.h} should be included in place of @file{<IntrinsicP.h>}. @item -all objects that are used by the redisplay engine that must not be freed -are marked by a special function called @code{mark_redisplay} (in -@code{redisplay.c}). +@file{xmmanagerp.h} should be included in place of @file{<XmManagerP.h>}. @item -all objects created for profiling purposes are allocated by C functions -instead of using the lisp allocation mechanisms. In order to receive the -right ones during the sweep phase, they also have to be marked -manually. That is done by the function @code{mark_profiling_info} +@file{xmprimitivep.h} should be included in place of @file{<XmPrimitiveP.h>}. @end itemize -@item -Hash tables in XEmacs belong to a kind of special objects that -make use of a concept often called 'weak pointers'. -To make a long story short, these kind of pointers are not followed -during the estimation of the live objects during garbage collection. -Any object referenced only by weak pointers is collected -anyway, and the reference to it is cleared. In hash tables there are -different usage patterns of them, manifesting in different types of hash -tables, namely 'non-weak', 'weak', 'key-weak' and 'value-weak' -(internally also 'key-car-weak' and 'value-car-weak') hash tables, each -clearing entries depending on different conditions. More information can -be found in the documentation to the function @code{make-hash-table}. -Because there are complicated dependency rules about when and what to -mark while processing weak hash tables, the standard @code{marker} -method is only active if it is marking non-weak hash tables. As soon as -a weak component is in the table, the hash table entries are ignored -while marking. Instead their marking is done each separately by the -function @code{finish_marking_weak_hash_tables}. This function iterates -over each hash table entry @code{hentries} for each weak hash table in -@code{Vall_weak_hash_tables}. Depending on the type of a table, the -appropriate action is performed. -If a table is acting as @code{HASH_TABLE_KEY_WEAK}, and a key already marked, -everything reachable from the @code{value} component is marked. If it is -acting as a @code{HASH_TABLE_VALUE_WEAK} and the value component is -already marked, the marking starts beginning only from the -@code{key} component. -If it is a @code{HASH_TABLE_KEY_CAR_WEAK} and the car -of the key entry is already marked, we mark both the @code{key} and -@code{value} components. -Finally, if the table is of the type @code{HASH_TABLE_VALUE_CAR_WEAK} -and the car of the value components is already marked, again both the -@code{key} and the @code{value} components get marked. -Again, there are lists with comparable properties called weak -lists. There exist different peculiarities of their types called -@code{simple}, @code{assoc}, @code{key-assoc} and -@code{value-assoc}. You can find further details about them in the -description to the function @code{make-weak-list}. The scheme of their -marking is similar: all weak lists are listed in @code{Qall_weak_lists}, -therefore we iterate over them. The marking is advanced until we hit an -already marked pair. Then we know that during a former run all -the rest has been marked completely. Again, depending on the special -type of the weak list, our jobs differ. If it is a @code{WEAK_LIST_SIMPLE} -and the elem is marked, we mark the @code{cons} part. If it is a -@code{WEAK_LIST_ASSOC} and not a pair or a pair with both marked car and -cdr, we mark the @code{cons} and the @code{elem}. If it is a -@code{WEAK_LIST_KEY_ASSOC} and not a pair or a pair with a marked car of -the elem, we mark the @code{cons} and the @code{elem}. Finally, if it is -a @code{WEAK_LIST_VALUE_ASSOC} and not a pair or a pair with a marked -cdr of the elem, we mark both the @code{cons} and the @code{elem}. -Since, by marking objects in reach from weak hash tables and weak lists, -other objects could get marked, this perhaps implies further marking of -other weak objects, both finishing functions are redone as long as -yet unmarked objects get freshly marked. +@example +xmu.c +xmu.h +@end example -@item -After completing the special marking for the weak hash tables and for the weak -lists, all entries that point to objects that are going to be swept in -the further process are useless, and therefore have to be removed from -the table or the list. +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. -The function @code{prune_weak_hash_tables} does the job for weak hash -tables. Totally unmarked hash tables are removed from the list -@code{Vall_weak_hash_tables}. The other ones are treated more carefully -by scanning over all entries and removing one as soon as one of -the components @code{key} and @code{value} is unmarked. -The same idea applies to the weak lists. It is accomplished by -@code{prune_weak_lists}: An unmarked list is pruned from -@code{Vall_weak_lists} immediately. A marked list is treated more -carefully by going over it and removing just the unmarked pairs. -@item -The function @code{prune_specifiers} checks all listed specifiers held -in @code{Vall_specifiers} and removes the ones from the lists that are -unmarked. +@example +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 +@end example -@item -All syntax tables are stored in a list called -@code{Vall_syntax_tables}. The function @code{prune_syntax_tables} walks -through it and unlinks the tables that are unmarked. +@cindex external widget + These files provide the @dfn{external widget} interface, which allows an +XEmacs frame to appear as a widget in another application. To do this, +you have to configure with @samp{--external-widget}. +@file{ExternalShell*} provides the server (XEmacs) side of the +connection. + +@file{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. + +@file{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. + + +@node Dumping, Future Work, Interface to the X Window System, Top +@chapter Dumping +@cindex dumping + +@menu +* Dumping Justification:: +* Overview:: +* Data descriptions:: +* Dumping phase:: +* Reloading phase:: +* Remaining issues:: +@end menu + +@node Dumping Justification, Overview, Dumping, Dumping +@section Dumping Justification +@cindex 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 @file{temacs}, then +runs it until it has finished loading and initializing all the lisp +code, and eventually creates a new executable called @file{xemacs} +including both the object code in @file{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 @code{main()}) which tend to +crash when they are called multiple times, once before dumping and once +after (IRIX 6.x @file{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. + +@node Overview, Data descriptions, Dumping Justification, Dumping +@section Overview +@cindex dumping overview + +The portable dumping system has to: + +@enumerate @item -Next, we will attack the complete sweeping - the function -@code{gc_sweep} which holds the predominance. -@item -First, all the variables with respect to garbage collection are -reset. @code{consing_since_gc} - the counter of the created cells since -the last garbage collection - is set back to 0, and -@code{gc_in_progress} is not @code{true} anymore. -@item -In case the session is interactive, the displayed cursor and message are -removed again. -@item -The state of @code{gc_inhibit} is restored to the former value by -unwinding the stack. +At dump time, write all initialized, non-quickly-rebuildable data to a +file [Note: currently named @file{xemacs.dmp}, but the name will +change], along with all information needed for the reloading. + @item -A small memory reserve is always held back that can be reached by -@code{breathing_space}. If nothing more is left, we create a new reserve -and exit. +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. @end enumerate -@node mark_object -@subsection @code{mark_object} -@cindex @code{mark_object} +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. -The first thing that is checked while marking an object is whether the -object is a real Lisp object @code{Lisp_Type_Record} or just an integer -or a character. Integers and characters are the only two types that are -stored directly - without another level of indirection, and therefore they -don't have to be marked and collected. -@xref{How Lisp Objects Are Represented in C}. +@node Data descriptions, Dumping phase, Overview, Dumping +@section Data descriptions +@cindex dumping data descriptions -The second case is the one we have to handle. It is the one when we are -dealing with a pointer to a Lisp object. But, there exist also three -possibilities, that prevent us from doing anything while marking: The -object is read only which prevents it from being garbage collected, -i.e. marked (@code{C_READONLY_RECORD_HEADER}). The object in question is -already marked, and need not be marked for the second time (checked by -@code{MARKED_RECORD_HEADER_P}). If it is a special, unmarkable object -(@code{UNMARKABLE_RECORD_HEADER_P}, apparently, these are objects that -sit in some const space, and can therefore not be marked, see -@code{this_one_is_unmarkable} in @code{alloc.c}). +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. -Now, the actual marking is feasible. We do so by once using the macro -@code{MARK_RECORD_HEADER} to mark the object itself (actually the -special flag in the lrecord header), and calling its special marker -"method" @code{marker} if available. The marker method marks every -other object that is in reach from our current object. Note, that these -marker methods should not call @code{mark_object} recursively, but -instead should return the next object from where further marking has to -be performed. +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: + +@example +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 @} +@}; +@end example -In case another object was returned, as mentioned before, we reiterate -the whole @code{mark_object} process beginning with this next object. +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 @code{data}". The length of said data is +given by the expression @code{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 @code{plist} in the Lisp_String +structure". @code{XD_END} then ends the description. -@node gc_sweep -@subsection @code{gc_sweep} -@cindex @code{gc_sweep} +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. -The job of this function is to free all unmarked records from memory. As -we know, there are different types of objects implemented and managed, and -consequently different ways to free them from memory. -@xref{Introduction to Allocation}. +@node Dumping phase, Reloading phase, Data descriptions, Dumping +@section Dumping phase +@cindex dumping phase -We start with all objects stored through @code{lcrecords}. All -bulkier objects are allocated and handled using that scheme of -@code{lcrecords}. Each object is @code{malloc}ed separately -instead of placing it in one of the contiguous frob blocks. All types -that are currently stored -using @code{lcrecords}'s @code{alloc_lcrecord} and -@code{make_lcrecord_list} are the types: vectors, buffers, -char-table, char-table-entry, console, weak-list, database, device, -ldap, hash-table, command-builder, extent-auxiliary, extent-info, face, -coding-system, frame, image-instance, glyph, popup-data, gui-item, -keymap, charset, color_instance, font_instance, opaque, opaque-list, -process, range-table, specifier, symbol-value-buffer-local, -symbol-value-lisp-magic, symbol-value-varalias, toolbar-button, -tooltalk-message, tooltalk-pattern, window, and window-configuration. We -take care of them in the fist place -in order to be able to handle and to finalize items stored in them more -easily. The function @code{sweep_lcrecords_1} as described below is -doing the whole job for us. -For a description about the internals: @xref{lrecords}. +Dumping is done by calling the function @code{pdump()} (in @file{dumper.c}) which is +invoked from Fdump_emacs (in @file{emacs.c}). This function performs a number +of tasks. -Our next candidates are the other objects that behave quite differently -than everything else: the strings. They consists of two parts, a -fixed-size portion (@code{struct Lisp_String}) holding the string's -length, its property list and a pointer to the second part, and the -actual string data, which is stored in string-chars blocks comparable to -frob blocks. In this block, the data is not only freed, but also a -compression of holes is made, i.e. all strings are relocated together. -@xref{String}. This compacting phase is performed by the function -@code{compact_string_chars}, the actual sweeping by the function -@code{sweep_strings} is described below. +@menu +* Object inventory:: +* Address allocation:: +* The header:: +* Data dumping:: +* Pointers dumping:: +@end menu -After that, the other types are swept step by step using functions -@code{sweep_conses}, @code{sweep_bit_vectors_1}, -@code{sweep_compiled_functions}, @code{sweep_floats}, -@code{sweep_symbols}, @code{sweep_extents}, @code{sweep_markers} and -@code{sweep_extents}. They are the fixed-size types cons, floats, -compiled-functions, symbol, marker, extent, and event stored in -so-called "frob blocks", and therefore we can basically do the same on -every type objects, using the same macros, especially defined only to -handle everything with respect to fixed-size blocks. The only fixed-size -type that is not handled here are the fixed-size portion of strings, -because we took special care of them earlier. +@node Object inventory, Address allocation, Dumping phase, Dumping phase +@subsection Object inventory +@cindex dumping object inventory +@cindex memory blocks -The only big exceptions are bit vectors stored differently and -therefore treated differently by the function @code{sweep_bit_vectors_1} -described later. +The first task is to build the list of the objects to dump. This +includes: -At first, we need some brief information about how -these fixed-size types are managed in general, in order to understand -how the sweeping is done. They have all a fixed size, and are therefore -stored in big blocks of memory - allocated at once - that can hold a -certain amount of objects of one type. The macro -@code{DECLARE_FIXED_TYPE_ALLOC} creates the suitable structures for -every type. More precisely, we have the block struct -(holding a pointer to the previous block @code{prev} and the -objects in @code{block[]}), a pointer to current block -(@code{current_..._block)}) and its last index -(@code{current_..._block_index}), and a pointer to the free list that -will be created. Also a macro @code{FIXED_TYPE_FROM_BLOCK} plus some -related macros exists that are used to obtain a new object, either from -the free list @code{ALLOCATE_FIXED_TYPE_1} if there is an unused object -of that type stored or by allocating a completely new block using -@code{ALLOCATE_FIXED_TYPE_FROM_BLOCK}. +@itemize @bullet +@item lisp objects +@item other memory blocks (C structures, arrays. etc) +@end itemize -The rest works as follows: all of them define a -macro @code{UNMARK_...} that is used to unmark the object. They define a -macro @code{ADDITIONAL_FREE_...} that defines additional work that has -to be done when converting an object from in use to not in use (so far, -only markers use it in order to unchain them). Then, they all call -the macro @code{SWEEP_FIXED_TYPE_BLOCK} instantiated with their type name -and their struct name. +We end up with one @code{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. -This call in particular does the following: we go over all blocks -starting with the current moving towards the oldest. -For each block, we look at every object in it. If the object already -freed (checked with @code{FREE_STRUCT_P} using the first pointer of the -object), or if it is -set to read only (@code{C_READONLY_RECORD_HEADER_P}, nothing must be -done. If it is unmarked (checked with @code{MARKED_RECORD_HEADER_P}), it -is put in the free list and set free (using the macro -@code{FREE_FIXED_TYPE}, otherwise it stays in the block, but is unmarked -(by @code{UNMARK_...}). While going through one block, we note if the -whole block is empty. If so, the whole block is freed (using -@code{xfree}) and the free list state is set to the state it had before -handling this block. +These entries are linked together in @code{pdump_block_list} structures +and can be enumerated thru either: -@node sweep_lcrecords_1 -@subsection @code{sweep_lcrecords_1} -@cindex @code{sweep_lcrecords_1} +@enumerate +@item +the @code{pdump_object_table}, an array of @code{pdump_block_list}, one +per lrecord type, indexed by type number. -After nullifying the complete lcrecord statistics, we go over all -lcrecords two separate times. They are all chained together in a list with -a head called @code{all_lcrecords}. +@item +the @code{pdump_opaque_data_list}, used for the opaque data which does +not include pointers, and hence does not need descriptions. -The first loop calls for each object its @code{finalizer} method, but only -in the case that it is not read only -(@code{C_READONLY_RECORD_HEADER_P)}, it is not already marked -(@code{MARKED_RECORD_HEADER_P}), it is not already in a free list (list of -freed objects, field @code{free}) and finally it owns a finalizer -method. +@item +the @code{pdump_desc_table}, which is a vector of +@code{memory_description}/@code{pdump_block_list} pairs, used for +non-opaque C memory blocks. +@end enumerate -The second loop actually frees the appropriate objects again by iterating -through the whole list. In case an object is read only or marked, it -has to persist, otherwise it is manually freed by calling -@code{xfree}. During this loop, the lcrecord statistics are kept up to -date by calling @code{tick_lcrecord_stats} with the right arguments, +This uses a marking strategy similar to the garbage collector. Some +differences though: -@node compact_string_chars -@subsection @code{compact_string_chars} -@cindex @code{compact_string_chars} +@enumerate +@item +We do not use the mark bit (which does not exist for generic memory blocks +anyway); we use a big hash table instead. -The purpose of this function is to compact all the data parts of the -strings that are held in so-called @code{string_chars_block}, i.e. the -strings that do not exceed a certain maximal length. +@item +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. +@end enumerate -The procedure with which this is done is as follows. We are keeping two -positions in the @code{string_chars_block}s using two pointer/integer -pairs, namely @code{from_sb}/@code{from_pos} and -@code{to_sb}/@code{to_pos}. They stand for the actual positions, from -where to where, to copy the actually handled string. +This is done by @code{pdump_register_object()}, which handles +Lisp_Object variables, and @code{pdump_register_block()} which handles +generic memory blocks (C structures, arrays, etc.), which both delegate +the description management to @code{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 @code{pdump_add_block()} and looked up with +@code{pdump_get_block()}. There is no need for entry removal. The hash +value is computed quite simply from the object pointer by +@code{pdump_make_hash()}. -While going over all chained @code{string_char_block}s and their held -strings, staring at @code{first_string_chars_block}, both pointers -are advanced and eventually a string is copied from @code{from_sb} to -@code{to_sb}, depending on the status of the pointed at strings. +The roots for the marking are: -More precisely, we can distinguish between the following actions. -@itemize @bullet +@enumerate @item -The string at @code{from_sb}'s position could be marked as free, which -is indicated by an invalid pointer to the pointer that should point back -to the fixed size string object, and which is checked by -@code{FREE_STRUCT_P}. In this case, the @code{from_sb}/@code{from_pos} -is advanced to the next string, and nothing has to be copied. +the @code{staticpro}'ed variables (there is a special +@code{staticpro_nodump()} call for protected variables we do not want to +dump). + @item -Also, if a string object itself is unmarked, nothing has to be -copied. We likewise advance the @code{from_sb}/@code{from_pos} -pair as described above. +the Lisp_Object variables registered via @code{dump_add_root_lisp_object} +(@code{staticpro()} is equivalent to @code{staticpro_nodump()} + +@code{dump_add_root_lisp_object()}). + @item -In all other cases, we have a marked string at hand. The string data -must be moved from the from-position to the to-position. In case -there is not enough space in the actual @code{to_sb}-block, we advance -this pointer to the beginning of the next block before copying. In case the -from and to positions are different, we perform the -actual copying using the library function @code{memmove}. -@end itemize +the data-segment memory blocks registered via @code{dump_add_root_block} +(for blocks with relocatable pointers), or @code{dump_add_opaque} (for +"opaque" blocks with no relocatable pointers; this is just a shortcut +for calling @code{dump_add_root_block} with a NULL description). + +@item +the pointer variables registered via @code{dump_add_root_block_ptr}, +each of which points to a block of heap memory (generally a C structure +or array). Note that @code{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 +@code{dump_add_root_block}. Doing it this way, however, would require +another level of static structures declared. Since pointer variables +are quite common, @code{dump_add_root_block_ptr} is provided for +convenience. Note also that internally we have to treat it separately +from @code{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. +@end enumerate -After compacting, the pointer to the current -@code{string_chars_block}, sitting in @code{current_string_chars_block}, -is reset on the last block to which we moved a string, -i.e. @code{to_block}, and all remaining blocks (we know that they just -carry garbage) are explicitly @code{xfree}d. +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. -@node sweep_strings -@subsection @code{sweep_strings} -@cindex @code{sweep_strings} +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. -The sweeping for the fixed sized string objects is essentially exactly -the same as it is for all other fixed size types. As before, the freeing -into the suitable free list is done by using the macro -@code{SWEEP_FIXED_SIZE_BLOCK} after defining the right macros -@code{UNMARK_string} and @code{ADDITIONAL_FREE_string}. These two -definitions are a little bit special compared to the ones used -for the other fixed size types. +@node Address allocation, The header, Object inventory, Dumping phase +@subsection Address allocation +@cindex dumping address allocation -@code{UNMARK_string} is defined the same way except some additional code -used for updating the bookkeeping information. -For strings, @code{ADDITIONAL_FREE_string} has to do something in -addition: in case, the string was not allocated in a -@code{string_chars_block} because it exceeded the maximal length, and -therefore it was @code{malloc}ed separately, we know also @code{xfree} -it explicitly. +The next step is to allocate the offsets of each of the objects in the +final dump file. This is done by @code{pdump_allocate_offset()} which +is called indirectly by @code{pdump_scan_by_alignment()}. -@node sweep_bit_vectors_1 -@subsection @code{sweep_bit_vectors_1} -@cindex @code{sweep_bit_vectors_1} +The strategy to deal with alignment problems uses these facts: -Bit vectors are also one of the rare types that are @code{malloc}ed -individually. Consequently, while sweeping, all further needless -bit vectors must be freed by hand. This is done, as one might imagine, -the expected way: since they are all registered in a list called -@code{all_bit_vectors}, all elements of that list are traversed, -all unmarked bit vectors are unlinked by calling @code{xfree} and all of -them become unmarked. -In addition, the bookkeeping information used for garbage -collector's output purposes is updated. +@enumerate +@item +real world alignment requirements are powers of two. -@node Integers and Characters -@section Integers and Characters -@cindex integers and characters -@cindex characters, integers and +@item +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. - Integer and character Lisp objects are created from integers using the -macros @code{XSETINT()} and @code{XSETCHAR()} or the equivalent -functions @code{make_int()} and @code{make_char()}. (These are actually -macros on most systems.) These functions basically just do some moving -of bits around, since the integral value of the object is stored -directly in the @code{Lisp_Object}. +@item +the non-variant part of variable size lrecords has an alignment +requirement of 4. +@end enumerate - @code{XSETINT()} and the like will truncate values given to them that -are too big; i.e. you won't get the value you expected but the tag bits -will at least be correct. +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. @code{pdump_scan_by_alignment()} then scans all the +@code{pdump_block_list_elmt}'s, the ones with the highest requirements +first. This ensures the best packing. -@node Allocation from Frob Blocks -@section Allocation from Frob Blocks -@cindex allocation from frob blocks -@cindex frob blocks, allocation from +The maximum alignment requirement we take into account is 2^8. -The uninitialized memory required by a @code{Lisp_Object} of a particular type -is allocated using -@code{ALLOCATE_FIXED_TYPE()}. This only occurs inside of the -lowest-level object-creating functions in @file{alloc.c}: -@code{Fcons()}, @code{make_float()}, @code{Fmake_byte_code()}, -@code{Fmake_symbol()}, @code{allocate_extent()}, -@code{allocate_event()}, @code{Fmake_marker()}, and -@code{make_uninit_string()}. The idea is that, for each type, there are -a number of frob blocks (each 2K in size); each frob block is divided up -into object-sized chunks. Each frob block will have some of these -chunks that are currently assigned to objects, and perhaps some that are -free. (If a frob block has nothing but free chunks, it is freed at the -end of the garbage collection cycle.) The free chunks are stored in a -free list, which is chained by storing a pointer in the first four bytes -of the chunk. (Except for the free chunks at the end of the last frob -block, which are handled using an index which points past the end of the -last-allocated chunk in the last frob block.) -@code{ALLOCATE_FIXED_TYPE()} first tries to retrieve a chunk from the -free list; if that fails, it calls -@code{ALLOCATE_FIXED_TYPE_FROM_BLOCK()}, which looks at the end of the -last frob block for space, and creates a new frob block if there is -none. (There are actually two versions of these macros, one of which is -more defensive but less efficient and is used for error-checking.) +@code{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). -@node lrecords -@section lrecords -@cindex lrecords +@node The header, Data dumping, Address allocation, Dumping phase +@subsection The header +@cindex dumping, the header - [see @file{lrecord.h}] +The next step creates the file and writes a header with a signature and +some random information in it. The @code{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). - All lrecords have at the beginning of their structure a @code{struct -lrecord_header}. This just contains a type number and some flags, -including the mark bit. All builtin type numbers are defined as -constants in @code{enum lrecord_type}, to allow the compiler to generate -more efficient code for @code{@var{type}P}. The type number, thru the -@code{lrecord_implementation_table}, gives access to a @code{struct -lrecord_implementation}, which is a structure containing method pointers -and such. There is one of these for each type, and it is a global, -constant, statically-declared structure that is declared in the -@code{DEFINE_LRECORD_IMPLEMENTATION()} macro. +@node Data dumping, Pointers dumping, The header, Dumping phase +@subsection Data dumping +@cindex data dumping +@cindex dumping, data - Simple lrecords (of type (b) above) just have a @code{struct -lrecord_header} at their beginning. lcrecords, however, actually have a -@code{struct lcrecord_header}. This, in turn, has a @code{struct -lrecord_header} at its beginning, so sanity is preserved; but it also -has a pointer used to chain all lcrecords together, and a special ID -field used to distinguish one lcrecord from another. (This field is used -only for debugging and could be removed, but the space gain is not -significant.) +The data is dumped in the same order as the addresses were allocated by +@code{pdump_dump_data()}, called from @code{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. - Simple lrecords are created using @code{ALLOCATE_FIXED_TYPE()}, just -like for other frob blocks. The only change is that the implementation -pointer must be initialized correctly. (The implementation structure for -an lrecord, or rather the pointer to it, is named @code{lrecord_float}, -@code{lrecord_extent}, @code{lrecord_buffer}, etc.) +@node Pointers dumping, , Data dumping, Dumping phase +@subsection Pointers dumping +@cindex pointers dumping +@cindex dumping, pointers - lcrecords are created using @code{alloc_lcrecord()}. This takes a -size to allocate and an implementation pointer. (The size needs to be -passed because some lcrecords, such as window configurations, are of -variable size.) This basically just @code{malloc()}s the storage, -initializes the @code{struct lcrecord_header}, and chains the lcrecord -onto the head of the list of all lcrecords, which is stored in the -variable @code{all_lcrecords}. The calls to @code{alloc_lcrecord()} -generally occur in the lowest-level allocation function for each lrecord -type. +A bunch of tables needed to reassign properly the global pointers are +then written. They are: -Whenever you create an lrecord, you need to call either -@code{DEFINE_LRECORD_IMPLEMENTATION()} or -@code{DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION()}. This needs to be -specified in a @file{.c} file, at the top level. What this actually -does is define and initialize the implementation structure for the -lrecord. (And possibly declares a function @code{error_check_foo()} that -implements the @code{XFOO()} macro when error-checking is enabled.) The -arguments to the macros are the actual type name (this is used to -construct the C variable name of the lrecord implementation structure -and related structures using the @samp{##} macro concatenation -operator), a string that names the type on the Lisp level (this may not -be the same as the C type name; typically, the C type name has -underscores, while the Lisp string has dashes), various method pointers, -and the name of the C structure that contains the object. The methods -are used to encapsulate type-specific information about the object, such -as how to print it or mark it for garbage collection, so that it's easy -to add new object types without having to add a specific case for each -new type in a bunch of different places. +@enumerate +@item +the pdump_root_block_ptrs dynarr +@item +the pdump_opaques dynarr +@item +a vector of all the offsets to the objects in the file that include a +description (for faster relocation at reload time) +@item +the pdump_root_objects and pdump_weak_object_chains dynarrs. +@end enumerate - The difference between @code{DEFINE_LRECORD_IMPLEMENTATION()} and -@code{DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION()} is that the former is -used for fixed-size object types and the latter is for variable-size -object types. Most object types are fixed-size; some complex -types, however (e.g. window configurations), are variable-size. -Variable-size object types have an extra method, which is called -to determine the actual size of a particular object of that type. -(Currently this is only used for keeping allocation statistics.) +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. - For the purpose of keeping allocation statistics, the allocation -engine keeps a list of all the different types that exist. Note that, -since @code{DEFINE_LRECORD_IMPLEMENTATION()} is a macro that is -specified at top-level, there is no way for it to initialize the global -data structures containing type information, like -@code{lrecord_implementations_table}. For this reason a call to -@code{INIT_LRECORD_IMPLEMENTATION} must be added to the same source file -containing @code{DEFINE_LRECORD_IMPLEMENTATION}, but instead of to the -top level, to one of the init functions, typically -@code{syms_of_@var{foo}.c}. @code{INIT_LRECORD_IMPLEMENTATION} must be -called before an object of this type is used. +The @code{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. -The type number is also used to index into an array holding the number -of objects of each type and the total memory allocated for objects of -that type. The statistics in this array are computed during the sweep -stage. These statistics are returned by the call to -@code{garbage-collect}. +Some very important information like the @code{staticpros} and +@code{lrecord_implementations_table} are handled indirectly using +@code{dump_add_opaque} or @code{dump_add_root_block_ptr}. - Note that for every type defined with a @code{DEFINE_LRECORD_*()} -macro, there needs to be a @code{DECLARE_LRECORD_IMPLEMENTATION()} -somewhere in a @file{.h} file, and this @file{.h} file needs to be -included by @file{inline.c}. +This is the end of the dumping part. - Furthermore, there should generally be a set of @code{XFOOBAR()}, -@code{FOOBARP()}, etc. macros in a @file{.h} (or occasionally @file{.c}) -file. To create one of these, copy an existing model and modify as -necessary. +@node Reloading phase, Remaining issues, Dumping phase, Dumping +@section Reloading phase +@cindex reloading phase +@cindex dumping, reloading phase - @strong{Please note:} If you define an lrecord in an external -dynamically-loaded module, you must use @code{DECLARE_EXTERNAL_LRECORD}, -@code{DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION}, and -@code{DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION} instead of the -non-EXTERNAL forms. These macros will dynamically add new type numbers -to the global enum that records them, whereas the non-EXTERNAL forms -assume that the programmer has already inserted the correct type numbers -into the enum's code at compile-time. +@subsection File loading +@cindex dumping, file loading - The various methods in the lrecord implementation structure are: +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. -@enumerate -@item -@cindex mark method -A @dfn{mark} method. This is called during the marking stage and passed -a function pointer (usually the @code{mark_object()} function), which is -used to mark an object. All Lisp objects that are contained within the -object need to be marked by applying this function to them. The mark -method should also return a Lisp object, which should be either @code{nil} or -an object to mark. (This can be used in lieu of calling -@code{mark_object()} on the object, to reduce the recursion depth, and -consequently should be the most heavily nested sub-object, such as a -long list.) +Some variables are reinitialized from the values found in the header. -@strong{Please note:} When the mark method is called, garbage collection -is in progress, and special precautions need to be taken when accessing -objects; see section (B) above. +The difference between the actual loading address and the reloc_address +is computed and will be used for all the relocations. -If your mark method does not need to do anything, it can be -@code{NULL}. -@item -A @dfn{print} method. This is called to create a printed representation -of the object, whenever @code{princ}, @code{prin1}, or the like is -called. It is passed the object, a stream to which the output is to be -directed, and an @code{escapeflag} which indicates whether the object's -printed representation should be @dfn{escaped} so that it is -readable. (This corresponds to the difference between @code{princ} and -@code{prin1}.) Basically, @dfn{escaped} means that strings will have -quotes around them and confusing characters in the strings such as -quotes, backslashes, and newlines will be backslashed; and that special -care will be taken to make symbols print in a readable fashion -(e.g. symbols that look like numbers will be backslashed). Other -readable objects should perhaps pass @code{escapeflag} on when -sub-objects are printed, so that readability is preserved when necessary -(or if not, always pass in a 1 for @code{escapeflag}). Non-readable -objects should in general ignore @code{escapeflag}, except that some use -it as an indication that more verbose output should be given. +@subsection Putting back the pdump_opaques +@cindex dumping, putting back the pdump_opaques -Sub-objects are printed using @code{print_internal()}, which takes -exactly the same arguments as are passed to the print method. +The memory contents are restored in the obvious and trivial way. -Literal C strings should be printed using @code{write_c_string()}, -or @code{write_string_1()} for non-null-terminated strings. -Functions that do not have a readable representation should check the -@code{print_readably} flag and signal an error if it is set. +@subsection Putting back the pdump_root_block_ptrs +@cindex dumping, putting back the pdump_root_block_ptrs -If you specify NULL for the print method, the -@code{default_object_printer()} will be used. +The variables pointed to by pdump_root_block_ptrs in the dump phase are +reset to the right relocated object addresses. -@item -A @dfn{finalize} method. This is called at the beginning of the sweep -stage on lcrecords that are about to be freed, and should be used to -perform any extra object cleanup. This typically involves freeing any -extra @code{malloc()}ed memory associated with the object, releasing any -operating-system and window-system resources associated with the object -(e.g. pixmaps, fonts), etc. -The finalize method can be NULL if nothing needs to be done. +@subsection Object relocation +@cindex dumping, object relocation + +All the objects are relocated using their description and their offset +by @code{pdump_reloc_one}. This step is unnecessary if the +reloc_address is equal to the file loading address. -WARNING #1: The finalize method is also called at the end of the dump -phase; this time with the for_disksave parameter set to non-zero. The -object is @emph{not} about to disappear, so you have to make sure to -@emph{not} free any extra @code{malloc()}ed memory if you're going to -need it later. (Also, signal an error if there are any operating-system -and window-system resources here, because they can't be dumped.) -Finalize methods should, as a rule, set to zero any pointers after -they've been freed, and check to make sure pointers are not zero before -freeing. Although I'm pretty sure that finalize methods are not called -twice on the same object (except for the @code{for_disksave} proviso), -we've gotten nastily burned in some cases by not doing this. +@subsection Putting back the pdump_root_objects and pdump_weak_object_chains +@cindex dumping, putting back the pdump_root_objects and pdump_weak_object_chains -WARNING #2: The finalize method is @emph{only} called for -lcrecords, @emph{not} for simply lrecords. If you need a -finalize method for simple lrecords, you have to stick -it in the @code{ADDITIONAL_FREE_foo()} macro in @file{alloc.c}. +Same as Putting back the pdump_root_block_ptrs. -WARNING #3: Things are in an @emph{extremely} bizarre state -when @code{ADDITIONAL_FREE_foo()} is called, so you have to -be incredibly careful when writing one of these functions. -See the comment in @code{gc_sweep()}. If you ever have to add -one of these, consider using an lcrecord or dealing with -the problem in a different fashion. -@item -An @dfn{equal} method. This compares the two objects for similarity, -when @code{equal} is called. It should compare the contents of the -objects in some reasonable fashion. It is passed the two objects and a -@dfn{depth} value, which is used to catch circular objects. To compare -sub-Lisp-objects, call @code{internal_equal()} and bump the depth value -by one. If this value gets too high, a @code{circular-object} error -will be signaled. +@subsection Reorganize the hash tables +@cindex dumping, reorganize the hash tables -If this is NULL, objects are @code{equal} only when they are @code{eq}, -i.e. identical. +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 @code{pdump_reorganize_hash_table}. -@item -A @dfn{hash} method. This is used to hash objects when they are to be -compared with @code{equal}. The rule here is that if two objects are -@code{equal}, they @emph{must} hash to the same value; i.e. your hash -function should use some subset of the sub-fields of the object that are -compared in the ``equal'' method. If you specify this method as -@code{NULL}, the object's pointer will be used as the hash, which will -@emph{fail} if the object has an @code{equal} method, so don't do this. +@node Remaining issues, , Reloading phase, Dumping +@section Remaining issues +@cindex dumping, remaining issues -To hash a sub-Lisp-object, call @code{internal_hash()}. Bump the -depth by one, just like in the ``equal'' method. +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. -To convert a Lisp object directly into a hash value (using -its pointer), use @code{LISP_HASH()}. This is what happens when -the hash method is NULL. +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). -To hash two or more values together into a single value, use -@code{HASH2()}, @code{HASH3()}, @code{HASH4()}, etc. +The DOC file contents should probably end up in the dump file. -@item -@dfn{getprop}, @dfn{putprop}, @dfn{remprop}, and @dfn{plist} methods. -These are used for object types that have properties. I don't feel like -documenting them here. If you create one of these objects, you have to -use different macros to define them, -i.e. @code{DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS()} or -@code{DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS()}. -@item -A @dfn{size_in_bytes} method, when the object is of variable-size. -(i.e. declared with a @code{_SEQUENCE_IMPLEMENTATION} macro.) This should -simply return the object's size in bytes, exactly as you might expect. -For an example, see the methods for window configurations and opaques. -@end enumerate +@node Future Work, Future Work Discussion, Dumping, Top +@chapter Future Work +@cindex future work -@node Low-level allocation -@section Low-level allocation -@cindex low-level allocation -@cindex allocation, low-level +@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 @code{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:: +@end menu - Memory that you want to allocate directly should be allocated using -@code{xmalloc()} rather than @code{malloc()}. This implements -error-checking on the return value, and once upon a time did some more -vital stuff (i.e. @code{BLOCK_INPUT}, which is no longer necessary). -Free using @code{xfree()}, and realloc using @code{xrealloc()}. Note -that @code{xmalloc()} will do a non-local exit if the memory can't be -allocated. (Many functions, however, do not expect this, and thus XEmacs -will likely crash if this happens. @strong{This is a bug.} If you can, -you should strive to make your function handle this OK. However, it's -difficult in the general circumstance, perhaps requiring extra -unwind-protects and such.) +@node Future Work -- General Suggestions, Future Work -- Elisp Compatibility Package, Future Work, Future Work +@section Future Work -- General Suggestions +@cindex future work, general suggestions +@cindex general suggestions, future work + +@subheading Jamie Zawinski's XEmacs Wishlist + +This document is based on Jamie Zawinski's +@uref{http://www.jwz.org/doc/xemacs-wishlist.html,xemacs wishlist}. + 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 +@uref{http://www.xemacs.org/Releases/Public-21.2/execution.html#wishlists,wishlists}. + + +@subsubheading 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. + +@subsubheading XEmacs Wishlist + +@table @strong +@item 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. + +@table @strong +@item 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: + +@example +@kbd{C-x ( } +; start macro #1 +@kbd{... } +; (do stuff) +@kbd{C-x ) } +; done with macro #1 +@kbd{... } +; (do stuff) +@kbd{C-x ( } +; start macro #2 +@kbd{C-x e } +; execute macro #1 (splice it into macro #2) +@kbd{C-s foo } +; move forward to the next spot +@kbd{C-x ) } +; done with macro #2 +@kbd{C-u 1000 C-x e } +; apply the new macro +@end example + +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 ``@kbd{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. +@item 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: +@item Make it possible to edit a keyboard macro after it has been defined. + +I only just discovered @code{edit-kbd-macro} (@kbd{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 @code{while} loops or +something.) (@kbd{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.) +@end table - Note that XEmacs provides two separate replacements for the standard -@code{malloc()} library function. These are called @dfn{old GNU malloc} -(@file{malloc.c}) and @dfn{new GNU malloc} (@file{gmalloc.c}), -respectively. New GNU malloc is better in pretty much every way than -old GNU malloc, and should be used if possible. (It used to be that on -some systems, the old one worked but the new one didn't. I think this -was due specifically to a bug in SunOS, which the new one now works -around; so I don't think the old one ever has to be used any more.) The -primary difference between both of these mallocs and the standard system -malloc is that they are much faster, at the expense of increased space. -The basic idea is that memory is allocated in fixed chunks of powers of -two. This allows for basically constant malloc time, since the various -chunks can just be kept on a number of free lists. (The standard system -malloc typically allocates arbitrary-sized chunks and has to spend some -time, sometimes a significant amount of time, walking the heap looking -for a free block to use and cleaning things up.) The new GNU malloc -improves on things by allocating large objects in chunks of 4096 bytes -rather than in ever larger powers of two, which results in ever larger -wastage. There is a slight speed loss here, but it's of doubtful -significance. +@item Save my wrists! - NOTE: Apparently there is a third-generation GNU malloc that is -significantly better than the new GNU malloc, and should probably -be included in XEmacs. +In the spirit of the `@code{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 ``@kbd{bt\n}'' and +``@kbd{ret\ny\n}'' into my @samp{*gdb*} buffer about a hundred +thousand times a day. +@item XmCreateFileSelectionBox + +The thing that ``File/Open...'' pops up has excellent @emph{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.) +@item Improve the toolbar system. + +It's great that XEmacs has a toolbar, but it's damn near impossible +to customize it. + +@table @strong +@item 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. +@item Make it easy to have customized, mode-local toolbars. + +In my @code{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 @code{c-mode-map}. Making +mode-local additions and subtractions to the toolbars should be as +easy. +@item 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... +@end table - There is also the relocating allocator, @file{ralloc.c}. This actually -moves blocks of memory around so that the @code{sbrk()} pointer shrunk -and virtual memory released back to the system. On some systems, -this is a big win. On all systems, it causes a noticeable (and -sometimes huge) speed penalty, so I turn it off by default. -@file{ralloc.c} only works with the new GNU malloc in @file{gmalloc.c}. -There are also two versions of @file{ralloc.c}, one that uses @code{mmap()} -rather than block copies to move data around. This purports to -be faster, although that depends on the amount of data that would -have had to be block copied and the system-call overhead for -@code{mmap()}. I don't know exactly how this works, except that the -relocating-allocation routines are pretty much used only for -the memory allocated for a buffer, which is the biggest consumer -of space, esp. of space that may get freed later. +@item Make the External Widget work. - Note that the GNU mallocs have some ``memory warning'' facilities. -XEmacs taps into them and issues a warning through the standard -warning system, when memory gets to 75%, 85%, and 95% full. -(On some systems, the memory warnings are not functional.) +About half of the work is done to make a replacement for the +@code{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 @code{Text} instead of @code{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 @file{ExternalClient.c} and @file{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 +@code{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. +@item Bring the debugger interface into the eighties. + +Some of you may have seen my @file{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 @samp{*gdb*} buffer and make very nearly +everything be clickable and have a context-sensitive menu. Generally, +the types that are noticed are: + +@itemize +@item function names; +@item variable and parameter names; +@item structure slots; +@item source file names; +@item type names; +@item breakpoint numbers; +@item stack frame numbers. +@end itemize - Allocated memory that is going to be used to make a Lisp object -is created using @code{allocate_lisp_storage()}. This just calls -@code{xmalloc()}. It used to verify that the pointer to the memory can -fit into a Lisp word, before the current Lisp object representation was -introduced. @code{allocate_lisp_storage()} is called by -@code{alloc_lcrecord()}, @code{ALLOCATE_FIXED_TYPE()}, and the vector -and bit-vector creation routines. These routines also call -@code{INCREMENT_CONS_COUNTER()} at the appropriate times; this keeps -statistics on how much memory is allocated, so that garbage-collection -can be invoked when the threshold is reached. +Any time one of those objects is presented in the @samp{*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. + +@table @strong +@item Make gdbsrc-mode not suck. + +The idea behind @code{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 @emph{edit} the sources which the debugger has chosen to +display! Switching into and out of @code{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{kp_enter} 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... +@item 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. +@item 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 @emph{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. +@item Make a debugger status display window. + +@itemize +@item + +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 @samp{*gdb*} buffer. +@item + +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. +@item + +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. +@end itemize -@node Cons -@section Cons -@cindex cons +The reason for all of this is that I spend entirely too much time +scrolling around in the @samp{*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 @emph{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 ``@kbd{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... +@item 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. +@item 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 @emph{after} a loop +instead of @emph{inside} it). But emacs knows, so emacs should +inform the debugger, and move the breakpoints back to the places they +were intended to be. +@end table - Conses are allocated in standard frob blocks. The only thing to -note is that conses can be explicitly freed using @code{free_cons()} -and associated functions @code{free_list()} and @code{free_alist()}. This -immediately puts the conses onto the cons free list, and decrements -the statistics on memory allocation appropriately. This is used -to good effect by some extremely commonly-used code, to avoid -generating extra objects and thereby triggering GC sooner. -However, you have to be @emph{extremely} careful when doing this. -If you mess this up, you will get BADLY BURNED, and it has happened -before. +(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...) +@item 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. +@item 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. +@item 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; ``@kbd{C-u C-SPC}'' is among my most common gestures. -@node Vector -@section Vector -@cindex vector +@enumerate +@item - As mentioned above, each vector is @code{malloc()}ed individually, and -all are threaded through the variable @code{all_vectors}. Vectors are -marked strangely during garbage collection, by kludging the size field. -Note that the @code{struct Lisp_Vector} is declared with its -@code{contents} field being a @emph{stretchy} array of one element. It -is actually @code{malloc()}ed with the right size, however, and access -to any element through the @code{contents} array works fine. +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. +@item + +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. +@item + +Markers which are in registers (@code{point-to-register}, @kbd{C-x +/}) should be displayed differently (more prominent.) +@item -@node Bit Vector -@section Bit Vector -@cindex bit vector -@cindex vector, bit +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. +@end enumerate - Bit vectors work exactly like vectors, except for more complicated -code to access an individual bit, and except for the fact that bit -vectors are lrecords while vectors are not. (The only difference here is -that there's an lrecord implementation pointer at the beginning and the -tag field in bit vector Lisp words is ``lrecord'' rather than -``vector''.) +@item Write a new garbage collector. -@node Symbol -@section Symbol -@cindex symbol +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... +@item Add support for lexical scope to the emacs-lisp runtime. - Symbols are also allocated in frob blocks. Symbols in the awful -horrible obarray structure are chained through their @code{next} field. +Yadda yadda, this list goes to eleven. +@end table -Remember that @code{intern} looks up a symbol in an obarray, creating -one if necessary. +@* +Subject: +@strong{Re: XEmacs wishlist} +Date: Wed, 14 May 1997 16:18:23 -0700 +From: Jamie Zawinski <jwz@@netscape.com> +Newsgroups: comp.emacs.xemacs, comp.emacs -@node Marker -@section Marker -@cindex marker +Andreas Schwab wrote: - Markers are allocated in frob blocks, as usual. They are kept -in a buffer unordered, but in a doubly-linked list so that they -can easily be removed. (Formerly this was a singly-linked list, -but in some cases garbage collection took an extraordinarily -long time due to the O(N^2) time required to remove lots of -markers from a buffer.) Markers are removed from a buffer in -the finalize stage, in @code{ADDITIONAL_FREE_marker()}. +@quotation +@emph{Use `C-u C-x (': } -@node String -@section String -@cindex string +@emph{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. } +@end quotation - As mentioned above, strings are a special case. A string is logically -two parts, a fixed-size object (containing the length, property list, -and a pointer to the actual data), and the actual data in the string. -The fixed-size object is a @code{struct Lisp_String} and is allocated in -frob blocks, as usual. The actual data is stored in special -@dfn{string-chars blocks}, which are 8K blocks of memory. -Currently-allocated strings are simply laid end to end in these -string-chars blocks, with a pointer back to the @code{struct Lisp_String} -stored before each string in the string-chars block. When a new string -needs to be allocated, the remaining space at the end of the last -string-chars block is used if there's enough, and a new string-chars -block is created otherwise. +Cool, I didn't know it did that... - There are never any holes in the string-chars blocks due to the string -compaction and relocation that happens at the end of garbage collection. -During the sweep stage of garbage collection, when objects are -reclaimed, the garbage collector goes through all string-chars blocks, -looking for unused strings. Each chunk of string data is preceded by a -pointer to the corresponding @code{struct Lisp_String}, which indicates -both whether the string is used and how big the string is, i.e. how to -get to the next chunk of string data. Holes are compressed by -block-copying the next string into the empty space and relocating the -pointer stored in the corresponding @code{struct Lisp_String}. -@strong{This means you have to be careful with strings in your code.} -See the section above on @code{GCPRO}ing. +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.) - Note that there is one situation not handled: a string that is too big -to fit into a string-chars block. Such strings, called @dfn{big -strings}, are all @code{malloc()}ed as their own block. (#### Although it -would make more sense for the threshold for big strings to be somewhat -lower, e.g. 1/2 or 1/4 the size of a string-chars block. It seems that -this was indeed the case formerly---indeed, the threshold was set at -1/8---but Mly forgot about this when rewriting things for 19.8.) +@subheading 21.2 Showstoppers -Note also that the string data in string-chars blocks is padded as -necessary so that proper alignment constraints on the @code{struct -Lisp_String} back pointers are maintained. +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} - Finally, strings can be resized. This happens in Mule when a -character is substituted with a different-length character, or during -modeline frobbing. (You could also export this to Lisp, but it's not -done so currently.) Resizing a string is a potentially tricky process. -If the change is small enough that the padding can absorb it, nothing -other than a simple memory move needs to be done. Keep in mind, -however, that the string can't shrink too much because the offset to the -next string in the string-chars block is computed by looking at the -length and rounding to the nearest multiple of four or eight. If the -string would shrink or expand beyond the correct padding, new string -data needs to be allocated at the end of the last string-chars block and -the data moved appropriately. This leaves some dead string data, which -is marked by putting a special marker of 0xFFFFFFFF in the @code{struct -Lisp_String} pointer before the data (there's no real @code{struct -Lisp_String} to point to and relocate), and storing the size of the dead -string data (which would normally be obtained from the now-non-existent -@code{struct Lisp_String}) at the beginning of the dead string data gap. -The string compactor recognizes this special 0xFFFFFFFF marker and -handles it correctly. +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 +API's 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. + +@node Future Work -- Elisp Compatibility Package, Future Work -- Drag-n-Drop, Future Work -- General Suggestions, Future Work +@section Future Work -- Elisp Compatibility Package +@cindex future work, elisp compatibility package +@cindex elisp compatibility package, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +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: + +@enumerate +@item -@node Compiled Function -@section Compiled Function -@cindex compiled function -@cindex function, compiled +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 @code{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 +@code{compat} code that conditionally defines just these functions when +the package is loaded. The custom @code{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). +@item - Not yet documented. +The functions in the custom @code{compat} code have their names prefixed +with both the name of the package and the word @code{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. +@item +The actual definitions of the functions in the custom @code{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). +@item -@node Dumping, Events and the Event Loop, Allocation of Objects in XEmacs Lisp, Top -@chapter Dumping -@cindex dumping +The code that wants to make use of the custom @code{compat} code is +bracketed by a call to the construct @code{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 @code{compat} +code). -@section What is dumping and its justification -@cindex dumping and its justification, what is +@end enumerate -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. +In addition, the Compat package should define the macro +@code{compat-if-fboundp}. Similar macros such as +@code{compile-when-fboundp} and @code{compile-case-fboundp} could be +defined using similar principles). The @code{compat-if-fboundp} macro +behaves just like an @code{(if (fboundp ...) ...)} clause when executed, +but in addition, when it's compiled, it ensures that the code inside the +@code{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 @code{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 @code{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 @code{compat-funcall}, which works exactly like @code{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 @code{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 @code{symbol} occurs. For example, to catch places +where a function is called using @code{funcall} or @code{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). + +@node Future Work -- Drag-n-Drop, Future Work -- Standard Interface for Enabling Extensions, Future Work -- Elisp Compatibility Package, Future Work +@section Future Work -- Drag-n-Drop +@cindex future work, drag-n-drop +@cindex drag-n-drop, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{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 +@dfn{drop site} and @dfn{drop handler}. A @dfn{drop site} specifies a +particular graphical element where an object can be dropped onto, and a +@dfn{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 @uref{lisp-interface.html,Lisp Interface Changes} +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 @code{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 @code{drop-handlers} property. + +Each drop handler has an object of type @code{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 @dfn{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 @code{add-drop-handler} +function. The drop handler itself can either be created separately +using the @code{make-drop-handler} function and then passed in as one of +the parameters to @code{add-drop-handler}, or it will be created +automatically by the @code{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 +@code{add-drop-handler} call. Other functions, such as +@code{find-drop-handler}, @code{add-drop-handler} (when specifying a +drop handler before which the drop handler in question is to be added), +@code{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 @code{MIME-type} or +@code{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 @uref{misc-user-event.html,a separate page}, the +@code{misc-user-event} event type should be removed and split up into a +number of separate event types. Two such event types would be +@code{drag-event} and @code{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 @dfn{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 @code{current-mouse-event} variable, and in fact, this +variable should not be changed at all during a drag or a drop. + +@node Future Work -- Standard Interface for Enabling Extensions, Future Work -- Better Initialization File Scheme, Future Work -- Drag-n-Drop, Future Work +@section Future Work -- Standard Interface for Enabling Extensions +@cindex future work, standard interface for enabling extensions +@cindex standard interface for enabling extensions, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{Abstract:} Apparently, if you know the name of a package (for +example, @code{fusion}), you can load it using the @code{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 +@code{enable-extension} and @code{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 traditional solution to this problem is called dumping: the build -process first creates the lisp engine under the name @file{temacs}, then -runs it until it has finished loading and initializing all the lisp -code, and eventually creates a new executable called @file{xemacs} -including both the object code in @file{temacs} and all the contents of -the memory after the initialization. +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 +@code{enable-extension} and @code{disable-extension} function. There +should also be functions such as @code{extension-enabled-p} and +@code{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 +@code{define-key-shadowing}, which is just like @code{define-key} but +which also remembers the previous key binding in a shadow list. Then +there can be another function, something like @code{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 +@code{global-set-key-shadowing} and @code{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. + +@node Future Work -- Better Initialization File Scheme, Future Work -- Keyword Parameters, Future Work -- Standard Interface for Enabling Extensions, Future Work +@section Future Work -- Better Initialization File Scheme +@cindex future work, better initialization file scheme +@cindex better initialization file scheme, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{Abstract:} A proposal is outlined for converting XEmacs to use +the @code{.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 @code{.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. -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. +@subheading Principles in the new scheme -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. +@enumerate +@item -@menu -* Overview:: -* Data descriptions:: -* Dumping phase:: -* Reloading phase:: -* Remaining issues:: -@end menu +XEmacs has a defined @dfn{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 +@code{normal-top-level}, and the general way that the user customizes +this process should also be done using Lisp code. -@node Overview -@section Overview -@cindex dumping overview +@item -The portable dumping system has to: +The pre-initialization process involves a number of properties, for +example the directory containing the user initialization files (normally +the @code{.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 @code{set-pre-init-property}, +@code{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. -@enumerate @item -At dump time, write all initialized, non-quickly-rebuildable data to a -file [Note: currently named @file{xemacs.dmp}, but the name will -change], along with all informations needed for the reloading. + +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 @code{-q} and @code{-nw}. @item -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. -@end enumerate -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. +One of the command line switches is @code{-pre-init}, whose value is a +Lisp expression to be evaluated at pre-initialization time, similar to +the @code{-eval} command line switch. This allows any +pre-initialization property to be set from the command line. -@node Data descriptions -@section Data descriptions -@cindex dumping data descriptions +@item -The more complex task of the dumper is to be able to write lisp objects -(lrecords) and C structs 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 structures in memory. +Let's define the term @dfn{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 +@dfn{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. -The specification of these descriptions is in lrecord.h. A description -of an lrecord is an array of struct lrecord_description. Each of these -structs include a type, an offset in the structure and some optional -parameters depending on the type. For instance, here is the string -description: +@item -@example -static const struct lrecord_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 @} -@}; -@end example +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: -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 @code{data}". The length of said data is -given by the expression @code{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 @code{plist} in the Lisp_String -structure". @code{XD_END} then ends the description. +@enumerate +@item -This gives us all the information we need to move around what is pointed -to by a structure (C or lrecord) and, by transitivity, everything that -it points to. The only missing information for dumping is the size of -the structure. For lrecords, this is part of the -lrecord_implementation, so we don't need to duplicate it. For C -structures we use a struct struct_description, which includes a size -field and a pointer to an associated array of lrecord_description. +If the @code{.xemacs} sub-directory exists, and it's not obviously a +package root (which probably means that it contains a file like +@code{init.el} or @code{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. +@item -@node Dumping phase -@section Dumping phase -@cindex dumping phase +If the init file directory is the user's home directory, then the init +file is called @code{.emacs}. Otherwise, it's called @code{init.el}. +@item -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. +If the init file directory is the user's home directory, then the +pre-init file is called @code{.xemacs-pre-init.el}. Otherwise it's +called @code{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.) +@item -@menu -* Object inventory:: -* Address allocation:: -* The header:: -* Data dumping:: -* Pointers dumping:: -@end menu +If the init file directory is the user's home directory, then the custom +init file is called @code{.xemacs-custom-init.el}. Otherwise, it's +called @code{custom-init.el}. -@node Object inventory -@subsection Object inventory -@cindex dumping object inventory +@end enumerate -The first task is to build the list of the objects to dump. This -includes: +@item -@itemize @bullet -@item lisp objects -@item C structures -@end itemize +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 @strong{Yes}, @strong{No}, and @strong{No, +and don't ask this again}. If this last response is chosen, then the +file @code{.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 +@strong{Yes} option is chosen, then any package root files in +@code{.xemacs} are moved into @code{.xemacs/packages}, the file +@code{.emacs} is moved into @code{.xemacs/init.el} and @code{.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. -We end up with one @code{pdump_entry_list_elmt} 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. +@end enumerate -These entries are linked together in @code{pdump_entry_list} structures -and can be enumerated thru either: +@subheading The custom init file + +The @dfn{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. + +@subheading 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 @code{-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. + +@node Future Work -- Keyword Parameters, Future Work -- Property Interface Changes, Future Work -- Better Initialization File Scheme, Future Work +@section Future Work -- Keyword Parameters +@cindex future work, keyword parameters +@cindex keyword parameters, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +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 API's 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 @code{&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 @dfn{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 @code{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 @code{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: @enumerate @item -the @code{pdump_object_table}, an array of @code{pdump_entry_list}, one -per lrecord type, indexed by type number. +The subr object type needs to be modified to contain additional slots +for the number and names of any keyword parameters. @item -the @code{pdump_opaque_data_list}, used for the opaque data which does -not include pointers, and hence does not need descriptions. -@item -the @code{pdump_struct_table}, which is a vector of -@code{struct_description}/@code{pdump_entry_list} pairs, used for -non-opaque C structures. +The implementation of the @code{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 +@code{cl} code. +@item + +A new macro, similar to the @code{DEFUN} macro, and probably called +@code{DEFUN_WITH_KEYWORDS}, needs to be defined so that built-in Lisp +primitives containing keywords can be created. Now, the +@code{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 @code{&key} +specifier. This string is parsed in the @code{DEFSUBR} macro during +XEmacs initialization, and is converted into the appropriate structure +that needs to be stored into the subr object. In addition, the +@var{max_args} parameter of the @code{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 +@code{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 @code{DEFUN_WITH_KEYWORDS} macro +that specifies the number of keyword parameters. However, this would +require some additional complexity in the preprocessor definition of the +@code{DEFUN_WITH_KEYWORDS} macro, and probably isn't worth +implementing). +@item + +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. +@item + +The @code{make-docfile} program would have to be modified so that it +generates the correct parameter lists for primitives defined using the +@code{DEFUN_WITH_KEYWORDS} macro. +@item + +Possibly other aspects of the help system that deal with function +descriptions might have to be modified. +@item + +A helper function might need to be defined to make it easier for +primitives that use both the @code{&rest} and @code{&key} +specifiers to parse their argument lists. + @end enumerate -This uses a marking strategy similar to the garbage collector. Some -differences though: +@subheading Internal API for C primitives with keywords - necessary for many of the new Mule APIs being defined. + +@example + 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 +@end example + +@node Future Work -- Property Interface Changes, Future Work -- Toolbars, Future Work -- Keyword Parameters, Future Work +@section Future Work -- Property Interface Changes +@cindex future work, property interface changes +@cindex property interface changes, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +In my past work on XEmacs, I already expanded the standard property +functions of @code{get}, @code{put}, and @code{remprop} to work on +objects other than symbols and defined an additional function +@code{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: @enumerate @item -We do not use the mark bit (which does not exist for C structures -anyway); we use a big hash table instead. -@item -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 C structures and opaque data in addition to -Lisp_Object members. +A new concept associated with each property called a @dfn{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 @code{get} when it is +@dfn{unbound}, which is to say that its value has not been explicitly +specified. Note: the way to make a property unbound is to call +@code{remprop}. Note also that for some built-in properties, setting +the property to its default value is equivalent to making it unbound. +@item + +The behavior of the @code{get} function is modified. If the @code{get} +function is called on a property that is unbound and the third, optional +@var{default} argument is @code{nil}, then the default value of the +property is returned. If the @var{default} argument is not @code{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 @code{get} because all user-defined properties have an +initial default value of @code{nil}. Code that calls the @code{get} +function and specifies @code{nil} for the @var{default} argument, and +expects to get @code{nil} returned if the property is unbound, is almost +certainly wrong anyway. +@item + +A new function, @code{get1} is defined. This function does not take a +default argument like the @code{get} function. Instead, if the property +is unbound, an error is signaled. Note: @code{get} can be implemented +in terms of @code{get1}. +@item + +New functions @code{property-default-value} and @code{property-bound-p} +are defined with the obvious semantics. +@item + +An additional function @code{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. +@item + +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 @code{put} function should signal an error, such as +@code{undefined-property}, when given any property other than those that +are predefined. +@item + +A function called @code{user-defined-properties-allowed-p} should be +defined with the obvious semantics. (See the previous item.) +@item + +Three more functions should be defined, called +@code{built-in-property-name-list}, @code{property-name-list}, and +@code{user-defined-property-name-list}. + @end enumerate -This is done by @code{pdump_register_object()}, which handles Lisp_Object -variables, and @code{pdump_register_struct()} which handles C structures, -which both delegate the description management to @code{pdump_register_sub()}. - -The hash table doubles as a map object to pdump_entry_list_elmt (i.e. -allows us to look up a pdump_entry_list_elmt with the object it points -to). Entries are added with @code{pdump_add_entry()} and looked up with -@code{pdump_get_entry()}. There is no need for entry removal. The hash -value is computed quite simply from the object pointer by -@code{pdump_make_hash()}. +Another idea: -The roots for the marking are: +@example +(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))) +@end example + +@node Future Work -- Toolbars, Future Work -- Menu API Changes, Future Work -- Property Interface Changes, Future Work +@section Future Work -- Toolbars +@cindex future work, toolbars +@cindex toolbars + +@menu +* Future Work -- Easier Toolbar Customization:: +* Future Work -- Toolbar Interface Changes:: +@end menu + +@node Future Work -- Easier Toolbar Customization, Future Work -- Toolbar Interface Changes, Future Work -- Toolbars, Future Work -- Toolbars +@subsection Future Work -- Easier Toolbar Customization +@cindex future work, easier toolbar customization +@cindex easier toolbar customization, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{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 @code{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 +@strong{Execute} item which simply does what would happen if you +left-click on a toolbar button. There should probably be a +@strong{Delete} item to get rid of the toolbar button and a +@strong{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 @strong{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 @code{edit-toolbar.el}. The second item is +called @strong{Align}, which contains a submenu that says @strong{Top}, +@strong{Bottom}, @strong{Left}, and @strong{Right}, which will be just +like setting the default toolbar position. The third one says +@strong{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. @code{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 @code{.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.....) + +@node Future Work -- Toolbar Interface Changes, , Future Work -- Easier Toolbar Customization, Future Work -- Toolbars +@subsection Future Work -- Toolbar Interface Changes +@cindex future work, toolbar interface changes +@cindex toolbar interface changes, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +I propose changing the way that toolbars are specified to make them more +flexible. @enumerate @item -the @code{staticpro}'ed variables (there is a special @code{staticpro_nodump()} -call for protected variables we do not want to dump). -@item -the variables registered via @code{dump_add_root_object} -(@code{staticpro()} is equivalent to @code{staticpro_nodump()} + -@code{dump_add_root_object()}). +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: +@code{:help-echo}, @code{:context-menu}, @code{:drop-handlers}, and +@code{:enabled-p}. The @code{:enabled-p} and @code{:help-echo} keyword +arguments are the same as the third and fourth items in the old toolbar +item vector format. The @code{: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 @code{:drop-handlers} keyword is for use by the new +drag-n-drop interface (see @uref{drag-n-drop.html,Drag-n-Drop Interface +Changes} ), and is not normally specified or modified directly. +@item + + +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 +@code{:captioned-p} (whether the captions are visible under the +toolbar), @code{:glyphs-visible-p} (whether the toolbar glyphs are +visible), and @code{: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 +@code{left-toolbar-width}, @code{right-toolbar-width}, +@code{left-toolbar-visible-p}, @code{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. +@item + + +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 -- @dfn{toolbar paths} and +@dfn{toolbar item paths}. Each kind of path is an object (of type +@code{toolbar-path} and @code{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 @code{make-toolbar-path} function, which takes a +toolbar specifier (or optionally, a symbol, such as @code{left}, +@code{right}, @code{default}, or @code{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 @code{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 @code{get} or +@code{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 +@code{add-toolbar-item}, @code{delete-toolbar-item}, and +@code{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 @uref{drag-n-drop.html,Drag-n-Drop Interface +Changes} 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). +@item + + +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). +@item + + +The default context menu for toolbars (which should be specified using a +specifier called @code{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 @code{edit-faces} or @code{custom} +interface), etc. + +@end enumerate +@node Future Work -- Menu API Changes, Future Work -- Removal of Misc-User Event Type, Future Work -- Toolbars, Future Work +@section Future Work -- Menu API Changes +@cindex future work, menu API changes +@cindex menu API changes, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@enumerate @item -the variables registered via @code{dump_add_root_struct_ptr}, each of -which points to a C structure. + +I propose making a specifier for the menubar associated with the frame. +The specifier should be called @code{default-menubar} and should replace +the existing @code{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 @uref{symbol-value-handlers.html,complete the symbol value +handler mechanism}) +@item + + +I propose an API for modifying menu instantiators similar to the API +composed above for toolbar instantiators. A new object called a +@dfn{menu path} (of type @code{menu-path}) can be created using the +@code{make-menu-path} function, and specifies a location in a particular +menu instantiator where changes can be made. The first argument to +@code{make-menu-path} specifies which menu to modify and can be a +specifier, a value such as @code{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 +@code{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 +@code{get}, @code{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 +@code{find-menu-item}, @code{delete-menu-item}, @code{add-menu-button}, +etc. (It is really a shame that @code{add-menu-item} is an obsolete +function because it is a much better name than @code{add-menu-button}). +Finally, the menu path object can be passed to the drop-handler +functions described in @uref{drag-n-drop.html,Drag-n-Drop Interface +Changes} to access or modify the drop handlers that are associated with +a particular menu item. +@item + + +New keyword properties should be added to the menu item vector. These +include @code{:help-echo}, @code{:context-menu} and +@code{: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. + @end enumerate -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. +@node Future Work -- Removal of Misc-User Event Type, Future Work -- Mouse Pointer, Future Work -- Menu API Changes, Future Work +@section Future Work -- Removal of Misc-User Event Type +@cindex future work, removal of misc-user event type +@cindex removal of misc-user event type, future work -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. +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} -@node Address allocation -@subsection Address allocation -@cindex dumping address allocation +@strong{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 @code{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. + +@node Future Work -- Mouse Pointer, Future Work -- Extents, Future Work -- Removal of Misc-User Event Type, Future Work +@section Future Work -- Mouse Pointer +@cindex future work, mouse pointer +@cindex mouse pointer, future work -The next step is to allocate the offsets of each of the objects in the -final dump file. This is done by @code{pdump_allocate_offset()} which -is called indirectly by @code{pdump_scan_by_alignment()}. +@menu +* Future Work -- Abstracted Mouse Pointer Interface:: +* Future Work -- Busy Pointer:: +@end menu -The strategy to deal with alignment problems uses these facts: +@node Future Work -- Abstracted Mouse Pointer Interface, Future Work -- Busy Pointer, Future Work -- Mouse Pointer, Future Work -- Mouse Pointer +@subsection Future Work -- Abstracted Mouse Pointer Interface +@cindex future work, abstracted mouse pointer interface +@cindex abstracted mouse pointer interface, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{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 @code{pointer}, which +has one tag associated with it, named @code{: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 +@code{cursor-font} to @code{x-cursor-font}, because it only works under +X Windows. We also need to change the format called @code{resource} to +be @code{mswindows-resource}. At least in the case of +@code{cursor-font}, the old value should be maintained for compatibility +as an obsolete alias. The @code{resource} format was added so recently +that it's possible that we can just change it. + +@node Future Work -- Busy Pointer, , Future Work -- Abstracted Mouse Pointer Interface, Future Work -- Mouse Pointer +@subsection Future Work -- Busy Pointer +@cindex future work, busy pointer +@cindex busy pointer, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +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 @dfn{busy time} as the time since the last time that XEmacs was +ready to receive input from the user. An implementation might be: @enumerate @item -real world alignment requirements are powers of two. +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. +@item +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 @strong{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). +@end enumerate + +@node Future Work -- Extents, Future Work -- Version Number and Development Tree Organization, Future Work -- Mouse Pointer, Future Work +@section Future Work -- Extents +@cindex future work, extents +@cindex extents, future work + +@menu +* Future Work -- Everything should obey duplicable extents:: +@end menu + +@node Future Work -- Everything should obey duplicable extents, , Future Work -- Extents, Future Work -- Extents +@subsection Future Work -- Everything should obey duplicable extents +@cindex future work, everything should obey duplicable extents +@cindex everything should obey duplicable extents, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +A lot of functions don't properly track duplicable extents. For +example, the @code{concat} function does, but the @code{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 @code{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 @code{lisp_string_struct} to generate a Lisp string from a +@code{lisp_string_struct} and vice-versa to append a sub-string of a +Lisp string to a @code{lisp_string_struct}, to just append characters to +a @code{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 @code{lisp_string_struct}. However, there is +already a function @code{copy_string_extents()} that does basically this +exact thing, and it should be easy to create a modified version of this +function. + +@node Future Work -- Version Number and Development Tree Organization, Future Work -- Improvements to the @code{xemacs.org} Website, Future Work -- Extents, Future Work +@section Future Work -- Version Number and Development Tree Organization +@cindex future work, version number and development tree organization +@cindex version number and development tree organization, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{Abstract:} The purpose of this proposal is to present a coherent +plan for how development branches in XEmacs are managed. This will +cover such issues as stable versus experimental branches, creating new +branches, synchronizing patches between branches, and how version +numbers are assigned to branches. + +A development branch is defined to be a linear series of releases of the +XEmacs code base, each of which is derived from the previous one. When +the XEmacs development tree is forked and two branches are created where +there used to be one, the branch that is intended to be more stable and +have fewer changes made to it is considered the one that inherits the +parent branch, and the other branch is considered to have begun at the +branching point. The less stable of the two branches will eventually be +forked again, while this will not happen usually to the more stable of +the two branches, and its development will eventually come to an end. +This means that every branch has a definite ending point. For example, +the 20.x branch began at the point when the released +19.13 code tree was split into a 19.x and a 20.x branch, and a 20.x +branch will end when the last 20.x release (probably numbered 20.5 or +20.6) is released. + +I think that there should always be three active development branches at +any time. These branches can be designated the stable, the semi-stable, +and the experimental branches. This situation has existed in the +current code tree as soon as the 21.0 development branch was split. In +this situation, the stable branch is the 20.x series. The semi-stable +branch is the 21.0 release and the stability releases that follow. The +experimental branch is the branch that was created as the result of the +21.0 development branch split. Typically, the stable branch has been +released for a long period of time. The semi-stable branch has been +released for a short period of time, or is about to be released, and the +experimental branch has not yet been released, and will probably not be +released for awhile. The conditions that should hold in all +circumstances are: +@enumerate @item -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. +There should be three active branches. @item -the non-variant part of variable size lrecords has an alignment -requirement of 4. -@end enumerate -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. @code{pdump_scan_by_alignment()} then scans all the -@code{pdump_entry_list_elmt}'s, the ones with the highest requirements -first. This ensures the best packing. +The experimental branch should never be in feature freeze. -The maximum alignment requirement we take into account is 2^8. +@end enumerate -@code{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). +The reason for the second condition is to ensure that active development +can always proceed and is never throttled, as is happening currently at +the end of the 21.0 release cycle. What this means is that as soon as +the experimental branch is deemed to be stable enough to go into feature +freeze: -@node The header -@subsection The header -@cindex dumping, the header +@enumerate +@item -The next step creates the file and writes a header with a signature and -some random information in it. The @code{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). +The current stable branch is made inactive and all further development +on it ceases. +@item -@node Data dumping -@subsection Data dumping -@cindex data dumping -@cindex dumping, data +The semi-stable branch, which by now should have been released for a +fair amount of time, and should be fairly stable, gets renamed to the +stable branch. +@item -The data is dumped in the same order as the addresses were allocated by -@code{pdump_dump_data()}, called from @code{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. +The experimental branch is forked into two branches, one of which +becomes the semi-stable branch, and the other, the experimental branch. -@node Pointers dumping -@subsection Pointers dumping -@cindex pointers dumping -@cindex dumping, pointers +@end enumerate -A bunch of tables needed to reassign properly the global pointers are -then written. They are: +The stable branch is always in high resistance, which is to say that the +only changes that can be made to the code are important bug fixes +involving a small amount of code where it should be clear just by +reading the code that no destabilizing code has been introduced. The +semi-stable branch is in low resistance, which means that no major +features can be added, but except right before a release fairly major +code changes are allowed. Features can be added if they are +sufficiently small, if they are deemed sufficiently critical due to +severe problems that would exist if the features were not added (for +example, replacement of the unexec mechanism with a portable solution +would be a feature that could be added to the semi-stable branch +provided that it did not involve an overly radical code re-architecture, +because otherwise it might be impossible to build XEmacs on some +architectures or with some compilers), or if the primary purpose of the +new feature is to remedy an incompleteness in a recent architectural +change that was not finished in a prior release due to lack of time (for +example, abstracting the mouse pointer and list-of-colors interfaces, +which were left out of 21.0). There is no feature resistance in place +in the experimental branch, which allows full development to proceed at +all times. + +In general, both the stable and semi-stable branches will contain +previous net releases. In addition, there will be beta releases in all +three branches, and possibly development snapshots between the beta +releases. It's obviously necessary to have a good version numbering +scheme in order to keep everything straight. + +First of all, it needs to be immediately clear from the version number +whether the release is a beta release or a net release. Steve has +proposed getting rid of the beta version numbering system, which I think +would be a big mistake. Furthermore, the net release version number and +beta release version number should be kept separate, just as they are +now, to make it completely clear where any particular release stands. +There may be alternate ways of phrasing a beta release other than +something like 21.0 beta 34, but in all such systems, the beta number +needs to be zero for any release version. Three possible alternative +systems, none of which I like very much, are: @enumerate @item -the pdump_root_struct_ptrs dynarr -@item -the pdump_opaques dynarr -@item -a vector of all the offsets to the objects in the file that include a -description (for faster relocation at reload time) + +The beta number is simply an extra number in the regular version number. +Then, for example, 21.0 beta 34 becomes 21.0.34. The problem is that +the release version, which would simply be called 21.0, appears to be +earlier than 21.0 beta 34. +@item + +The beta releases appear as later revisions of earlier releases. Then, +for example, 21.1 beta 34 becomes 21.0.34, and 21.0 beta 34 would have +to become 21.-1.34. This has both the obvious ugliness of negative +version numbers and the problem that it makes beta releases appear to be +associated with their previous releases, when in fact they are more +closely associated with the following release. +@item + +Simply make the beta version number be negative. In this scheme, you'd +start with something like -1000 as the first beta, and then 21.0 beta 34 +would get renumbered to 21.0.-968. Obviously, this is a crazy and +convoluted scheme as well, and we would be best to avoid it. + +@end enumerate + +Currently, the between-beta snapshots are not numbered, but I think that +they probably should be. If appropriate scripts are handled to automate +beta release, it should be very easy to have a version number +automatically updated whenever a snapshot is made. The number could be +added either as a separate snapshot number, and you'd have 21.0 beta 34 +pre 1, which becomes before 21.0 beta 34; or we could make the beta +number be floating point, and then the same snapshot would have to be +called 21.0 beta 33.1. The latter solution seems quite kludgey to me. + +There also needs to be a clear way to distinguish, when a net release is +made, which branch the release is a part of. Again, three solutions +come to mind: + +@enumerate @item -the pdump_root_objects and pdump_weak_object_chains dynarrs. + +The major version number reflects which development branch the release +is in and the minor version number indicates how many releases have been +made along this branch. In this scheme, 21.0 is always the first +release of the 21 series development branch, and when this branch is +split, the child branch that becomes the experimental branch gets +version numbers starting with 22. This scheme is the simplest, and it's +the one I like best. +@item + +We move to a three-part version number. In this scheme, the first two +numbers indicate the branch, and the third number indicates the release +along the branch. In this scheme, we have numbers like 21.0.1, which +would be the second release in the 21.0 series branch, and 21.1.2, which +would be the third release in the +21.1 series branch. The major version number then gets increased +only very occasionally, and only when a sufficiently major architectural +change has been made, particularly one that causes compatibility +problems with code written for previous branches. I think schemes like +this are unnecessary in most circumstances, because usually either the +major version number ends up changing so often that the second number is +always either zero or one, or the major version number never changes, +and as such becomes useless. By the time the major version number would +change, the product itself has changed so much that it often gets +renamed. Furthermore, it is clear that the two version number scheme +has been used throughout most of the history of Emacs, and recently we +have been following the two number scheme also. If we introduced a +third revision number, at this point it would both confuse existing code +that assumed there were two numbers, and would look rather silly given +that the major version number is so high and would probably remain at +the same place for quite a long time. +@item + +A third scheme that would attempt to cross the two schemes would keep +the same concept of major version number as for the three number scheme, +and would compress the second and third numbers of the three number +scheme into one number by using increments of ten. For example, the +current 21.x branch would have releases No. 21.0, 21.1, etc. The next +branch would be No. 21.10, 21.11, etc. I don't like this scheme very +much because it seems rather kludgey, and also because it is not used in +any other product as far as I know. +@item + +Another scheme that would combine the second and third numbers in the +three number scheme would be to have the releases in the current 21.x +series be numbered 21.0, then 21.01, then 22.02, etc. The next series +is 21.1, then 21.11, then 21.12, etc. This is similar to the way that +version numbers are done for DOS in Windows. I also think that this +scheme is fairly silly because, like the previous scheme, its only +purpose is to avoid increasing the major version number very much. But +given that we have already have a fairly large major version number, +there doesn't seem to be any particular problem with increasing this +number by one every year or two. Some people will object that by doing +this, it becomes impossible to tell when a change is so major that it +causes a lot of code breakage, but past releases have not been accurate +indicators of this. For example, +19.12 caused a lot of code breakage, but 20.0 caused less, and 21.0 +caused less still. In the GNU Emacs world, there were byte code changes +made between 19.28 and 19.29, but as far as I know, not between 19.29 +and 20.0. + @end enumerate -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. +With three active development branches, synchronizing code changes +between the branches is obviously somewhat of a problem. To make things +easier, I propose a few general guidelines: -The @code{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. +@enumerate +@item -Some very important information like the @code{staticpros} and -@code{lrecord_implementations_table} are handled indirectly using -@code{dump_add_opaque} or @code{dump_add_root_struct_ptr}. +Merging between different branches need not happen that often. It +should not happen more often than necessary to avoid undue burden on the +maintainer, but needs to be done at all defined checkpoints. These +checkpoints need to be noted in all of the places that track changes +along the branch, for example, in all of the change logs and in all of +the CVS tags. +@item + +Every code change that can be considered a self-contained unit, no +matter how large or small, needs to have a change log entry, preferably +a single change log entry associated with it. This is an absolute +requirement. There should be no code changes without an associated +change log entry. Otherwise, it is highly likely that patches will not +be correctly synchronized across all versions, and will get lost. There +is no need for change log entries to contain unnecessary detail though, +and it is important that there be no more change log entries than +necessary, which means that two or more change log entries associated +with a single patch need to be grouped together if possible. This might +imply that there should be one global change log instead of change logs +in each directory, or at the very least, the number of separate change +logs should be kept to a minimum. +@item + +The patch that is associated with each change log entry needs to be kept +around somewhere. The reason for this is that when synchronizing code +from some branch to some earlier branch, it is necessary to go through +each change log entry and decide whether a change is worthy to make it +into a more stable branch. If so, the patch associated with this change +needs to be individually applied to the earlier branch. +@item + +All changes made in more stable branches get merged into less stable +branches unless the change really is completely unnecessary in the less +stable branch because it is superseded by some other change. This will +probably mean more developers making changes to the semi-stable branch +than to the experimental branch. This means that developers should +strive to do their development in the most stable branch that they +expect their code to go into. An alternative to this which is perhaps +more workable is simply to insist that all developers make all patches +based off of the experimental branch, and then later merge these patches +down to the more stable branches as necessary. This means, however, +that submitted patches should never be combinations of two or more +unrelated changes. Whenever such patches are submitted, they should +either be rejected (which should apply to anybody who should know +better, which probably means everybody on the beta list and anybody else +who is a regular contributor), or the maintainer or some other +designated party needs to filter the combined patch into separate +patches, one per logical change. +@item + +The maintainer should keep all the patches around in some data base, and +the patches should be given an identifier consisting of the author of +the patch, the date the patch was submitted, and some other identifying +characteristic, such as a number, in case there is more than one patch +on the same date by the same author. The database should hopefully be +correctly marked at all times with something indicating which branches +the patch has been applied to, and this database should hopefully be +publicly visible so that patch authors can determine whether their +patches have been applied, and whether their patches have been received, +so that patches do not get needlessly resubmitted. +@item + +Global automatable changes such as textual renaming, reordering, and +additions or deletions of parameters in function calls should still be +allowed, even with multiple development branches. (Sometimes these are +necessary for code cleanliness, and in the long run, they save a lot of +time, even through they may cause some headaches in the short-term.) In +general, when such changes are made, they should occur in a separate +beta version that contains only such changes and no other patches, and +the changes should be made in both the semi-stable and experimental +branches at the same time. The description of the beta version should +make it very clear that the beta is comprised of such changes. The +reason for doing these things is to make it easier for people to diff +between beta versions in order to figure out the changes that were made +without the diff getting cluttered up by these code cleanliness changes +that don't change any actual behavior. -This is the end of the dumping part. +@end enumerate -@node Reloading phase -@section Reloading phase -@cindex reloading phase -@cindex dumping, reloading phase +@node Future Work -- Improvements to the @code{xemacs.org} Website, Future Work -- Keybindings, Future Work -- Version Number and Development Tree Organization, Future Work +@section Future Work -- Improvements to the @code{xemacs.org} Website +@cindex future work, improvements to the @code{xemacs.org} website +@cindex improvements to the @code{xemacs.org} website, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +The @code{xemacs.org} web site is the face that XEmacs presents to the +outside world. In my opinion, its most important function is to present +information about XEmacs in such a way that solicits new XEmacs users +and co-contributors. Existing members of the XEmacs community can +probably find out most of the information they want to know about XEmacs +regardless of what shape the web site is in, or for that matter, perhaps +even if the web site doesn't exist at all. However, potential new users +and co-contributors who go to the XEmacs web site and find it out of +date and/or lacking the information that they need are likely to be +turned away and may never return. For this reason, I think it's +extremely important that the web site be up-to-date, well-organized, and +full of information that an inquisitive visitor is likely to want to +know. + +The current XEmacs web site needs a lot of work if it is to meet these +standards. I don't think it's reasonable to expect one person to do all +of this work and make continual updates as needed, especially given the +dismal record that the XEmacs web site has had. The proper thing to do +is to place the web site itself under CVS and allow many of the core +members to remotely check files in and out. This way, for example, +Steve could update the part of the site that contains the current +release status of XEmacs. (Much of this could be done by a script that +Steve executes when he sends out a beta release announcement which +automatically HTML-izes the mail message and puts it in the appropriate +place on the web site. There are programs that are specifically +designed to convert email messages into HTML, for example +@code{mhonarc}.) Meanwhile, the @code{xemacs.org} mailing list +administrator (currently Jason Mastaler, I think) could maintain the +part of the site that describes the various mailing lists and other +addresses at @code{xemacs.org}. Someone like me (perhaps through a +proxy typist) could maintain the part of the site that specifies the +future directions that XEmacs is going in, etc., etc. -@subsection File loading -@cindex dumping, file loading +Here are some things that I think it's very important to add to the web +site. -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. +@enumerate +@item -Some variables are reinitialized from the values found in the header. +A page describing in detail how to get involved in the XEmacs +development process, how to submit and where to submit various patches +to the XEmacs core or associated packages, how to contact the +maintainers and core developers of XEmacs and the maintainers of various +packages, etc. +@item + +A page describing exactly how to download, compile, and install XEmacs, +and how to download and install the various binary distributions. This +page should particularly cover in detail how exactly the package system +works from an installation standpoint and how to correctly compile and +install under Microsoft Windows and Cygwin. This latter section should +cover what compilers are needed under Microsoft Windows and Cygwin, and +how to get and install the Cygwin components that are needed. +@item + +A page describing where to get the various ancillary libraries that can +be linked with XEmacs, such as the JPEG, TIFF, PNG, X-Face, DBM, and +other libraries. This page should also cover how to correctly compile +it and install these libraries, including under Microsoft Windows (or at +least it should contain pointers to where this information can be +found). Also, it should describe anything that needs to be specified as +an option to @code{configure} in order for XEmacs to link with and make +use of these libraries or of Motif or CDE. Finally, this page should +list which versions of the various libraries are required for use with +the various different beta versions of XEmacs. (Remember, this can +change from beta to beta, and someone needs to keep a watchful eye on +this). +@item + +Pointers to any other sites containing information on XEmacs. This +would include, for example, Hrvoje's XEmacs on Windows FAQ and my +Architecting XEmacs web site. (Presumably, most of the information in +this section will be temporary. Eventually, these pages should be +integrated into the main XEmacs web site). +@item + +A page listing the various sub-projects in the XEmacs development +process and who is responsible for each of these sub-projects, for +example development of the package system, administration of the mailing +lists, maintenance of stable XEmacs versions, maintenance of the CVS web +interface, etc. This page should also list all of the packages that are +archived at @code{xemacs.org} and who is the maintainer or maintainers +for each of these packages. + +@end enumerate -The difference between the actual loading address and the reloc_address -is computed and will be used for all the relocations. +@subheading Other Places with an XEmacs Presence +We should try to keep an XEmacs presence in all of the major places on +the web that are devoted to free software or to the "open source" +community. This includes, for example, the open source web site at +@uref{../../opensource.oreilly.com/default.htm,http://opensource.oreilly.com} +(I'm already in the process of contacting this site), the Freshmeat site +at @uref{../../www.freshmeat.net/default.htm,http://www.freshmeat.net}, +the various announcement news groups (for example, +@uref{news:comp.os.linux.announce,comp.os.linux.announce}, and the +Windows announcement news group) etc. + +@node Future Work -- Keybindings, Future Work -- Byte Code Snippets, Future Work -- Improvements to the @code{xemacs.org} Website, Future Work +@section Future Work -- Keybindings +@cindex future work, keybindings +@cindex keybindings, future work -@subsection Putting back the pdump_opaques -@cindex dumping, putting back the pdump_opaques +@menu +* Future Work -- Keybinding Schemes:: +* Future Work -- Better Support for Windows Style Key Bindings:: +* Future Work -- Misc Key Binding Ideas:: +@end menu -The memory contents are restored in the obvious and trivial way. +@node Future Work -- Keybinding Schemes, Future Work -- Better Support for Windows Style Key Bindings, Future Work -- Keybindings, Future Work -- Keybindings +@subsection Future Work -- Keybinding Schemes +@cindex future work, keybinding schemes +@cindex keybinding schemes, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{Abstract:} We need a standard mechanism that allows a different +global key binding schemes to be defined. Ideally, this would be the +@uref{keyboard-actions.html,keyboard action interface} that I have +proposed, however this would require a lot of work on the part of mode +maintainers and other external Elisp packages and will not be rady in +the short term. So I propose a very kludgy interface, along the lines +of what is done in Viper currently. Perhaps we can rip that key munging +code out of Viper and make a separate extension that implements a global +key binding scheme munging feature. This way a key binding scheme could +rearrange all the default keys and have all sorts of other code, which +depends on the standard keys being in their default location, still +work. + +@node Future Work -- Better Support for Windows Style Key Bindings, Future Work -- Misc Key Binding Ideas, Future Work -- Keybinding Schemes, Future Work -- Keybindings +@subsection Future Work -- Better Support for Windows Style Key Bindings +@cindex future work, better support for windows style key bindings +@cindex better support for windows style key bindings, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{Abstract:} This page describes how we could create an XEmacs +extension that modifies the global key bindings so that a Windows user +would feel at home when using the keyboard in XEmacs. Some of these +bindings don't conflict with standard XEmacs keybindings and should be +added by default, or at the very least under Windows, and probably under +X Windows as well. Other key bindings would need to be implemented in a +Windows compatibility extension which can be enabled and disabled on the +fly, following the conventions outlined in +@uref{enabling-extensions.html,Standard interface for enabling +extensions} Ideally, this should be implemented using the +@uref{keyboard-actions.html,keyboard action interface} but these wil not +be available in the short term, so we will have to resort to some awful +kludges, following the model of Michael Kifer's Viper mode. + +We really need to make XEmacs provide standard Windows key bindings as +much as possible. Currently, for example, there are at least two +packages that allow the user to make a selection using the shifted arrow +keys, and neither package works all that well, or is maintained. There +should be one well-written piece of code that does this, and it should +be a standard part of XEmacs. In fact, it should be turned on by +default under Windows, and probably under X as well. (As an aside here, +one point of contention in how to implement this involves what happens +if you select a region using the shifted arrow keys and then hit the +regular arrow keys. Does the region remain selected or not? I think +there should be a variable that controls which of these two behaviors +you want. We can argue over what the default value of this variable +should be. The standard Windows behavior here is to keep the region +selected, but move the insertion point elsewhere, which is unfortunately +impossible to implement in XEmacs.) + +Some thought should be given to what to do about the standard Windows +control and alt key bindings. Under NTEmacs, there is a variable that +controls whether the alt key behaves like the Emacs meta key, or whether +it is passed on to the menu as in standard Windows programs. We should +surely implement this and put this option on the @strong{Options} menu. +Making @kbd{Alt-f} for example, invoke the @strong{File} menu, is not +all that disruptive in XEmacs, because the user can always type @kbd{ESC +f} to get the meta key functionality. Making @kbd{Control-x}, for +example, do @strong{Cut}, is much, much more problematic, of course, but +we should consider how to implement this anyway. One possibility would +be to move all of the current Emacs control key bindings onto +control-shift plus a key, and to make the simple control keys follow the +Windows standard as much as possible. This would mean, for example, +that we would have the following keybindings:@* @kbd{Control-x} ==> +@strong{Cut} @* @kbd{Control-c} ==> @strong{Copy} @* @kbd{Control-v} ==> +@strong{Paste} @* @kbd{Control-z} ==> @strong{Undo}@* @kbd{Control-f} +==> @strong{Find} @* @kbd{Control-a} ==> @strong{Select All}@* +@kbd{Control-s} ==> @strong{Save}@* @kbd{Control-p} ==> @strong{Print}@* +@kbd{Control-y} ==> @strong{Redo}@* (this functionality @emph{is} +available in XEmacs with Kyle Jones' @code{redo.el} package, but it +should be better integrated)@* @kbd{Control-n} ==> @strong{New} @* +@kbd{Control-o} ==> @strong{Open}@* @kbd{Control-w} ==> @strong{Close +Window}@* + +The changes described in the previous paragraph should be put into an +extension named @code{windows-keys.el} (see +@uref{enabling-extensions.html,Standard interface for enabling +extensions}) so that it can be enabled and disabled on the fly using a +menu item and can be selected as the default for a particular user in +their custom options file. Once this is implemented, the Windows +installer should also be modified so that it brings up a dialog box that +allows the user to make a selection of which key binding scheme they +would prefer as the default, either the XEmacs standard bindings, Vi +bindings (which would be Viper mode), Windows-style bindings, Brief, +CodeWright, Visual C++, or whatever we manage to implement. + +@node Future Work -- Misc Key Binding Ideas, , Future Work -- Better Support for Windows Style Key Bindings, Future Work -- Keybindings +@subsection Future Work -- Misc Key Binding Ideas +@cindex future work, misc key binding ideas +@cindex misc key binding ideas, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@itemize +@item +M-123 ... do digit arg + +@item +However, M-( group commands together until M-) + +@item +Nested M-() are allowed. + +@item +Number repeating plus () repeats N times each group of commands as a +unit. + +@item +M-() by itself forms an anonymous macro, and there should be a +command to repeat, like VI (execute macro), but when no () before, +it repeats the last command of same amount of complication - or more +like, somewhere there is a repeats all command back to make to act +that stopping like VI's dot command. +@item +C-numbers switches to a particular window. maybe 1-3 or 1-4 does +this. -@subsection Putting back the pdump_root_struct_ptrs -@cindex dumping, putting back the pdump_root_struct_ptrs +@item +C-4 or 5 to 9 (or ()? maybe reserved) switches to a particular frame. -The variables pointed to by pdump_root_struct_ptrs in the dump phase are -reset to the right relocated object addresses. +@item +Possibly C-Sh-numbers select more windows or frames. +@item +M-C-1 +M-C-2 +M-C-3 +M-C-4 +M-C-5 +M-C-6 +M-C-7 +M-C-8 +M-C-9 +M-C-0 -@subsection Object relocation -@cindex dumping, object relocation +maybe should be execute anonymous macros (other possibility is insert +register but you can easily simulate with a keyboard macro) -All the objects are relocated using their description and their offset -by @code{pdump_reloc_one}. This step is unnecessary if the -reloc_address is equal to the file loading address. +@item +What about C-S M-C-S M-S?? +@item +I think there should be default fun key binding for @strong{ILLEGIBLE} +similar to what I have - load, save, cut, copy, paste, kill line, +start/end macro, do macro +@end itemize -@subsection Putting back the pdump_root_objects and pdump_weak_object_chains -@cindex dumping, putting back the pdump_root_objects and pdump_weak_object_chains +@node Future Work -- Byte Code Snippets, Future Work -- Lisp Stream API, Future Work -- Keybindings, Future Work +@section Future Work -- Byte Code Snippets +@cindex future work, byte code snippets +@cindex byte code snippets, future work -Same as Putting back the pdump_root_struct_ptrs. +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} +@itemize +@item +For use in time critical (e.g. redisplay) places such as display +tables - a simple piece of code is evalled, e.g. +@example +(int-to-char (1+ c)) +@end example +where c is the arg, specbound. -@subsection Reorganize the hash tables -@cindex dumping, reorganize the hash tables +@item +can be compiled like +@example +(byte-compile-snippet (int-to-char (1+ c)) (c)) + ^^^ + environment of local vars +@end example -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 @code{pdump_reorganize_hash_table}. +@item +need eval with bindings (not hard to implement) +(extendable when lexical scoping present) -@node Remaining issues -@section Remaining issues -@cindex dumping, remaining issues +@item +What's the return value of byte-compile-snippet? +(Look to see how this might be implemented) +@end itemize -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. +@menu +* Future Work -- Autodetection:: +* Future Work -- Conversion Error Detection:: +* Future Work -- Unicode:: +* Future Work -- BIDI Support:: +* Future Work -- Localized Text/Messages:: +@end menu -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). +@node Future Work -- Autodetection, Future Work -- Conversion Error Detection, Future Work -- Byte Code Snippets, Future Work -- Byte Code Snippets +@subsection Future Work -- Autodetection +@cindex future work, autodetection +@cindex autodetection, future work + +There are various proposals contained here. + +@subheading New Implementation of Autodetection Mechanism + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +The current auto detection mechanism in XEmacs Mule has many +problems. For one thing, it is wrong too much of the time. Another +problem, although easily fixed, is that priority lists are fixed rather +than varying, depending on the particular locale; and finally, it +doesn't warn the user when it's not sure of the encoding or when there's +a mistake made during decoding. In both of these situations the user +should be presented with a list of likely encodings and given the +choice, rather than simply proceeding anyway and giving a result that is +likely to be wrong and may result in data corruption when the file is +saved out again. + +All coding systems are categorized according to their type. Currently +this includes ISO2022, Big 5, Shift-JIS, UTF8 and a few others. In +the future there will be many more types defined and this mechanism +will be generalized so that it is easily extendable by the Lisp +programmer. + +In general, each coding system type defines a series of subtypes which +are handled differently for the purpose of detection. For example, ISO +2022 defines many different subtypes such as 7 bit, 8 bit, locking +shift, designating and so on. UCS2 may define subtypes such as normal +and byte reversed. + +The detection engine works conceptually by calling the detection +methods of all of the defined coding system types in parallel on +successive chunks of data (which may, for example, be 4K in size, but +where the size makes no difference except for optimization purposes) +and watching the results until either a definite answer is determined +or the end of data is reached. The way the definite answer is +determined will be defined below. The detection method of the coding +system type is passed some data and a chunk of memory, which the +method uses to store its current state (and which is maintained +separately for each coding system type by the detection engine between +successive calls to the coding system type's detection method). Its +return value should be an alist consisting of a list of all of the +defined subtypes for that coding system type along with a level of +likelihood and a list of additional properties indicating certain +features detected in the data. The extra properties returned are +defined entirely by the particular coding system type and are used +only in the algorithm described below under "user control." However, +the levels of likelihood have a standard meaning as follows: + +Level 4 means "near certainty" and typically indicates that a +signature has been detected, usually at the beginning of the data, +indicating that the data is encoded in this particular coding system +type. An example of this would be the byte order mark at the beginning +of UCS2 encoded data or the GZIP mark at the beginning of GZIP data. + +Level 3 means "highly likely" and indicates that tell-tale signs have +been discovered in the data that are characteristic of this particular +coding system type. Examples of this might be ISO 2022 escape +sequences or the current Unicode end of line markers at regular +intervals. + +Level 2 means "strongly statistically likely" indicating that +statistical analysis concludes that there's a high chance that this +data is encoded according to this particular type. For example, this +might mean that for UCS2 data, there is a high proportion of null bytes +or other repeated bytes in the odd-numbered bytes of the data and a +high variance in the even-numbered bytes of the data. For Shift-JIS, +this might indicate that there were no illegal Shift-JIS sequences +and a fairly high occurrence of common Shift-JIS characters. + +Level 1 means "weak statistical likelihood" meaning that there is some +indication that the data is encoded in this coding system type. In +fact, there is a reasonable chance that it may be some other type as +well. This means, for example, that no illegal sequences were +encountered and at least some data was encountered that is purposely +not in other coding system types. For Shift-JIS data, this might mean +that some bytes in the range 128 to 159 were encountered in the data. + +Level 0 means "neutral" which is to say that there's either not enough +data to make any decision or that the data could well be interpreted +as this type (meaning no illegal sequences), but there is little or no +indication of anything particular to this particular type. + +Level -1 means "weakly unlikely" meaning that some data was +encountered that could conceivably be part of the coding system type +but is probably not. For example, successively long line-lengths or +very rarely-encountered sequences. + +Level -2 means "strongly unlikely" meaning that typically a number +of illegal sequences were encountered. + +The algorithm to determine when to stop and indicate that the data has +been detected as a particular coding system uses a priority list, +which is typically specified as part of the language environment +determined from the current locale or the user's choice. This priority +list consists of a list of coding system subtypes, along with a +minimum level required for positive detection and optionally +additional properties that need to be present. Using the return values +from all of the detection methods called, the detection engine looks +through this priority list until it finds a positive match. In this +priority list, along with each subtype is a particular coding system +to return when the subtype is encountered. (For example, in a +Japanese-language environment particular subtypes of ISO 2022 will be +associated with the Japanese coding system version of those +subtypes). It is perfectly legal and quite common in fact, to list the +same subtype more than once in the priority list with successively +lower requirements. Other facts that can be listed in the priority +list for a subtype are "reject", meaning that the data should never be +detected as this subtype, or "ask", meaning that if the data is +detected to be this subtype, the user will be asked whether they +actually mean this. This latter property could be used, for example, +towards the bottom of the priority list. + +In addition there is a global variable which specifies the minimum +number of characters required before any positive match is +reported. There may actually be more than one such variable for +different sources of data, for example, detection of files versus +detection of subprocess data. + +Whenever a file is opened and detected to be a particular coding +system, the subtype, the coding system and the associated level of +likelihood will be prominently displayed either in the echo area or in +a status box somewhere. + +If no positive match is found according to the priority list, or if +the matches that are found have the "ask" property on them, then the +user will be presented with a list of choices of possible encodings +and asked to choose one. This list is typically sorted first by level +of likelihood, and then within this, by the order in which the +subtypes appear in the priority list. This list is displayed in a +special kind of dialog box or other buffer allowing the user, in +addition to just choosing a particular encoding, to view what the +file would look like if it were decoded according to the type. + +Furthermore, whenever a file is decoded according to a particular +type, the decoding engine keeps track of status values that are output +by the coding system type's decoding method. Generally, this status +will be in the form of errors or warnings of various levels, some of +which may be severe enough to stop the decoding entirely, and some of +which may either indicate definitely malformed data but from which +it's possible to recover, or simply data that appears rather +questionable. If any of these status values are reported during +decoding, the user will be informed of this and asked "are you sure?" +As part of the "are you sure" dialog box or question, the user can +display the results of the decoding to make sure it's correct. If the +user says "no, they're not sure," then the same list of choices as +previously mentioned will be presented. + +@subheading RFC: Autodetection + +Also appeared under heading "Implementation of Coding System Priority +Lists in Various Locales" ? + +Author: @uref{mailto:stephen@@xemacs.org,Stephen Turnbull} + +Date: 11/1/1999 2:48 AM + +@example +>>>>> "Hrvoje" == Hrvoje Niksic <hniksic@@srce.hr> writes: + + [Ben sez:] + + >> You are perfectly free to set up your XEmacs like this, but + >> XEmacs/Mule @strong{will} autodetect by default if there is no + >> Content-Type: info and no reason to believe we are dealing with + >> binary files. + + Hrvoje> In that case, it will be a serious mistake to make + Hrvoje> --with-mule the default, ever. I think more care should + Hrvoje> be shown in meeting the need of European users. +@end example + +Hrvoje, I don't understand what you are worrying about. I suspect you +are worrying about Handa's hyperactive and obstinate Mule, not what +Ben has in mind. Yes, Ben has said "better guessing," but that's +simply not reasonable without substantial language environment +information. I think trying to detect Latin-1 vs Latin-2 in the POSIX +locale would be a big mistake, I think trying to guess Big 5 v. Shift +JIS in a European locale would be a big mistake. + +If Ben doesn't mean "more appropriate use of language environment +information" when he writes "better guessing," I, as much as you, want +to see how he plans to do that. Ben? ("Yes/no/oops I need to think +about it" is good enough if you have specifics you intend to put in +the RFC you're planning to present.) -The DOC file contents should probably end up in the dump file. +Let me give a formal proposal of what I would like to see in the +autodetection specification. +@enumerate +@item +Definitions -@node Events and the Event Loop, Evaluation; Stack Frames; Bindings, Dumping, Top -@chapter Events and the Event Loop -@cindex events and the event loop -@cindex event loop, events and the +@enumerate +@item +@dfn{Autodetection} means detecting and making available to Mule +the external file's encoding. See (5), below. It doesn't +imply any specific actions based on that information. + +@item +The @dfn{default} case is POSIX locale, and no environment +information in ~/.emacs. + +N.B. This @strong{will} cause breakage for all 1-byte users because +the default case can no longer assume Latin-1. You @strong{may} be +able to use the TTY font or the Xt -font option to fake this, +and default to iso8859-1; I would hope that we would not use +such a kludge in the beta versions, although it might be +satisfactory for general use. In particular, encodings like +VISCII (Vietnamese) and I believe KOI-8 (Cyrillic) are not +ISO-2022-clean, but using C1 control characters as a heuristic +for detecting binary files is useful. + +If we do allow it, I think that XEmacs should bitch and warn +that the practices of implicitly specifying language +environment by -font and defaulting on TTYs is deprecated and +likely to be obsoleted. + +@item +The @dfn{European} case is any Latin-* locale, either implied by +setlocale() and friends or set in ~/.emacs. Latin-1 is +specifically not given precedence over other Latin-*, or +non-Latin or non-ISO-8859 for that matter. I suspect but am +not sure that this case extends to all ISO-8859 encodings, and +possibly to non-ISO-8859 single-byte encodings like KOI-8r (in +particular when combined in a class with ISO-8859 encodings). + +@item +The @dfn{CJK} case is any CJK locale. Japanese is specifically +not given precedence over other Asian locales. + +@item +For completeness, define the @dfn{Unicode} case (Unicode +unfortunately has lots of junk such as precomposed characters, +language tags, and directionality indicators in it; we +probably don't care yet, but we should also not claim +compliance) and the @dfn{general} case (which has a lot of +features similar to Unicode, but lacks the advantage of a +unified encoding). This proposal has no idea how to handle +the special features of these, or even if that matters. The +general case includes stuff that nobody here really knows how +it works, like Tibetan and Ethiopic. +@end enumerate -@menu -* Introduction to Events:: -* Main Loop:: -* Specifics of the Event Gathering Mechanism:: -* Specifics About the Emacs Event:: -* The Event Stream Callback Routines:: -* Other Event Loop Functions:: -* Converting Events:: -* Dispatching Events; The Command Builder:: -@end menu +Each of the following cases is given in the order of priority of +detection. I'm not sure I'm serious about the top priority given the +(optional) Unicode detection. This may be appropriate if Ben is +right that ISO-2022 is going to disappear, but possibly not until then +(two two-byte sequences out of 65536 is probably 1.99 too many). It +probably isn't too risky if (6)(c) is taken pretty seriously; a Unicode +file should contain _no_ private use characters unless the encoding is +explicitly specified, and that's a block of 1/10 of the code space, +which should help a lot in detecting binary files. -@node Introduction to Events -@section Introduction to Events -@cindex events, introduction to +@item +Default locale - 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 @dfn{collection}. +@enumerate +@item +Some Unicode (fixed width; maybe UTF-8, too?) may optionally +be detected by the byte-order-mark magic (if the first two +bytes are 0xFE 0xFF, the file is Unicode text, if 0xFF 0xFE, +it is wrong-endian Unicode; if legal in UTF-8, it would be +0xFE 0xBB 0xBF, either-endian). This is probably an +optimization that should not be on by default yet. - 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.) +@item +ISO-2022 encodings will be detected as long as they use +explicit designation of all non-ASCII character sets. This +means that many 7-bit ISO-2022 encodings would be detected +(eg, ISO-2022-JP), but EUC-JP and X Compound Text would not, +because they implicitly designate character sets. - 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. +N.B. Latin-1 will be detected as binary, as for any Latin-*. - XEmacs has its own types of events (called @dfn{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. +N.B. An explicit ISO-2022 designation is semantically +equivalent to a Content-Type: header. It is more dangerous +because shorter, but I think we should recognize them by +default despite the slight risk; XEmacs is a text editor. - Emacs events are documented in @file{events.h}; I'll discuss them -later. +N.B. This is unlikely to be as dangerous as it looks at first +glance. Any file that includes an 8-bit-set byte before the +first valid designation should be detected as binary. -@node Main Loop -@section Main Loop -@cindex main loop -@cindex events, main loop +@item +Binary files will be detected (eg, presence of NULs, other +non-whitespace control characters, absurdly long lines, and +presence of bytes >127). - The @dfn{command loop} is the top-level loop that the editor is always -running. It loops endlessly, calling @code{next-event} to retrieve an -event and @code{dispatch-event} to execute it. @code{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, @code{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. @code{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 @dfn{command builder}. -This is documented elsewhere. +@item +Everything else is ASCII. - The guts of the command loop are in @code{command_loop_1()}. This -function doesn't catch errors, though---that's the job of -@code{command_loop_2()}, which is a condition-case (i.e. error-trapping) -wrapper around @code{command_loop_1()}. @code{command_loop_1()} never -returns, but may get thrown out of. +@item +Newlines will be detected in text files. +@end enumerate - When an error occurs, @code{cmd_error()} is called, which usually -invokes the Lisp error handler in @code{command-error}; however, a -default error handler is provided if @code{command-error} is @code{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 -@code{command_loop_2()} will finish and @code{command_loop_2()} will -reinvoke @code{command_loop_1()}. +@item +European locales - @code{command_loop_2()} is invoked from three places: from -@code{initial_command_loop()} (called from @code{main()} at the end of -internal initialization), from the Lisp function @code{recursive-edit}, -and from @code{call_command_loop()}. +@enumerate +@item +Unicode may optionally be detected by the byte-order-mark +magic. - @code{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 -@code{execute-kbd-macro} for macros and @code{exit} for minibuffers. -Note also that the low-level minibuffer-entering function, -@code{read-minibuffer-internal}, provides its own error handling and -does not need @code{command_loop_2()}'s error encapsulation; so it tells -@code{call_command_loop()} to invoke @code{command_loop_1()} directly.) +@item +ISO-2022 encodings will be detected as long as they use +explicit designation of all non-ASCII character sets. - Note that both read-minibuffer-internal and recursive-edit set up a -catch for @code{exit}; this is why @code{abort-recursive-edit}, which -throws to this catch, exits out of either one. +@item +A locale-specific class of 1-byte character sets (eg, +'(Latin-1)) will be detected. - @code{initial_command_loop()}, called from @code{main()}, sets up a -catch for @code{top-level} when invoking @code{command_loop_2()}, -allowing functions to throw all the way to the top level if they really -need to. Before invoking @code{command_loop_2()}, -@code{initial_command_loop()} calls @code{top_level_1()}, which handles -all of the startup stuff (creating the initial frame, handling the -command-line options, loading the user's @file{.emacs} file, etc.). The -function that actually does this is in Lisp and is pointed to by the -variable @code{top-level}; normally this function is -@code{normal-top-level}. @code{top_level_1()} is just an error-handling -wrapper similar to @code{command_loop_2()}. Note also that -@code{initial_command_loop()} sets up a catch for @code{top-level} when -invoking @code{top_level_1()}, just like when it invokes -@code{command_loop_2()}. +N.B. The reason for permitting a class is for cases like +Cyrillic where there are both ISO-8859 encodings and +incompatible encodings (KOI-8r) in common use. If you want to +write a Latin-1 v. Latin-2 detector, be my guest, but I don't +think it would be easy or accurate. -@node Specifics of the Event Gathering Mechanism -@section Specifics of the Event Gathering Mechanism -@cindex event gathering mechanism, specifics of the +@item +Binary files will be detected per (2)(c), except that only +8-bit bytes out of the encoding's range imply binary. - 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): +@item +Everything else is ASCII. -@noindent -@example - 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' -@end example +@item +Newlines will be detected in text files. +@end enumerate -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. +@item +CJK locales -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 @file{event-tty.c} and @file{event-Xt.c}, -respectively), the TTY event loop @emph{only} handles TTY consoles, -while the Xt event loop handles @emph{both} TTY and X consoles. This -situation is different from all of the output handlers, where you simply -have one per console type. +@enumerate +@item +Unicode may optionally be detected by the byte-order-mark +magic. - Here's the Xt Event Loop Diagram (notice that below a certain point, -it's the same as the above diagram): +@item +ISO-2022 encodings will be detected as long as they use +explicit designation of all non-ASCII character sets. -@example -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' -@end example +@item +A locale-specific class of multi-byte and wide-character +encodings will be detected. +N.B. No 1-byte character sets (eg, Latin-1) will be detected. +The reason for a class is to allow the Japanese to let Mule do +the work of choosing EUC v. SJIS. -@node Specifics About the Emacs Event -@section Specifics About the Emacs Event -@cindex event, specifics about the Lisp object +@item +Binary files will be detected per (3)(d). -@node The Event Stream Callback Routines -@section The Event Stream Callback Routines -@cindex event stream callback routines, the -@cindex callback routines, the event stream +@item +Everything else is ASCII. -@node Other Event Loop Functions -@section Other Event Loop Functions -@cindex event loop functions, other +@item +Newlines will be detected in text files. +@end enumerate - @code{detect_input_pending()} and @code{input-pending-p} look for -input by calling @code{event_stream->event_pending_p} and looking in -@code{[V]unread-command-event} and the @code{command_event_queue} (they -do not check for an executing keyboard macro, though). +@item +Unicode and general locales; multilingual use - @code{discard-input} cancels any command events pending (and any -keyboard macros currently executing), and puts the others onto the -@code{command_event_queue}. There is a comment about a ``race -condition'', which is not a good sign. +@enumerate +@item +Hopefully a system general enough to handle (2)--(4) will +handle these, too, but we should watch out for gotchas like +Unicode "plane 14" tags which (I think _both_ Ben and Olivier +will agree) have no place in the internal representation, and +thus must be treated as out-of-band control sequences. I +don't know if all such gotchas will be as easy to dispose of. - @code{next-command-event} and @code{read-char} are higher-level -interfaces to @code{next-event}. @code{next-command-event} gets the -next @dfn{command} event (i.e. keypress, mouse event, menu selection, -or scrollbar action), calling @code{dispatch-event} on any others. -@code{read-char} calls @code{next-command-event} and uses -@code{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. +@item +An explicit coding system priority list will be provided to +allow multilingual users to autodetect both Shift JIS and Big +5, say, but this ability is not promised by Mule, since it +would involve (eg) heuristics like picking a set of code +points that are frequent in Shift JIS and uncommon in Big 5 +and betting that a file containing many characters from that +set is Shift JIS. +@end enumerate -@node Converting Events -@section Converting Events -@cindex converting events -@cindex events, converting +@item +Relationship to decoding semantics - @code{character_to_event()}, @code{event_to_character()}, -@code{event-to-character}, and @code{character-to-event} convert between -characters and keypress events corresponding to the characters. If the -event was not a keypress, @code{event_to_character()} returns -1 and -@code{event-to-character} returns @code{nil}. These functions convert -between character representation and the split-up event representation -(keysym plus mod keys). +@enumerate +@item +Autodetection should be run on every input stream unless the +user explicitly disables it. -@node Dispatching Events; The Command Builder -@section Dispatching Events; The Command Builder -@cindex dispatching events; the command builder -@cindex events; the command builder, dispatching -@cindex command builder, dispatching events; the +@item +The (conceptual) default procedure is -Not yet documented. +@item +Read the file into the buffer -@node Evaluation; Stack Frames; Bindings, Symbols and Variables, Events and the Event Loop, Top -@chapter Evaluation; Stack Frames; Bindings -@cindex evaluation; stack frames; bindings -@cindex stack frames; bindings, evaluation; -@cindex bindings, evaluation; stack frames; +Announce the result of autodetection to the user. -@menu -* Evaluation:: -* Dynamic Binding; The specbinding Stack; Unwind-Protects:: -* Simple Special Forms:: -* Catch and Throw:: -@end menu +User may request decoding, with autodetected encoding(s) +given priority in a list of available encodings. -@node Evaluation -@section Evaluation -@cindex evaluation +zations (see (e) below) should avoid introducing data +tion that this default procedure would avoid. - @code{Feval()} evaluates the form (a Lisp object) that is passed to -it. Note that evaluation is only non-trivial for two types of objects: -symbols and conses. A symbol is evaluated simply by calling -@code{symbol-value} on it and returning the value. +sly, it can't be perfect if any autodecoding is done; +like Hrvoje should have an easily available option to + to this default (or an optimized approximation which +t actually read the whole file into a buffer) or simply +y everything as binary (with the "font" for binary files +a user option). - Evaluating a cons means calling a function. First, @code{eval} checks -to see if garbage-collection is necessary, and calls -@code{garbage_collect_1()} if so. It then increases the evaluation -depth by 1 (@code{lisp_eval_depth}, which is always less than -@code{max_lisp_eval_depth}) and adds an element to the linked list of -@code{struct backtrace}'s (@code{backtrace_list}). Each such structure -contains a pointer to the function being called plus a list of the -function's arguments. Originally these values are stored unevalled, and -as they are evaluated, the backtrace structure is updated. Garbage -collection pays attention to the objects pointed to in the backtrace -structures (garbage collection might happen while a function is being -called or while an argument is being evaluated, and there could easily -be no other references to the arguments in the argument list; once an -argument is evaluated, however, the unevalled version is not needed by -eval, and so the backtrace structure is changed). +@item +This implies that we should be detecting conditions in the +tail of the file which violate the implicit assumptions of the +coding system autodetected (eg, in UTF-8 illegal UTF-8 +sequences, including those corresponding to surrogates) should +raise a warning; the buffer should probably be made read-only +and the user prompted. -At this point, the function to be called is determined by looking at -the car of the cons (if this is a symbol, its function definition is -retrieved and the process repeated). The function should then consist -of either a @code{Lisp_Subr} (built-in function written in C), a -@code{Lisp_Compiled_Function} object, or a cons whose car is one of the -symbols @code{autoload}, @code{macro} or @code{lambda}. +This could be taken to extremes, like checking by table +whether all characters in a Japanese file are actually +legitimate JIS codes; that's insane (and would cause corporate +encodings to be recognized as binary). But we should think +about the idea that autodetection shouldn't mean XEmacs can't +change its mind. -If the function is a @code{Lisp_Subr}, the lisp object points to a -@code{struct Lisp_Subr} (created by @code{DEFUN()}), which contains a -pointer to the C function, a minimum and maximum number of arguments -(or possibly the special constants @code{MANY} or @code{UNEVALLED}), a -pointer to the symbol referring to that subr, and a couple of other -things. If the subr wants its arguments @code{UNEVALLED}, they are -passed raw as a list. Otherwise, an array of evaluated arguments is -created and put into the backtrace structure, and either passed whole -(@code{MANY}) or each argument is passed as a C argument. +@item +A flexible means for the user to delegate the decision +(conditional on the result of autodetection) to decode or not +to XEmacs or a Lisp program should be provided (eg, the +coding priority list and/or a file-coding-alist). -If the function is a @code{Lisp_Compiled_Function}, -@code{funcall_compiled_function()} is called. If the function is a -lambda list, @code{funcall_lambda()} is called. If the function is a -macro, [..... fill in] is done. If the function is an autoload, -@code{do_autoload()} is called to load the definition and then eval -starts over [explain this more]. +@item +Optimized operations (eg, the current lstreams) should be +provided, with the recognition that if they depend on sampling +the file they are risky. -When @code{Feval()} exits, the evaluation depth is reduced by one, the -debugger is called if appropriate, and the current backtrace structure -is removed from the list. +@item +Mule should provide a reasonable set of default delegations +(as in (d) above) for as many locales as possible. +@end enumerate + +@item +Implementation + +@enumerate +@item +I think all the decision logic suggested above can be +accomplished through a coding-priority-list and appropriate +initializations for different language environments, and a +file-coding-alist. + +@item +Many of the tests on the file's tail shouldn't be very +expensive; in particular, all of the ones I've suggested are +O(n) although they might involve moderate-sized auxiliary +tables for efficiency (eg, 64kB for a single Unicode-oriented +test). +@end enumerate +@end enumerate + +Other comments: + +It might be reasonable given Hrvoje's objections to require that any +autodetection that could cause data loss (any coding system that +involves escape sequences, and only those AFAIK: by design translation +to Unicode is invertible) by default prompt the user (presumable with +a novice-like ability to retain the prompt, always default to binary, +or always default to the autodetected encoding) in the future, at +least in locales that don't need it (POSIX, Latin-any). + +Ben thinks that we can remember the input data; I think it's going to +be hard to comprehensively test that a highly optimized version works. +Good design will help, but ISO-2022 is enormously complex, and there +are many encodings that violate even its lax assumptions. On the +other hand, memory is the only way to get non-rewindable streams right. + +Hrvoje himself said he would like to have an XEmacs that distinguishes +between Latin-1 and Latin-2 text. Where it is possible to do that, +this is exactly what autodetection of ISO-2022 and Unicode gives you. +Many people would want that, even at some risk of binary corruption. + + >> Once again I remind you that XEmacs is a @strong{text} editor. There + >> are lots of files that potentially may have Japanese etc. in + >> them without this marked, e.g. C or Elisp files in the XEmacs + >> source. Surely you're not arguing that we interpret even these + >> files as binary by default? + + Hrvoje> I am. If I want to see Japanese, I'll setup my + Hrvoje> environment that way. But I don't, and neither do 99% of + Hrvoje> Croatian users. I can't speak for French, Italian, and + Hrvoje> others, but I'd assume similar. + + Hrvoje> If there is Japanese in the source files, I will see it as + Hrvoje> escape sequences, which is perfectly fine, because I don't + Hrvoje> read Japanese. + +And some (European) people will have their terminals scrambled, +because Shift-JIS contains sequences that can change the state of +XTerm (as do fixed-width Unicode and Big5). This may also be a +problem with some Windows-12xx encodings; I'm not sure they all are +ISO-2022-clean. (This isn't a problem for XEmacs native X11 frames or +native MS-Windows frames, and the XEmacs sources themselves are all in +7-bit ISO-2022 now IIRC. But it is a potential source of great +frustration for many users.) + +I think that should be considered too, although it is presumably lower +priority than the data corruption of binary files. + +@subheading Response to RFC: Autodetection + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +Date: 11/1/1999 7:24 AM + +Stephen, thank you very much for writing this up. I think it is a good start, +and definitely moving in the direction I would like to see things going: more +proposals, less arguing. (aka "more light, less heat") However, I have some +suggestions for cleaning this up: + +You should try to make it more layered. For example, you might have one +section devoted to the workings of autodetection, which starts out like this +(the section numbers below are totally arbitrary): + +@subsubheading Section 5 + +@code{Autodetect()} is a function whose arguments are (1) a readable stream, (2) some +hints indicating how the autodetection is to proceed, and (3) a value +indicating the maximum number of characters to examine at the beginning of the +stream. (Possibly, the value in (3) may be some special symbol indicating +that we only go as far as the next line, or a certain number of lines ahead; +this would be used as part of "continuous autodetection", e.g. we are decoding +the results of an interactive terminal session, where the user may +periodically switch encodings, line terminations, etc. as different programs +get run and/or telnet or similar sessions are entered into and exited.) We +assume the stream is rewindable; if not, insert a "rewinding" stream in front +of the non-rewinding stream; this kind of stream automatically buffers the +data as necessary. +[You can use pseudo-code terminology here. No need for straight C or ELisp.] +[Then proceed to describe what the hints look like -- e.g. you could portray +it as a property list or whatever. The idea is that, for each locale, there +is a corresponding hints value that is used at least by default. The hints +structure also has to be set up to allow for two or more competing hints +specifications to be merged together. For example, the extension of a file +might provide an additional hint or hints about how to interpret the data of +that file, and the caller of @code{autodetect()}, when calling @code{autodetect()} on such a +file, would need to have a way of gracefully merging the default hints +corresponding to the locale with the more specific hints provided by the +extension. Furthermore, users like Hrvoje might well want to provide their +own hints to supplement and override parts of the generic hints -- e.g. "I +don't ever want to see non-European encodings decoded; treat them as binary +instead".] +[Then describe algorithmically how the autodetection works. First, you could +describe it more generally, i.e. presenting an algorithmic overview, then you +could discuss in detail exactly how autodetection of a particular type of +external encoding works -- e.g. "for iso2022, we first look for an escape +character, followed by a byte in this range [. ... .] etc."] + +@subsubheading Section 6 + +This section describes the concept of a locale in XEmacs, and how it is +derived from the user's environment. A locale in XEmacs is a pair, a country +and a language, together determining the handling of locale-specific areas of +XEmacs. All locale-specific areas in XEmacs make use of this XEmacs locale, +and do not attempt to derive the locale from any other sources. The user is +free to change the current locale at any time; accessor and mutator functions +are provided to do this so that various locale-specific areas can optionally +be changed together with it. + +[Then you describe how the XEmacs locale is extracted from .emacs, from +@code{setlocale()}, from the LANG environment variables, from -font, or wherever +else. All other sections assume this dirty work is done and never even +mention it] + +@subsubheading Section 7 + +[Here you describe the default @code{autodetect()} hints value corresponding to each +possible locale. You should probably use a schematic description here, e.g. +an actual Lisp property list, liberally commented.] + +@subsubheading Section 8 etc. + +[Other sections cover anything I've missed. By being very careful to separate +out the layers, you simultaneously introduce more rigor (easier to catch bugs) +and make it easier for someone else to understand it completely.] + +@subheading Better Algorithm, More Flexibility, Different Levels of Certainty + +@subheading Much More Flexible Coding System Priority List, per-Language Environment + +@subheading User Ability to Select Encoding when System Unsure or Encounters Errors + +@subheading Another Autodetection Proposal + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +however, in general the detection code has major problems and needs lots +of work: + +@itemize @bullet +@item +instead of merely "yes" or "no" for particular categories, we need a +more flexible system, with various levels of likelihood. Currently +I've created a system with six levels, as follows: + +[see @file{file-coding.h}] + +Let's consider what this might mean for an ASCII text detector. (In +order to have accurate detection, especially given the iteration I +proposed below, we need active detectors for @strong{all} types of data we +might reasonably encounter, such as ASCII text files, binary files, +and possibly other sorts of ASCII files, and not assume that simply +"falling back to no detection" will work at all well.) + +An ASCII text detector DOES NOT report ASCII text as level 0, since +that's what the detector is looking for. Such a detector ideally +wants all bytes in the range 0x20 - 0x7E (no high bytes!), except for +whitespace control chars and perhaps a few others; LF, CR, or CRLF +sequences at regular intervals (where "regular" might mean an average +< 100 chars and 99% < 300 for code and other stuff of the "text file +w/line breaks" variety, but for the "text file w/o line breaks" +variety, excluding blank lines, averages could easily be 600 or more +with 2000-3000 char "lines" not so uncommon); similar statistical +variance between odds and evens (not Unicode); frequent occurrences of +the space character; letters more common than non-letters; etc. Also +checking for too little variability between frequencies of characters +and for exclusion of particular characters based on character ranges +can catch ASCII encodings like base-64, UUEncode, UTF-7, etc. +Granted, this doesn't even apply to everything called "ASCII", and we +could potentially distinguish off ASCII for code, ASCII for text, +etc. as separate categories. However, it does give us a lot to work +off of, in deciding what likelihood to choose -- and it shows there's +in fact a lot of detectable patterns to look for even in something +seemingly so generic as ASCII. The detector would report most text +files in level 1 or level 2. EUC encodings, Shift-JIS, etc. probably +go to level -1 because they also pass the EOL test and all other tests +for the ASCII part of the text, but have lots of high bytes, which in +essence turn them into binary. Aberrant text files like something in +BASE64 encoding might get placed in level 0, because they pass most +tests but fail dramatically the frequency test; but they should not be +reported as any lower, because that would cause explicit prompting, +and the user should be able any valid text file without prompting. +The escape sequences and the base-64-type checks might send 7-bit +iso2022 to 0, but probably not -1, for similar reasons. + +@item +The assumed algorithm for the above detection levels is to in essence +sort categories first by detection level and then by priority. +Perhaps, however, we would want smarter algorithms, or at least +something user-controllable -- in particular, when (other than no +category at level 0 or greater) do we prompt the user to pick a +category? + +@item +Improvements in how the detection algorithm works: we want to handle +lots of different ways something could be encoded, including multiple +stacked encodings. trying to specify a series of detection levels +(check for base64 first, then check for gzip, then check for an i18n +decoding, then for crlf) won't generally work. for example, what +about the same encoding appearing more than once? for example, take +euc-jp, base64'd, then gzip'd, then base64'd again: this could well +happen, and you could specify the encodings specifically as +base64|gzip|base64|euc-jp, but we'd like to autodetect it without +worrying about exactly what order these things appear in. we should +allow for iterating over detection/decoding cycles until we reach +some maximum (we got stuck in a loop, due to incorrect category +tables or detection algorithms), have no reported detection levels +over -1, or we end up with no change after a decoding pass (i.e. the +coding system associated with a chosen category was @code{no-conversion} +or something equivalent). it might make sense to divide things into +two phases (internal and external), where the internal phase has a +separate category list and would probably mostly end up handling EOL +detection; but the i think about it, the more i disagree. with +properly written detectors, and properly organized tables (in +general, those decodings that are more "distinctive" and thus +detectable with greater certainty go lower on the list), we shouldn't +need two phases. for example, let's say the example above was also +in CRLF format. The EOL detector (which really detects *plain text* +with a particular EOL type) would return at most level 0 for all +results until the text file is reached, whereas the base64, gzip or +euc-jp decoders will return higher. Once the text file is reached, +the EOL detector will return 0 or higher for the CRLF encoding, and +all other detectors will return 0 or lower; thus, we will successfully +proceed through CRLF decoding, or at worst prompt the user. (The only +external-vs-internal distinction that might make sense here is to +favor coding systems of the correct source type over those that +require conversion between external and internal; if done right, this +could allow the CRLF detector to return level 1 for all CRLF-encoded +text files, even those that look like Base-64 or similar encoding, so +that CRLF encoding will always get decoded without prompting, but not +interfere with other decoders. On the other hand, this +external-vs-internal distinction may not matter at all -- with +automatic internal-external conversion, CRLF decoding can occur +before or after decoding of euc-jp, base64, iso2022, or similar, +without any difference in the final results.) + +#### What are we trying to say? In base64, the CRLF decoding before +base64 decoding is irrelevant, they will be thrown out as whitespace +is not significant in base64. + +[sjt considers all of this to be rather bogus. Ideas like "greater +certainty" and "distinctive" can and should be quantified. The issue +of proper table organization should be a question of optimization.] + +[sjt wonders if it might not be a good idea to use Unicode's newline +character as the internal representation so that (for non-Unicode +coding systems) we can catch EOL bugs on Unix too.] + +@item +There need to be two priority lists and two +category->coding-system lists. Once is general, the other +category->langenv-specific. The user sets the former, the langenv +category->the latter. The langenv-specific entries take precedence +category->over the others. This works similarly to the +category->category->Unicode charset priority list. + +@item +The simple list of coding categories per detectors is not enough. +Instead of coding categories, we need parameters. For example, +Unicode might have separate detectors for UTF-8, UTF-7, UTF-16, +and perhaps UCS-4; or UTF-16/UCS-4 would be one detection type. +UTF-16 would have parameters such as "little-endian" and "needs BOM", +and possibly another one like "collapse/expand/leave alone composite +sequences" once we add this support. Usually these parameters +correspond directly to a coding system parameter. Different +likelihood values can be specified for each parameter as well as for +the detection type as a whole. The user can specify particular +coding systems for a particular combination of detection type and +parameters, or can give "default parameters" associated with a +detection type. In the latter case, we create a new coding system as +necessary that corresponds to the detected type and parameters. + +@item +a better means of presentation. rather than just coming up +with the new file decoded according to the detected coding +system, allow the user to browse through the file and +conveniently reject it if it looks wrong; then detection +starts again, but with that possibility removed. in cases where +certainty is low and thus more than one possibility is presented, +the user can browse each one and select one or reject them all. + +@item +fail-safe: even after the user has made a choice, if they +later on realize they have the wrong coding system, they can +go back, and we've squirreled away the original data so they +can start the process over. this may be tricky. + +@item +using a larger buffer for detection. we use just a small +piece, which can give quite random results. we may need to +buffer up all the data we look through because we can't +necessarily rewind. the idea is we proceed until we get a +result that's at least at a certain level of certainty +(e.g. "probable") or we reached a maximum limit of how much +we want to buffer. + +@item +dealing with interactive systems. we might need to go ahead +and present the data before we've finished detection, and +then re-decode it, perhaps multiple times, as we get better +detection results. + +@item +Clearly some of these are more important than others. at the +very least, the "better means of presentation" should be +implemented as soon as possible, along with a very simple means +of fail-safe whenever the data is readibly available, e.g. it's +coming from a file, which is the most common scenario. +@end itemize -Both @code{funcall_compiled_function()} and @code{funcall_lambda()} need -to go through the list of formal parameters to the function and bind -them to the actual arguments, checking for @code{&rest} and -@code{&optional} symbols in the formal parameters and making sure the -number of actual arguments is correct. -@code{funcall_compiled_function()} can do this a little more -efficiently, since the formal parameter list can be checked for sanity -when the compiled function object is created. +ben [at least that's what sjt thinks] -@code{funcall_lambda()} simply calls @code{Fprogn} to execute the code -in the lambda list. +***** -@code{funcall_compiled_function()} calls the real byte-code interpreter -@code{execute_optimized_program()} on the byte-code instructions, which -are converted into an internal form for faster execution. +Author: @uref{mailto:stephen@@xemacs.org,Stephen Turnbull} -When a compiled function is executed for the first time by -@code{funcall_compiled_function()}, or during the dump phase of building -XEmacs, the byte-code instructions are converted from a -@code{Lisp_String} (which is inefficient to access, especially in the -presence of MULE) into a @code{Lisp_Opaque} object containing an array -of unsigned char, which can be directly executed by the byte-code -interpreter. At this time the byte code is also analyzed for validity -and transformed into a more optimized form, so that -@code{execute_optimized_program()} can really fly. +While this is clearly something of an improvement over earlier designs, +it doesn't deal with the most important issue: to do better than categories +(which in the medium term is mostly going to mean "which flavor of Unicode +is this?"), we need to look at statistical behavior rather than ruling out +categories via presence of specific sequences. This means the stream +processor should -Here are some of the optimizations performed by the internal byte-code -transformer: @enumerate @item -References to the @code{constants} array are checked for out-of-range -indices, so that the byte interpreter doesn't have to. +keep octet distributions (octet, 2-, 3-, 4- octet sequences) @item -References to the @code{constants} array that will be used as a Lisp -variable are checked for being correct non-constant (i.e. not @code{t}, -@code{nil}, or @code{keywordp}) symbols, so that the byte interpreter -doesn't have to. +in some kind of compressed form @item -The maximum number of variable bindings in the byte-code is -pre-computed, so that space on the @code{specpdl} stack can be -pre-reserved once for the whole function execution. +look for "skip features" (eg, characteristic behavior of leading +bytes for UTF-7, UTF-8, UTF-16, Mule code) @item -All byte-code jumps are relative to the current program counter instead -of the start of the program, thereby saving a register. +pick up certain "simple" regexps @item -One-byte relative jumps are converted from the byte-code form of unsigned -chars offset by 127 to machine-friendly signed chars. +provide "triggers" to determine when statistical detectors should be +invoked, such as octet count +@item +and "magic" like Unicode signatures or file(1) magic. @end enumerate -Of course, this transformation of the @code{instructions} should not be -visible to the user, so @code{Fcompiled_function_instructions()} needs -to know how to convert the optimized opaque object back into a Lisp -string that is identical to the original string from the @file{.elc} -file. (Actually, the resulting string may (rarely) contain slightly -different, yet equivalent, byte code.) +--sjt -@code{Ffuncall()} implements Lisp @code{funcall}. @code{(funcall fun -x1 x2 x3 ...)} is equivalent to @code{(eval (list fun (quote x1) (quote -x2) (quote x3) ...))}. @code{Ffuncall()} contains its own code to do -the evaluation, however, and is very similar to @code{Feval()}. +@node Future Work -- Conversion Error Detection, Future Work -- Unicode, Future Work -- Autodetection, Future Work -- Byte Code Snippets +@subsection Future Work -- Conversion Error Detection +@cindex future work, conversion error detection +@cindex conversion error detection, future work -From the performance point of view, it is worth knowing that most of the -time in Lisp evaluation is spent executing @code{Lisp_Subr} and -@code{Lisp_Compiled_Function} objects via @code{Ffuncall()} (not -@code{Feval()}). +@subheading "No Corruption" Scheme for Preserving External Encoding when Non-Invertible Transformation Applied -@code{Fapply()} implements Lisp @code{apply}, which is very similar to -@code{funcall} except that if the last argument is a list, the result is the -same as if each of the arguments in the list had been passed separately. -@code{Fapply()} does some business to expand the last argument if it's a -list, then calls @code{Ffuncall()} to do the work. +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} -@code{apply1()}, @code{call0()}, @code{call1()}, @code{call2()}, and -@code{call3()} call a function, passing it the argument(s) given (the -arguments are given as separate C arguments rather than being passed as -an array). @code{apply1()} uses @code{Fapply()} while the others use -@code{Ffuncall()} to do the real work. +A preliminary and simple implementation is: -@node Dynamic Binding; The specbinding Stack; Unwind-Protects -@section Dynamic Binding; The specbinding Stack; Unwind-Protects -@cindex dynamic binding; the specbinding stack; unwind-protects -@cindex binding; the specbinding stack; unwind-protects, dynamic -@cindex specbinding stack; unwind-protects, dynamic binding; the -@cindex unwind-protects, dynamic binding; the specbinding stack; +@quotation +But you could implement it much more simply and usefully by just +determining, for any text being decoded into mule-internal, can we go +back and read the source again? If not, remember the entire file +(GNUS message, etc) in text properties. Then, implement the UI +interface (like Netscape's) on top of that. This way, you have +something that at least works, but it might be inefficient. All we +would need to do is work on making the underlying implementation more +efficient. +@end quotation + +A more detailed proposal for avoiding binary file corruption is + +@quotation +Basic idea: A coding system is a filter converting an entire input +stream into an output stream. The resulting stream can be said to be +"correspondent to" the input stream. Similarly, smaller units can +correspond. These could potentially include zero width intervals on +either side, but we avoid this. Specifically, the coding system works +like: @example -struct specbinding -@{ - Lisp_Object symbol; - Lisp_Object old_value; - Lisp_Object (*func) (Lisp_Object); /* for unwind-protect */ -@}; -@end example +loop (input) @{ - @code{struct specbinding} is used for local-variable bindings and -unwind-protects. @code{specpdl} holds an array of @code{struct specbinding}'s, -@code{specpdl_ptr} points to the beginning of the free bindings in the -array, @code{specpdl_size} specifies the total number of binding slots -in the array, and @code{max_specpdl_size} specifies the maximum number -of bindings the array can be expanded to hold. @code{grow_specpdl()} -increases the size of the @code{specpdl} array, multiplying its size by -2 but never exceeding @code{max_specpdl_size} (except that if this -number is less than 400, it is first set to 400). + Read bytes till we have enough to generate a translated character or a chars. - @code{specbind()} binds a symbol to a value and is used for local -variables and @code{let} forms. The symbol and its old value (which -might be @code{Qunbound}, indicating no prior value) are recorded in the -specpdl array, and @code{specpdl_size} is increased by 1. + This establishes a "correspondence" between the whole input and + output more or less in minimal chunks. - @code{record_unwind_protect()} implements an @dfn{unwind-protect}, -which, when placed around a section of code, ensures that some specified -cleanup routine will be executed even if the code exits abnormally -(e.g. through a @code{throw} or quit). @code{record_unwind_protect()} -simply adds a new specbinding to the @code{specpdl} array and stores the -appropriate information in it. The cleanup routine can either be a C -function, which is stored in the @code{func} field, or a @code{progn} -form, which is stored in the @code{old_value} field. +@} +@end example - @code{unbind_to()} removes specbindings from the @code{specpdl} array -until the specified position is reached. Each specbinding can be one of -three types: +We then do the following processing: @enumerate @item -an unwind-protect with a C cleanup function (@code{func} is not 0, and -@code{old_value} holds an argument to be passed to the function); +Eliminate correspondences where one or the other of the I/O streams +has a zero interval by combining with an adjacent interval; + @item -an unwind-protect with a Lisp form (@code{func} is 0, @code{symbol} -is @code{nil}, and @code{old_value} holds the form to be executed with -@code{Fprogn()}); or +Group together all adjacent "identity" correspondences into as +large groups as possible; + @item -a local-variable binding (@code{func} is 0, @code{symbol} is not -@code{nil}, and @code{old_value} holds the old value, which is stored as -the symbol's value). +Use text properties to store the non-identity correspondences on +the characters. For identity correspondences, use a simple text +property on all that contains no data but just indicates that the +whole string of text is identity corresponded. (How do we define +"identity"? Latin 1 or could it be something else? For example, +Latin 2)? + +@item +Figure out the procedures when text is inserted/deleted and copied +or pasted. + +@item +Figure out to save the file out making use of the +correspondences. Allow ways of saving without correspondences, and +doing a "save to buffer with and without correspondences." Need to +be clever when dealing with modal coding systems to parse the +correspondences to get the internal state right. @end enumerate +@end quotation -@node Simple Special Forms -@section Simple Special Forms -@cindex special forms, simple +@subheading Another Error-Catching Idea -@code{or}, @code{and}, @code{if}, @code{cond}, @code{progn}, -@code{prog1}, @code{prog2}, @code{setq}, @code{quote}, @code{function}, -@code{let*}, @code{let}, @code{while} +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} -All of these are very simple and work as expected, calling -@code{Feval()} or @code{Fprogn()} as necessary and (in the case of -@code{let} and @code{let*}) using @code{specbind()} to create bindings -and @code{unbind_to()} to undo the bindings when finished. +Nov 4, 1999 -Note that, with the exception of @code{Fprogn}, these functions are -typically called in real life only in interpreted code, since the byte -compiler knows how to convert calls to these functions directly into -byte code. +Finally, I don't think "save the input" is as hard as you make it out to +be. Conceptually, in fact, it's simple: for each minimal group of bytes +where you cannot absolutely guarantee that an external->internal +transformation is reversible, you put a text property on the +corresponding internal character indicating the bytes that generated +this character. We also put a text property on every character, +indicating the coding system that caused the transformation. This +latter text property is extremely efficient (e.g. in a buffer with no +data pasted from elsewhere, it will map to a single extent over all the +buffer), and the former cases should not be prevalent enough to cause a +lot of inefficiency, esp. if we define what "reversible" means for each +coding system in such a way that it correctly handles the most common +cases. The hardest part, in fact, is making all the string/text +handling in XEmacs be robust w.r.t. text properties. + +@subheading Strategies for Error Annotation and Coding Orthogonalization + +Author: @uref{mailto:stephen@@xemacs.org,Stephen Turnbull} + +We really want to separate out a number of things. Conceptually, +there is a nested syntax. + +At the top level is the ISO 2022 extension syntax, including charset +designation and invocation, and certain auxiliary controls such as the +ISO 6429 direction specification. These are octet-oriented, with the +single exception (AFAIK) of the "exit Unicode" sequence which uses the +UTF's natural width (1 byte for UTF-7 and UTF-8, 2 bytes for UCS-2 and +UTF-16, and 4 bytes for UCS-4 and UTF-32). This will be treated as a +(deprecated) special case in Unicode processing. + +The middle layer is ISO 2022 character interpretation. This will depend +on the current state of the ISO 2022 registers, and assembles octets +into the character's internal representation. + +The lowest level is translating system control conventions. At present +this is restricted to newline translation, but one could imagine doing +tab conversion or line wrapping here. "Escape from Unicode" processing +would be done at this level. + +At each level the parser will verify the syntax. In the case of a +syntax error or warning (such as a redundant escape sequence that affects +no characters), the parser will take some action, typically inserting the +erroneous octets directly into the output and creating an annotation +which can be used by higher level I/O to mark the affected region. + +This should make it possible to do something sensible about separating +newline convention processing from character construction, and about +preventing ISO 2022 escape sequences from being recognized +inappropriately. + +The basic strategy will be to have octet classification tables, and +switch processing according to the table entry. -@node Catch and Throw -@section Catch and Throw -@cindex catch and throw -@cindex throw, catch and +It's possible that, by doing the processing with tables of functions or +the like, the parser can be used for both detection and translation. + +@subheading Handling Writing a File Safely, Without Data Loss + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@quotation +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" coding systems can perhaps +be presented at the end, which will lose only a few characters +and are perhaps what the users were looking for. + +[sjt sez this whole step is a crock. If a universal coding system +is unacceptable, the user had better know what he/she is doing, +and explicitly specify a lossy encoding. +In principle, we can simply check for characters being writable as +we go along. Eg, via an "unrepresentable character handler." We +still have the buffer contents. If we can't successfully save, +then ask the user what to do. (Do we ever simply destroy previous +file version before completing a write?)] + +@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. + +[sjt -- something is very confused, here; safe charsets should be +defined as those charsets all of whose characters can be encoded.] + +@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 quotation + +Author: @uref{mailto:stephen@@xemacs.org,Stephen Turnbull} + +I don't much like Ben's scheme. First, this isn't an issue of I/O, +it's a coding issue. It can happen in many places, not just on stream +I/O. Error checking should take place on all translations. Second, +the two-pass algorithm should be avoided if possible. In some cases +(eg, output to a tty) we won't be able to go back and change the +previously output data. Third, the whole idea of having a buffer full +of arbitrary characters which we're going to somehow shoehorn into a +file based on some twit user's less than informed idea of a coding system +is kind of laughable from the start. If we're going to say that a buffer +has a coding system, shouldn't we enforce restrictions on what you can +put into it? Fourth, what's the point of having safe charsets if some +of the characters in them are unsafe? Fifth, what makes you think we're +going to have a list of charsets? It seems to me that there might be +reasons to have user-defined charsets (eg, "German" vs "French" subsets +of ISO 8859/15). Sixth, the idea of having language environment determine +precedence doesn't seem very useful to me. Users who are working with a +language that corresponds to the language environment are not going to +run into safe charsets problems. It's users who are outside of their +usual language environment who run into trouble. Also, the reason for +specifying anything other than a universal coding system is normally +restrictions imposed by other users or applications. Seventh, the +statistical feedback isn't terribly useful. Users rarely "want" a +coding system, they want their file saved in a useful way. We could +add a FORCE argument to conversions for those who really want a specific +coding system. But mostly, a user might want to edit out a few unsafe +characters. So (up to some maximum) we should keep a list of unsafe +text positions, and provide a convenient function for traversing them. + +--sjt + +@node Future Work -- Unicode, Future Work -- BIDI Support, Future Work -- Conversion Error Detection, Future Work -- Byte Code Snippets +@subsection Future Work -- Unicode +@cindex future work, unicode +@cindex unicode, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +Following is an old proposal. Unicode has been implemented already, in +a different fashion; but there are some ideas here for more general +support, e.g. properties of Unicode characters other than their mappings +to particular charsets. + + +We recognize 128, [256], 128x128, [256x256] for source charsets; + +for Unicode, 256x256 or 16x256x256. + +In all cases, use tables of tables and substitute a default subtable +if entire row is empty. + +If destination is Unicode, either 16 or 32 bits. + +If destination is charset, either 8 or 16 bits. + +For the moment, since we only do 94, 96, 94x94 or 96x96, only do 128 +or 128x128 for source charsets and use the range 33-126 or 32-127. +(Except ASCII - we special case that and have no table because we can +algorithmically translate) + +Also have a 16x256x256 table -> 32 bits of Unicode char properties. + +A particular charset contains two associated mapping tables, for both +directions. + +API is set-unicode-mapping: @example -struct catchtag -@{ - Lisp_Object tag; - Lisp_Object val; - struct catchtag *next; - struct gcpro *gcpro; - jmp_buf jmp; - struct backtrace *backlist; - int lisp_eval_depth; - int pdlcount; -@}; +(set-unicode-mapping + unicode char + unicode charset-code charset-offset + unicode vector of char + unicode list of char + unicode string of char + unicode vector or list of codes charset-offset @end example - @code{catch} is a Lisp function that places a catch around a body of -code. A catch is a means of non-local exit from the code. When a catch -is created, a tag is specified, and executing a @code{throw} to this tag -will exit from the body of code caught with this tag, and its value will -be the value given in the call to @code{throw}. If there is no such -call, the code will be executed normally. + Establishes a mapping between a unicode codepoint (an integer) and + one or more chars in a charset. The mapping is automatically + established in both directions. Chars in a charset can be specified + either with an actual character or a codepoint (i.e. an integer) + and the charset it's within. If a sequence of chars or charset + points is given, multiple mappings are established for consecutive + unicode codepoints starting with the given one. Charset codepoints + are specified as most-significant x 256 + least significant, with + both bytes in the range 33-126 (for 94 or 94x94) or 32-127 (for 96 + or 96x96), unless an offset is given, which will be subtracted from + each byte. (Most common values are 128, for codepoints given with + the high bit set, or -32, for codepoints given as 1-94 or 0-95.) - Information pertaining to a catch is held in a @code{struct catchtag}, -which is placed at the head of a linked list pointed to by -@code{catchlist}. @code{internal_catch()} is passed a C function to -call (@code{Fprogn()} when Lisp @code{catch} is called) and arguments to -give it, and places a catch around the function. Each @code{struct -catchtag} is held in the stack frame of the @code{internal_catch()} -instance that created the catch. +Other API's: - @code{internal_catch()} is fairly straightforward. It stores into the -@code{struct catchtag} the tag name and the current values of -@code{backtrace_list}, @code{lisp_eval_depth}, @code{gcprolist}, and the -offset into the @code{specpdl} array, sets a jump point with @code{_setjmp()} -(storing the jump point into the @code{struct catchtag}), and calls the -function. Control will return to @code{internal_catch()} either when -the function exits normally or through a @code{_longjmp()} to this jump -point. In the latter case, @code{throw} will store the value to be -returned into the @code{struct catchtag} before jumping. When it's -done, @code{internal_catch()} removes the @code{struct catchtag} from -the catchlist and returns the proper value. +@example +(write-unicode-mapping file charset) +@end example - @code{Fthrow()} goes up through the catchlist until it finds one with -a matching tag. It then calls @code{unbind_catch()} to restore -everything to what it was when the appropriate catch was set, stores the -return value in the @code{struct catchtag}, and jumps (with -@code{_longjmp()}) to its jump point. + Write the mapping table for a particular charset to the specified + file. The tables are written in an internal format that allows for + efficient loading, for portability across platforms and XEmacs + invocations, for conserving space, for appending multiple tables one + directly after another with no need for a directory anywhere in the + file, and for reorganizing a file as in this format (with a magic + sequence at the beginning). The data will be appended at the end of + a file, so that multiple tables can be written to a file; remove the + file first to avoid this. - @code{unbind_catch()} removes all catches from the catchlist until it -finds the correct one. Some of the catches might have been placed for -error-trapping, and if so, the appropriate entries on the handlerlist -must be removed (see ``errors''). @code{unbind_catch()} also restores -the values of @code{gcprolist}, @code{backtrace_list}, and -@code{lisp_eval}, and calls @code{unbind_to()} to undo any specbindings -created since the catch. +@example +(write-unicode-properties file unicode-codepoint length) +@end example + Write the Unicode properties (not including charset mappings) for + the specified range of contiguous Unicode codepoints to the end of + the file (i.e. append mode) in a binary format similar to what was + mentioned in the write-unicode-mapping description and with the same + features. -@node Symbols and Variables, Buffers and Textual Representation, Evaluation; Stack Frames; Bindings, Top -@chapter Symbols and Variables -@cindex symbols and variables -@cindex variables, symbols and +Extension to set-unicode-mapping: -@menu -* Introduction to Symbols:: -* Obarrays:: -* Symbol Values:: -@end menu +@example +(set-unicode-mapping + list-or-vector-of-unicode-codepoints char + "" charset-code charset-offset + "" sequence of char + "" list-or-vector-of-codes +charset-offset +@end example -@node Introduction to Symbols -@section Introduction to Symbols -@cindex symbols, introduction to + The first two forms are conceptually the inverse of the forms above + to specify characters for a contiguous range of Unicode codepoints. + These new forms let you specify the Unicode codepoints for a + contiguous range of chars in a charset. "Contiguous" here means + that if we run off the end of a row, we go to the first entry of the + next row, rather than to an invalid code point. For example, in a + 94x94 charset, valid rows and columns are in the range 0x21-0x7e; + after 0x457c 0x457d 4x457e goes 0x4621, not something like 0x457f, + which is invalid. - A symbol is basically just an object with four fields: a name (a -string), a value (some Lisp object), a function (some Lisp object), and -a property list (usually a list of alternating keyword/value pairs). -What makes symbols special is that there is usually only one symbol with -a given name, and the symbol is referred to by name. This makes a -symbol a convenient way of calling up data by name, i.e. of implementing -variables. (The variable's value is stored in the @dfn{value slot}.) -Similarly, functions are referenced by name, and the definition of the -function is stored in a symbol's @dfn{function slot}. This means that -there can be a distinct function and variable with the same name. The -property list is used as a more general mechanism of associating -additional values with particular names, and once again the namespace is -independent of the function and variable namespaces. + The final two forms are the most general, letting you specify an + arbitrary set of both Unicode points and charset chars, and the two + are matched up just like a series of individual calls. However, if + the lists or vectors do not have the same length, an error is + signaled. -@node Obarrays -@section Obarrays -@cindex obarrays +@example +(load-unicode-mapping file &optional charset) +@end example + + If charset is omitted, loads all charset mapping tables found and + returns a list of the charsets found. If charset is specified, + searches through the file for the appropriate mapping tables. (This + is extremely fast because each entry in the file gives an offset to + the next one). Returns t if found. + +@example +(load-unicode-properties file unicode-codepoint) +@end example + +@example +(list-unicode-entries file) +@end example + +@example +(autoload-unicode-mapping charset) +@end example + +... + +(unfinished) + +@node Future Work -- BIDI Support, Future Work -- Localized Text/Messages, Future Work -- Unicode, Future Work -- Byte Code Snippets +@subsection Future Work -- BIDI Support +@cindex future work, bidi support +@cindex bidi support, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} - The identity of symbols with their names is accomplished through a -structure called an obarray, which is just a poorly-implemented hash -table mapping from strings to symbols whose name is that string. (I say -``poorly implemented'' because an obarray appears in Lisp as a vector -with some hidden fields rather than as its own opaque type. This is an -Emacs Lisp artifact that should be fixed.) +@enumerate +@item +Use text properties to handle nesting levels, overrides +BIDI-specific text properties (as per Unicode BIDI algorithm) +computed at text insertion time. - Obarrays are implemented as a vector of some fixed size (which should -be a prime for best results), where each ``bucket'' of the vector -contains one or more symbols, threaded through a hidden @code{next} -field in the symbol. Lookup of a symbol in an obarray, and adding a -symbol to an obarray, is accomplished through standard hash-table -techniques. +@item +Lisp API for reordering a display line at redisplay time, +possibly substitution of different glyphs (esp. mirroring of +glyphs). - The standard Lisp function for working with symbols and obarrays is -@code{intern}. This looks up a symbol in an obarray given its name; if -it's not found, a new symbol is automatically created with the specified -name, added to the obarray, and returned. This is what happens when the -Lisp reader encounters a symbol (or more precisely, encounters the name -of a symbol) in some text that it is reading. There is a standard -obarray called @code{obarray} that is used for this purpose, although -the Lisp programmer is free to create his own obarrays and @code{intern} -symbols in them. +@item +Lisp API called after a display line is laid out, but only when +reordering may be necessary (display engine checks for +non-uniform BIDI text properties; can handle internally a line +that's completely in one direction) - Note that, once a symbol is in an obarray, it stays there until -something is done about it, and the standard obarray @code{obarray} -always stays around, so once you use any particular variable name, a -corresponding symbol will stay around in @code{obarray} until you exit -XEmacs. +@item +Default direction is a buffer-local variable - Note that @code{obarray} itself is a variable, and as such there is a -symbol in @code{obarray} whose name is @code{"obarray"} and which -contains @code{obarray} as its value. +@item +We concentrate on implementing Unicode BIDI algorithm. - Note also that this call to @code{intern} occurs only when in the Lisp -reader, not when the code is executed (at which point the symbol is -already around, stored as such in the definition of the function). +@item +Display support for mirroring of entire window - You can create your own obarray using @code{make-vector} (this is -horrible but is an artifact) and intern symbols into that obarray. -Doing that will result in two or more symbols with the same name. -However, at most one of these symbols is in the standard @code{obarray}: -You cannot have two symbols of the same name in any particular obarray. -Note that you cannot add a symbol to an obarray in any fashion other -than using @code{intern}: i.e. you can't take an existing symbol and put -it in an existing obarray. Nor can you change the name of an existing -symbol. (Since obarrays are vectors, you can violate the consistency of -things by storing directly into the vector, but let's ignore that -possibility.) +@item +Display code keeps track of mirroring junctures so it can +display double cursor. - Usually symbols are created by @code{intern}, but if you really want, -you can explicitly create a symbol using @code{make-symbol}, giving it -some name. The resulting symbol is not in any obarray (i.e. it is -@dfn{uninterned}), and you can't add it to any obarray. Therefore its -primary purpose is as a symbol to use in macros to avoid namespace -pollution. It can also be used as a carrier of information, but cons -cells could probably be used just as well. +@item +Entire layout of screen (on a per window basis) is exported as a +Lisp API, for visual editing (also very useful for other +purposes e.g. proper handling of word wrapping with proportional +fonts, complex Lisp layout engines e.g. W3) - You can also use @code{intern-soft} to look up a symbol but not create -a new one, and @code{unintern} to remove a symbol from an obarray. This -returns the removed symbol. (Remember: You can't put the symbol back -into any obarray.) Finally, @code{mapatoms} maps over all of the symbols -in an obarray. +@item +Logical, visual, etc. cursor movement handled entirely in Lisp, +using aforementioned API, plus a specifier for controlling how +cursor is shown (e.g. split or not). +@end enumerate -@node Symbol Values -@section Symbol Values -@cindex symbol values -@cindex values, symbol +@node Future Work -- Localized Text/Messages, , Future Work -- BIDI Support, Future Work -- Byte Code Snippets +@subsection Future Work -- Localized Text/Messages +@cindex future work, localized text/messages +@cindex localized text/messages, future work - The value field of a symbol normally contains a Lisp object. However, -a symbol can be @dfn{unbound}, meaning that it logically has no value. -This is internally indicated by storing a special Lisp object, called -@dfn{the unbound marker} and stored in the global variable -@code{Qunbound}. The unbound marker is of a special Lisp object type -called @dfn{symbol-value-magic}. It is impossible for the Lisp -programmer to directly create or access any object of this type. +NOTE: There is existing message translation in X Windows of menu names. +This is handled through X resources. The files are in +@file{PACKAGES/mule-packages/locale/app-defaults/LOCALE/Emacs}, where +@var{locale} is @samp{ja}, @samp{fr}, etc. - @strong{You must not let any ``symbol-value-magic'' object escape to -the Lisp level.} Printing any of these objects will cause the message -@samp{INTERNAL EMACS BUG} to appear as part of the print representation. -(You may see this normally when you call @code{debug_print()} from the -debugger on a Lisp object.) If you let one of these objects escape to -the Lisp level, you will violate a number of assumptions contained in -the C code and make the unbound marker not function right. +See lib-src/make-msgfile.lex. - When a symbol is created, its value field (and function field) are set -to @code{Qunbound}. The Lisp programmer can restore these conditions -later using @code{makunbound} or @code{fmakunbound}, and can query to -see whether the value of function fields are @dfn{bound} (i.e. have a -value other than @code{Qunbound}) using @code{boundp} and -@code{fboundp}. The fields are set to a normal Lisp object using -@code{set} (or @code{setq}) and @code{fset}. +Long comment from jwz, some additions from ben marked "ben": - Other symbol-value-magic objects are used as special markers to -indicate variables that have non-normal properties. This includes any -variables that are tied into C variables (setting the variable magically -sets some global variable in the C code, and likewise for retrieving the -variable's value), variables that magically tie into slots in the -current buffer, variables that are buffer-local, etc. The -symbol-value-magic object is stored in the value cell in place of -a normal object, and the code to retrieve a symbol's value -(i.e. @code{symbol-value}) knows how to do special things with them. -This means that you should not just fetch the value cell directly if you -want a symbol's value. +(much of this comment is outdated, and a lot of it is actually +implemented) - The exact workings of this are rather complex and involved and are -well-documented in comments in @file{buffer.c}, @file{symbols.c}, and -@file{lisp.h}. +@subsection Proposal for How This All Ought to Work -@node Buffers and Textual Representation, MULE Character Sets and Encodings, Symbols and Variables, Top -@chapter Buffers and Textual Representation -@cindex buffers and textual representation -@cindex textual representation, buffers and +Author: @uref{mailto:jwz@@jwz.org,Jamie Zawinski} -@menu -* Introduction to Buffers:: A buffer holds a block of text such as a file. -* The Text in a Buffer:: Representation of the text in a buffer. -* Buffer Lists:: Keeping track of all buffers. -* Markers and Extents:: Tagging locations within a buffer. -* Ibytes and Ichars:: Representation of individual characters. -* The Buffer Object:: The Lisp object corresponding to a buffer. -* Searching and Matching:: Higher-level algorithms. -@end menu +this isn't implemented yet, but this is the plan-in-progress -@node Introduction to Buffers -@section Introduction to Buffers -@cindex buffers, introduction to +In general, it's accepted that the best way to internationalize is for all +messages to be referred to by a symbolic name (or number) and come out of a +table or tables, which are easy to change. - A buffer is logically just a Lisp object that holds some text. -In this, it is like a string, but a buffer is optimized for -frequent insertion and deletion, while a string is not. Furthermore: +However, with Emacs, we've got the task of internationalizing a huge body +of existing code, which already contains messages internally. -@enumerate +For the C code we've got two options: + +@itemize @bullet @item -Buffers are @dfn{permanent} objects, i.e. once you create them, they -remain around, and need to be explicitly deleted before they go away. +Use a Sun-like @code{gettext()} form, which takes an "english" string which +appears literally in the source, and uses that as a hash key to find +a translated string; @item -Each buffer has a unique name, which is a string. Buffers are -normally referred to by name. In this respect, they are like -symbols. +Rip all of the strings out and put them in a table. +@end itemize + +In this case, it's desirable to make as few changes as possible to the C +code, to make it easier to merge the code with the FSF version of emacs +which won't ever have these changes made to it. So we should go with the +former option. + +The way it has been done (between 19.8 and 19.9) was to use @code{gettext()}, but +@strong{also} to make massive changes to the source code. The goal now is to use +@code{gettext()} at run-time and yet not require a textual change to every line +in the C code which contains a string constant. A possible way to do this +is described below. + +(@code{gettext()} can be implemented in terms of @code{catgets()} for non-Sun systems, so +that in itself isn't a problem.) + +For the Lisp code, we've got basically the same options: put everything in +a table, or translate things implicitly. + +Another kink that lisp code introduces is that there are thousands of third- +party packages, so changing the source for all of those is simply not an +option. + +Is it a goal that if some third party package displays a message which is +one we know how to translate, then we translate it? I think this is a +worthy goal. It remains to be seen how well it will work in practice. + +So, we should endeavor to minimize the impact on the lisp code. Certain +primitive lisp routines (the stuff in lisp/prim/, and especially in +@file{cmdloop.el} and @file{minibuf.el}) may need to be changed to know about translation, +but that's an ideologically clean thing to do because those are considered +a part of the emacs substrate. + +However, if we find ourselves wanting to make changes to, say, RMAIL, then +something has gone wrong. (Except to do things like remove assumptions +about the order of words within a sentence, or how pluralization works.) + +There are two parts to the task of displaying translated strings to the +user: the first is to extract the strings which need to be translated from +the sources; and the second is to make some call which will translate those +strings before they are presented to the user. + +The old way was to use the same form to do both, that is, @code{GETTEXT()} was both +the tag that we searched for to build a catalog, and was the form which did +the translation. The new plan is to separate these two things more: the +tags that we search for to build the catalog will be stuff that was in there +already, and the translation will get done in some more centralized, lower +level place. + +This program (@file{make-msgfile.c}) addresses the first part, extracting the +strings. + +For the emacs C code, we need to recognize the following patterns: + +@example + message ("string" ... ) + error ("string") + report_file_error ("string" ... ) + signal_simple_error ("string" ... ) + signal_simple_error_2 ("string" ... ) + + build_translated_string ("string") + #### add this and use it instead of @code{build_string()} in some places. + + yes_or_no_p ("string" ... ) + #### add this instead of funcalling Qyes_or_no_p directly. + + barf_or_query_if_file_exists #### restructure this + check all callers of Fsignal #### restructure these + signal_error (Qerror ... ) #### change all of these to @code{error()} + + And we also parse out the @code{interactive} prompts from @code{DEFUN()} forms. + + #### When we've got a string which is a candidate for translation, we + should ignore it if it contains only format directives, that is, if + there are no alphabetic characters in it that are not a part of a `%' + directive. (Careful not to translate either "%s%s" or "%s: ".) +@end example + +For the emacs Lisp code, we need to recognize the following patterns: + +@example + (message "string" ... ) + (error "string" ... ) + (format "string" ... ) + (read-from-minibuffer "string" ... ) + (read-shell-command "string" ... ) + (y-or-n-p "string" ... ) + (yes-or-no-p "string" ... ) + (read-file-name "string" ... ) + (temp-minibuffer-message "string") + (query-replace-read-args "string" ... ) +@end example + +I expect there will be a lot like the above; basically, any function which +is a commonly used wrapper around an eventual call to @code{message} or +@code{read-from-minibuffer} needs to be recognized by this program. + +@example + (dgettext "domain-name" "string") #### do we still need this? + + things that should probably be restructured: + @code{princ} in @file{cmdloop.el} + @code{insert} in @file{debug.el} + face-interactive + @file{help.el}, @file{syntax.el} all messed up +@end example + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +ben: (format) is a tricky case. If I use format to create a string +that I then send to a file, I probably don't want the string translated. +On the other hand, If the string gets used as an argument to (y-or-n-p) +or some such function, I do want it translated, and it needs to be +translated before the %s and such are replaced. The proper solution +here is for (format) and other functions that call gettext but don't +immediately output the string to the user to add the translated (and +formatted) string as a string property of the object, and have +functions that output potentially translated strings look for a +"translated string" property. Of course, this will fail if someone +does something like + +@example + (y-or-n-p (concat (if you-p "Do you " "Does he ") + (format "want to delete %s? " filename)))) +@end example + +But you shouldn't be doing things like this anyway. + +ben: Also, to avoid excessive translating, strings should be marked +as translated once they get translated, and further calls to gettext +don't do any more translating. Otherwise, a call like + +@example + (y-or-n-p (format "Delete %s? " filename)) +@end example + +would cause translation on both the pre-formatted and post-formatted +strings, which could lead to weird results in some cases (y-or-n-p +has to translate its argument because someone could pass a string to +it directly). Note that the "translating too much" solution outlined +below could be implemented by just marking all strings that don't +come from a .el or .elc file as already translated. + +Menu descriptors: one way to extract the strings in menu labels would be +to teach this program about "^(defvar .*menu\n" forms; that's probably +kind of hard, though, so perhaps a better approach would be to make this +program recognize lines of the form + +@example + "string" ... ;###translate +@end example + +where the magic token ";###translate" on a line means that the string +constant on this line should go into the message catalog. This is analogous +to the magic ";###autoload" comments, and to the magic comments used in the +EPSF structuring conventions. + +----- +So this program manages to build up a catalog of strings to be translated. +To address the second part of the problem, of actually looking up the +translations, there are hooks in a small number of low level places in +emacs. + +Assume the existence of a C function gettext(str) which returns the +translation of @var{str} if there is one, otherwise returns @var{str}. + +@itemize @bullet @item -Buffers have a default insertion position, called @dfn{point}. -Inserting text (unless you explicitly give a position) goes at point, -and moves point forward past the text. This is what is going on when -you type text into Emacs. +@code{message()} takes a char* as its argument, and always filters it through +@code{gettext()} before displaying it. + @item -Buffers have lots of extra properties associated with them. +errors are printed by running the lisp function @code{display-error} which +doesn't call @code{message} directly (it princ's to streams), so it must be +carefully coded to translate its arguments. This is only a few lines +of code. + @item -Buffers can be @dfn{displayed}. What this means is that there -exist a number of @dfn{windows}, which are objects that correspond -to some visible section of your display, and each window has -an associated buffer, and the current contents of the buffer -are shown in that section of the display. The redisplay mechanism -(which takes care of doing this) knows how to look at the -text of a buffer and come up with some reasonable way of displaying -this. Many of the properties of a buffer control how the -buffer's text is displayed. +@code{Fread_minibuffer_internal()} is the lowest level interface to all minibuf +interactions, so it is responsible for translating the value that will go +into Vminibuf_prompt. + @item -One buffer is distinguished and called the @dfn{current buffer}. It is -stored in the variable @code{current_buffer}. Buffer operations operate -on this buffer by default. When you are typing text into a buffer, the -buffer you are typing into is always @code{current_buffer}. Switching -to a different window changes the current buffer. Note that Lisp code -can temporarily change the current buffer using @code{set-buffer} (often -enclosed in a @code{save-excursion} so that the former current buffer -gets restored when the code is finished). However, calling -@code{set-buffer} will NOT cause a permanent change in the current -buffer. The reason for this is that the top-level event loop sets -@code{current_buffer} to the buffer of the selected window, each time -it finishes executing a user command. -@end enumerate +Fpopup_menu filters the menu titles through @code{gettext()}. - Make sure you understand the distinction between @dfn{current buffer} -and @dfn{buffer of the selected window}, and the distinction between -@dfn{point} of the current buffer and @dfn{window-point} of the selected -window. (This latter distinction is explained in detail in the section -on windows.) +The above take care of 99% of all messages the user ever sees. -@node The Text in a Buffer -@section The Text in a Buffer -@cindex text in a buffer, the -@cindex buffer, the text in a +@item +The lisp function temp-minibuffer-message translates its arg. - The text in a buffer consists of a sequence of zero or more -characters. A @dfn{character} is an integer that logically represents -a letter, number, space, or other unit of text. Most of the characters -that you will typically encounter belong to the ASCII set of characters, -but there are also characters for various sorts of accented letters, -special symbols, Chinese and Japanese ideograms (i.e. Kanji, Katakana, -etc.), Cyrillic and Greek letters, etc. The actual number of possible -characters is quite large. +@item +query-replace-read-args is funny; it does + (setq from (read-from-minibuffer (format "%s: " string) ... )) + (setq to (read-from-minibuffer (format "%s %s with: " string from) ... )) +@end itemize - For now, we can view a character as some non-negative integer that -has some shape that defines how it typically appears (e.g. as an -uppercase A). (The exact way in which a character appears depends on the -font used to display the character.) The internal type of characters in -the C code is an @code{Ichar}; this is just an @code{int}, but using a -symbolic type makes the code clearer. +What should we do about this? We could hack query-replace-read-args to +translate its args, but might this be a more general problem? I don't +think we ought to translate all calls to format. We could just change +the calling sequence, since this is odd in that the first %s wants to be +translated but the second doesn't. - Between every character in a buffer is a @dfn{buffer position} or -@dfn{character position}. We can speak of the character before or after -a particular buffer position, and when you insert a character at a -particular position, all characters after that position end up at new -positions. When we speak of the character @dfn{at} a position, we -really mean the character after the position. (This schizophrenia -between a buffer position being ``between'' two characters and ``on'' a -character is rampant in Emacs.) +Solving the "translating too much" problem: - Buffer positions are numbered starting at 1. This means that -position 1 is before the first character, and position 0 is not -valid. If there are N characters in a buffer, then buffer -position N+1 is after the last one, and position N+2 is not valid. +The concern has been raised that in this situation: - The internal makeup of the Ichar integer varies depending on whether -we have compiled with MULE support. If not, the Ichar integer is an -8-bit integer with possible values from 0 - 255. 0 - 127 are the -standard ASCII characters, while 128 - 255 are the characters from the -ISO-8859-1 character set. If we have compiled with MULE support, an -Ichar is a 19-bit integer, with the various bits having meanings -according to a complex scheme that will be detailed later. The -characters numbered 0 - 255 still have the same meanings as for the -non-MULE case, though. +@itemize @bullet +@item +"Help" is a string for which we know a translation; +@item +someone visits a file called Help, and someone does something +contrived like (error buffer-file-name) +@end itemize - Internally, the text in a buffer is represented in a fairly simple -fashion: as a contiguous array of bytes, with a @dfn{gap} of some size -in the middle. Although the gap is of some substantial size in bytes, -there is no text contained within it: From the perspective of the text -in the buffer, it does not exist. The gap logically sits at some buffer -position, between two characters (or possibly at the beginning or end of -the buffer). Insertion of text in a buffer at a particular position is -always accomplished by first moving the gap to that position -(i.e. through some block moving of text), then writing the text into the -beginning of the gap, thereby shrinking the gap. If the gap shrinks -down to nothing, a new gap is created. (What actually happens is that a -new gap is ``created'' at the end of the buffer's text, which requires -nothing more than changing a couple of indices; then the gap is -``moved'' to the position where the insertion needs to take place by -moving up in memory all the text after that position.) Similarly, -deletion occurs by moving the gap to the place where the text is to be -deleted, and then simply expanding the gap to include the deleted text. -(@dfn{Expanding} and @dfn{shrinking} the gap as just described means -just that the internal indices that keep track of where the gap is -located are changed.) +then we would display the translation of Help, which would not be correct. +We can solve this by adding a bit to Lisp_String objects which identifies +them as having been read as literal constants from a .el or .elc file (as +opposed to having been constructed at run time as it would in the above +case.) To solve this: - Note that the total amount of memory allocated for a buffer text never -decreases while the buffer is live. Therefore, if you load up a -20-megabyte file and then delete all but one character, there will be a -20-megabyte gap, which won't get any smaller (except by inserting -characters back again). Once the buffer is killed, the memory allocated -for the buffer text will be freed, but it will still be sitting on the -heap, taking up virtual memory, and will not be released back to the -operating system. (However, if you have compiled XEmacs with rel-alloc, -the situation is different. In this case, the space @emph{will} be -released back to the operating system. However, this tends to result in a -noticeable speed penalty.) +@itemize @bullet +@item +@code{Fmessage()} takes a lisp string as its first argument. +If that string is a constant, that is, was read from a source file +as a literal, then it calls @code{message()} with it, which translates. +Otherwise, it calls @code{message_no_translate()}, which does not translate. - Astute readers may notice that the text in a buffer is represented as -an array of @emph{bytes}, while (at least in the MULE case) an Ichar is -a 19-bit integer, which clearly cannot fit in a byte. This means (of -course) that the text in a buffer uses a different representation from -an Ichar: specifically, the 19-bit Ichar becomes a series of one to -four bytes. The conversion between these two representations is complex -and will be described later. +@item +@code{Ferror()} (actually, @code{Fsignal()} when condition is Qerror) works similarly. +@end itemize + +More specifically, we do: + +@quotation + Scan specified C and Lisp files, extracting the following messages: - In the non-MULE case, everything is very simple: An Ichar -is an 8-bit value, which fits neatly into one byte. +@example + C files: + GETTEXT (...) + DEFER_GETTEXT (...) + DEFUN interactive prompts + Lisp files: + (gettext ...) + (dgettext "domain-name" ...) + (defer-gettext ...) + (interactive ...) +@end example + +The arguments given to this program are all the C and Lisp source files +of GNU Emacs. .el and .c files are allowed. There is no support for .elc +files at this time, but they may be specified; the corresponding .el file +will be used. Similarly, .o files can also be specified, and the corresponding +.c file will be used. This helps the makefile pass the correct list of files. + +The results, which go to standard output or to a file specified with -a or -o +(-a to append, -o to start from nothing), are quoted strings wrapped in +gettext(...). The results can be passed to xgettext to produce a .po message +file. - If we are given a buffer position and want to retrieve the -character at that position, we need to follow these steps: +However, we also need to do the following: @enumerate @item -Pretend there's no gap, and convert the buffer position into a @dfn{byte -index} that indexes to the appropriate byte in the buffer's stream of -textual bytes. By convention, byte indices begin at 1, just like buffer -positions. In the non-MULE case, byte indices and buffer positions are -identical, since one character equals one byte. +Definition of Arg below won't handle a generalized argument +as might appear in a function call. This is fine for DEFUN +and friends, because only simple arguments appear there; but +it might run into problems if Arg is used for other sorts +of functions. @item -Convert the byte index into a @dfn{memory index}, which takes the gap -into account. The memory index is a direct index into the block of -memory that stores the text of a buffer. This basically just involves -checking to see if the byte index is past the gap, and if so, adding the -size of the gap to it. By convention, memory indices begin at 1, just -like buffer positions and byte indices, and when referring to the -position that is @dfn{at} the gap, we always use the memory position at -the @emph{beginning}, not at the end, of the gap. +@code{snarf()} should be modified so that it doesn't output null +strings and non-textual strings (see the comment at the top +of @file{make-msgfile.c}). @item -Fetch the appropriate bytes at the determined memory position. +parsing of (insert) should snarf all of the arguments. @item -Convert these bytes into an Ichar. -@end enumerate - - In the non-Mule case, (3) and (4) boil down to a simple one-byte -memory access. - - Note that we have defined three types of positions in a buffer: - -@enumerate +need to add set-keymap-prompt and deal with gettext of that. @item -@dfn{buffer positions} or @dfn{character positions}, typedef @code{Charbpos} +parsing of arguments should snarf all strings anywhere within +the arguments, rather than just looking for a string as the +argument. This allows if statements as arguments to get parsed. @item -@dfn{byte indices}, typedef @code{Bytebpos} +@code{begin_paren_counting()} et al. should handle recursive entry. @item -@dfn{memory indices}, typedef @code{Membpos} +handle set-window-buffer and other such functions that take +a buffer as the other-than-first argument. +@item +there is a fair amount of work to be done on the C code. +Look through the code for #### comments associated with +'#ifdef I18N3' or with an I18N3 nearby. +@item +Deal with @code{get-buffer-process} et al. +@item +Many of the changes in the Lisp code marked +'rewritten for I18N3 snarfing' should be undone once (5) is +implemented. +@item +Go through the Lisp code in prim and make sure that all +strings are gettexted as necessary. This may reveal more +things to implement. +@item +Do the equivalent of (8) for the Lisp code. +@item +Deal with parsing of menu specifications. @end enumerate +@end quotation - All three typedefs are just @code{int}s, but defining them this way makes -things a lot clearer. +@node Future Work -- Lisp Stream API, Future Work -- Multiple Values, Future Work -- Byte Code Snippets, Future Work +@section Future Work -- Lisp Stream API +@cindex future work, Lisp stream API +@cindex Lisp stream API, future work - Most code works with buffer positions. In particular, all Lisp code -that refers to text in a buffer uses buffer positions. Lisp code does -not know that byte indices or memory indices exist. +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} - Finally, we have a typedef for the bytes in a buffer. This is a -@code{Ibyte}, which is an unsigned char. Referring to them as -Ibytes underscores the fact that we are working with a string of bytes -in the internal Emacs buffer representation rather than in one of a -number of possible alternative representations (e.g. EUC-encoded text, -etc.). +Expose XEmacs internal lstreams to Lisp as stream objects. (In +addition to the functions given below, each stream object has +properties that can be associated with it using the standard put, get +etc. API. For GNU Emacs, where put and get have not been extended to +be general property functions, but work only on strings, we would have +to create functions set-stream-property, stream-property, +remove-stream-property, and stream-properties. These provide the same +functionality as the generic get, put, remprop, and object-plist +functions under XEmacs) -@node Buffer Lists -@section Buffer Lists -@cindex buffer lists +(Implement properties using a hash table, and @strong{generalize} this so +that it is extremely easy to add a property interface onto any kind +of object) - Recall earlier that buffers are @dfn{permanent} objects, i.e. that -they remain around until explicitly deleted. This entails that there is -a list of all the buffers in existence. This list is actually an -assoc-list (mapping from the buffer's name to the buffer) and is stored -in the global variable @code{Vbuffer_alist}. +@example +(write-stream STREAM STRING) +@end example - The order of the buffers in the list is important: the buffers are -ordered approximately from most-recently-used to least-recently-used. -Switching to a buffer using @code{switch-to-buffer}, -@code{pop-to-buffer}, etc. and switching windows using -@code{other-window}, etc. usually brings the new current buffer to the -front of the list. @code{switch-to-buffer}, @code{other-buffer}, -etc. look at the beginning of the list to find an alternative buffer to -suggest. You can also explicitly move a buffer to the end of the list -using @code{bury-buffer}. +Write the STRING to the STREAM. This will signal an error if all the +bytes cannot be written. - In addition to the global ordering in @code{Vbuffer_alist}, each frame -has its own ordering of the list. These lists always contain the same -elements as in @code{Vbuffer_alist} although possibly in a different -order. @code{buffer-list} normally returns the list for the selected -frame. This allows you to work in separate frames without things -interfering with each other. +@example +(read-stream STREAM &optional N SEQUENCE) +@end example - The standard way to look up a buffer given a name is -@code{get-buffer}, and the standard way to create a new buffer is -@code{get-buffer-create}, which looks up a buffer with a given name, -creating a new one if necessary. These operations correspond exactly -with the symbol operations @code{intern-soft} and @code{intern}, -respectively. You can also force a new buffer to be created using -@code{generate-new-buffer}, which takes a name and (if necessary) makes -a unique name from this by appending a number, and then creates the -buffer. This is basically like the symbol operation @code{gensym}. +Reads data from STREAM. N specifies the number of bytes or +characters, depending on the stream. SEQUENCE specifies where to +write the data into. If N is not specified, data is read until end of +file. If SEQUENCE is not specified, the data is returned as a stream. +If SEQUENCE is specified, the SEQUENCE must be large enough to hold +the data. -@node Markers and Extents -@section Markers and Extents -@cindex markers and extents -@cindex extents, markers and +@example +(push-stream-marker STREAM) +@end example - Among the things associated with a buffer are things that are -logically attached to certain buffer positions. This can be used to -keep track of a buffer position when text is inserted and deleted, so -that it remains at the same spot relative to the text around it; to -assign properties to particular sections of text; etc. There are two -such objects that are useful in this regard: they are @dfn{markers} and -@dfn{extents}. + returns ID, probably a stream marker object - A @dfn{marker} is simply a flag placed at a particular buffer -position, which is moved around as text is inserted and deleted. -Markers are used for all sorts of purposes, such as the @code{mark} that -is the other end of textual regions to be cut, copied, etc. +@example +(pop-stream-marker STREAM) +@end example - An @dfn{extent} is similar to two markers plus some associated -properties, and is used to keep track of regions in a buffer as text is -inserted and deleted, and to add properties (e.g. fonts) to particular -regions of text. The external interface of extents is explained -elsewhere. + backs up stream to last marker - The important thing here is that markers and extents simply contain -buffer positions in them as integers, and every time text is inserted or -deleted, these positions must be updated. In order to minimize the -amount of shuffling that needs to be done, the positions in markers and -extents (there's one per marker, two per extent) are stored in Membpos's. -This means that they only need to be moved when the text is physically -moved in memory; since the gap structure tries to minimize this, it also -minimizes the number of marker and extent indices that need to be -adjusted. Look in @file{insdel.c} for the details of how this works. +@example +(unread-stream STREAM STRING) +@end example - One other important distinction is that markers are @dfn{temporary} -while extents are @dfn{permanent}. This means that markers disappear as -soon as there are no more pointers to them, and correspondingly, there -is no way to determine what markers are in a buffer if you are just -given the buffer. Extents remain in a buffer until they are detached -(which could happen as a result of text being deleted) or the buffer is -deleted, and primitives do exist to enumerate the extents in a buffer. +The only valid STREAM is an input stream in which case the data in +STRING is pushed back and will be read ahead of all other data. In +general, there is no limit to the amount of data that can be unread or +the number of times that unread-stream can be called before another +read. -@node Ibytes and Ichars -@section Ibytes and Ichars -@cindex Ibytes and Ichars -@cindex Ichars, Ibytes and +@example +(stream-available-chars STREAM) +@end example - Not yet documented. +This returns the number of characters (or bytes) that can definitely +be read from the screen without an error. This can be useful, for +example, when dealing with non-blocking streams when an attempt to +read too much data will result in a blocking error. -@node The Buffer Object -@section The Buffer Object -@cindex buffer object, the -@cindex object, the buffer +@example +(stream-seekable-p STREAM) +@end example - Buffers contain fields not directly accessible by the Lisp programmer. -We describe them here, naming them by the names used in the C code. -Many are accessible indirectly in Lisp programs via Lisp primitives. +Returns true if the stream is seekable. If false, operations such as +seek-stream and stream-position will signal an error. However, the +functions set-stream-marker and seek-stream-marker will still succeed +for an input stream. + +@example +(stream-position STREAM) +@end example + +If STREAM is a seekable stream, returns a position which can be passed +to seek-stream. + +@example +(seek-stream STREAM N) +@end example + +If STREAM is a seekable stream, move to the position indicated by N, +otherwise signal an error. + +@example +(set-stream-marker STREAM) +@end example + +If STREAM is an input stream, create a marker at the current position, +which can later be moved back to. The stream does not need to be a +seekable stream. In this case, all successive data will be buffered +to simulate the effect of a seekable stream. Therefore use this +function with care. + +@example +(seek-stream-marker STREAM marker) +@end example + +Move the stream back to the position that was stored in the marker +object. (this is generally an opaque object of type stream-marker). + +@example +(delete-stream-marker MARKER) +@end example + +Destroy the stream marker and if the stream is a non-seekable stream +and there are no other stream markers pointing to an earlier position, +frees up some buffering information. + +@example +(delete-stream STREAM N) +@end example + +@example +(delete-stream-marker STREAM ID) +@end example + +@example +(close-stream stream) +@end example + +Writes any remaining data to the stream and closes it and the object +to which it's attached. This also happens automatically when the +stream is garbage collected. + +@example +(getchar-stream STREAM) +@end example + +Return a single character from the stream. (This may be a single byte +depending on the nature of the stream). This is actually a macro with +an extremely efficient implementation (as efficient as you can get in +Emacs Lisp), so that this can be used without fear in a loop. The +implementation works by reading a large amount of data into a vector +and then simply using the function AREF to read characters one by one +from the vector. Because AREF is one of the primitives handled +specially by the byte interpreter, this will be very efficient. The +actual implementation may in fact use the function +call-with-condition-handler to avoid the necessity of checking for +overflow. Its typical implementation is to fetch the vector +containing the characters as a stream property, as well as the index +into that vector. Then it retrieves the character and increments the +value and stores it back in the stream. As a first implementation, we +check to see when we are reading the character whether the character +would be out of range. If so, we read another 4096 characters, +storing them into the same vector, setting the index back to the +beginning, and then proceeding with the rest of the getchar algorithm. + +@example +(putchar-stream STREAM CHAR) +@end example + +This is similar to getchar-stream but it writes data instead of +reading data. + +@example +Function make-stream +@end example + +There are actually two stream-creation functions, which are: + +@example +(make-input-stream TYPE PROPERTIES) +(make-output-stream TYPE PROPERTIES) +@end example + +These can be used to create a stream that reads data, or writes data, +respectively. PROPERTIES is a property list and the allowable +properties in it are defined by the type. Possible types are: + +@enumerate +@item +@code{file} (this reads data from a file or writes to a file) + +Allowable properties are: @table @code -@item name -The buffer name is a string that names the buffer. It is guaranteed to -be unique. @xref{Buffer Names,,, lispref, XEmacs Lisp Reference -Manual}. +@item :file-name +(the name of the file) -@item save_modified -This field contains the time when the buffer was last saved, as an -integer. @xref{Buffer Modification,,, lispref, XEmacs Lisp Reference -Manual}. +@item :create +(for output streams only, creates the file if it doesn't +already exist) + +@item :exclusive +(for output streams only, fails if the file already +exists) + +@item :append +(for output streams only; starts appending to the end +of the file rather than overwriting the file) + +@item :offset +(positions in bytes in the file where reading or writing +should begin. If unspecified, defaults to the beginning of the +file or to the end of the file when :appended specified) + +@item :count +(for input streams only, the number of bytes to read from +the file before signaling "end of file". If nil or omitted, the +number of bytes is unlimited) + +@item :non-blocking +(if true, reads or writes will fail if the operation +would block. This only makes sense for non-regular files). +@end table -@item modtime -This field contains the modification time of the visited file. It is -set when the file is written or read. Every time the buffer is written -to the file, this field is compared to the modification time of the -file. @xref{Buffer Modification,,, lispref, XEmacs Lisp Reference -Manual}. +@item +@code{process} (For output streams only, send data to a process.) -@item auto_save_modified -This field contains the time when the buffer was last auto-saved. +Allowable properties are: -@item last_window_start -This field contains the @code{window-start} position in the buffer as of -the last time the buffer was displayed in a window. +@table @code +@item :process +(the process object) +@end table -@item undo_list -This field points to the buffer's undo list. @xref{Undo,,, lispref, -XEmacs Lisp Reference Manual}. +@item +@code{buffer} (Read from or write to a buffer.) -@item syntax_table_v -This field contains the syntax table for the buffer. @xref{Syntax -Tables,,, lispref, XEmacs Lisp Reference Manual}. +Allowable properties are: -@item downcase_table -This field contains the conversion table for converting text to lower -case. @xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}. +@table @code +@item :buffer +(the name of the buffer or the buffer object.) -@item upcase_table -This field contains the conversion table for converting text to upper -case. @xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}. +@item :start +(the position to start reading from or writing to. If nil, +use the buffer point. If true, use the buffer's point and move +point beyond the end of the data read or written.) + +@item :end +(only for input streams, the position to stop reading at. If +nil, continue to the end of the buffer.) + +@item :ignore-accessible +(if true, the default for :start and :end +ignore any narrowing of the buffer.) +@end table -@item case_canon_table -This field contains the conversion table for canonicalizing text for -case-folding search. @xref{Case Tables,,, lispref, XEmacs Lisp -Reference Manual}. +@item +@code{stream} (read from or write to a lisp stream) -@item case_eqv_table -This field contains the equivalence table for case-folding search. -@xref{Case Tables,,, lispref, XEmacs Lisp Reference Manual}. +Allowable properties are: + +@table @code +@item :stream +(the stream object) + +@item :offset +(the position to begin to be reading from or writing to) + +@item :length +(For input streams only, the amount of data to read, +defaulting to the rest of the data in the string. Revise string +for output streams only if true, the stream is resized as +necessary to accommodate data written off the end, otherwise the +writes will fail. +@end table + +@item +@code{memory} (For output only, writes data to an internal memory +buffer. This is more lightweight than using a Lisp buffer. The +function memory-stream-string can be used to convert the memory +into a string.) + +@item +@code{debugging} (For output streams only, write data to the debugging +output.) + +@item +@code{stream-device} (During non-interactive invocations only, Read +from or write to the initial stream terminal device.) + +@item +@code{function} (For output streams only, send data by calling a +function, exactly as with the STREAM argument to the print +primitive.) + +Allowable Properties are: + +@table @code +@item :function +(the function to call. The function is called with one +argument, the stream.) +@end table + +@item +@code{marker} (Write data to the location pointed to by a marker and +move the marker past the data.) + +Allowable properties are: + +@table @code +@item :marker +(the marker object.) +@end table -@item display_table -This field contains the buffer's display table, or @code{nil} if it -doesn't have one. @xref{Display Tables,,, lispref, XEmacs Lisp -Reference Manual}. +@item +@code{decoding} (As an input stream, reads data from another stream and +decodes it according to a coding system. As an output stream +decodes the data written to it according to a coding system and +then writes results in another stream.) -@item markers -This field contains the chain of all markers that currently point into -the buffer. Deletion of text in the buffer, and motion of the buffer's -gap, must check each of these markers and perhaps update it. -@xref{Markers,,, lispref, XEmacs Lisp Reference Manual}. +Properties are: -@item backed_up -This field is a flag that tells whether a backup file has been made for -the visited file of this buffer. +@table @code +@item :coding-system +(the symbol of coding system object, which defines the +decoding.) -@item mark -This field contains the mark for the buffer. The mark is a marker, -hence it is also included on the list @code{markers}. @xref{The Mark,,, -lispref, XEmacs Lisp Reference Manual}. +@item :stream +(the stream on the other end.) +@end table -@item mark_active -This field is non-@code{nil} if the buffer's mark is active. +@item +@code{encoding} (As an input stream, reads data from another stream and +encodes it according to a coding system. As an output stream +encodes the data written to it according to a coding system and +then writes results in another stream.) -@item local_var_alist -This field contains the association list describing the variables local -in this buffer, and their values, with the exception of local variables -that have special slots in the buffer object. (Those slots are omitted -from this table.) @xref{Buffer-Local Variables,,, lispref, XEmacs Lisp -Reference Manual}. +Properties are: -@item modeline_format -This field contains a Lisp object which controls how to display the mode -line for this buffer. @xref{Modeline Format,,, lispref, XEmacs Lisp -Reference Manual}. +@table @code +@item :coding-system +(the symbol of coding system object, which defines the +encoding.) -@item base_buffer -This field holds the buffer's base buffer (if it is an indirect buffer), -or @code{nil}. +@item :stream +(the stream on the other end.) @end table +@end enumerate -@node Searching and Matching -@section Searching and Matching -@cindex searching -@cindex matching +Consider -Very incomplete, limited to a brief introduction. +@example +(define-stream-type 'type + :read-function + :write-function + :rewind- + :seek- + :tell- + (?:buffer) +@end example + +Old Notes: + +Expose lstreams as hash (put get etc. properties) table. + +@example + (write-stream stream string) + (read-stream stream &optional n sequence) + (make-stream ...) + (push-stream-marker stream) + returns ID prob a stream marker object + (pop-stream-marker stream) + backs up stream to last marker + (unread-stream stream string) + (stream-available-chars stream) + (seek-stream stream n) + (delete-stream stream n) + (delete-stream-marker stream ic) can always be poe only nested if you + have set stream marker + + (get-char-stream @strong{generalizes} stream) + + a macro that tries to be efficient perhaps by reading the next + e.g. 512 characters into a vector and arefing them. Might check aref + optimization for vectors in the byte interpreter. + + (make-stream 'process :process ... :type write) + + Consider + + (define-stream-type 'type + :read-function + :write-function + :rewind- + :seek- + :tell- + (?:buffer) +@end example + +@node Future Work -- Multiple Values, Future Work -- Macros, Future Work -- Lisp Stream API, Future Work +@section Future Work -- Multiple Values +@cindex future work, multiple values +@cindex multiple values, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +On low level, all funs that can return multiple values are defined +with DEFUN_MULTIPLE_VALUES and have an extra parameter, a struct +mv_context *. + +It has to be this way to ensure that only the fun itself, and no called +funs, think they're called in an mv context. + +apply, funcall, eval might propagate their mv context to their +children? + +Might need eval-mv to implement calling a fun in an mv context. Maybe +also funcall_mv? apply_mv? + +Generally, just set up context appropriately. Call fun (noticing +whether it's an mv-aware fun) and binding values on the way back or +passing them out. (e.g. to multiple-value-bind) + +@subheading Common Lisp multiple values, required for specifier improvements. + +The multiple return values from get-specifier should allow the +specifier value to be modified in the correct fashion (i.e. should +interact correctly with all manner of changes from other callers) +using set-specifier. We should check this and see if we need other +return values. (how-to-add? inst-list?) + +In C, call multiple-values-context to get number of expected values, +and multiple-value-set (#, value) to get values other than the first. + +(Returns Qno_value, or something, if there are no values. + +#### Or should throw? Probably not. +#### What happens if a fn returns no values but the caller expects a +#### value? + +Something like @code{funcall_with_multiple_values()} for setting up the +context. + +For efficiency, byte code could notice Ffuncall to m.v. functions and +sub in special opcodes during load in processing, if it mattered. + +@node Future Work -- Macros, Future Work -- Specifiers, Future Work -- Multiple Values, Future Work +@section Future Work -- Macros +@cindex future work, macros +@cindex macros, future work -People find the searching and matching code difficult to understand. -And indeed, the details are hard. However, the basic structures are not -so complex. First, there's a hard question with a simple answer. What -about Mule? The answer here is that it turns out that Mule characters -can be matched byte by byte, so neither the search code nor the regular -expression code need take much notice of it at all! Of course, we add -some special features (such as regular expressions that match only -certain charsets), but these do not require new concepts. The main -exception is that wild-card matches in Mule have to be careful to -swallow whole characters. This is handled using the same basic macros -that are used for buffer and string movements. +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} -This will also be true if a UTF-8 representation is used for the -internal encoding. +@enumerate +@item +Option to control whether beep really kills a macro execution. +@item +Recently defined macros are remembered on a stack, so accidentally +defining another one doesn't fuck you up. You can "rotate" +anonymous macros or just pick one (numbered) to put on tags, so it +works with execute macro - menu shows the anonymous macro, and +lists some keystrokes. Normally numbered but you can easily assign +to named fun or to keyboard sequence or give it a number (or give +it a letter accelerator?) +@end enumerate -The complex algorithms for searching are for simple string searches. In -particular, the algorithm used for fast string searching is Boyer-Moore. -This algorithm is based on the idea that if you have a mismatch at a -given position, you can precompute where to restart the search. This -typically means that you can often make many fewer than N character -comparisons, where N is the position at which the match is found, or the -size of the text if it contains no match. That's fast! But it's not -easy. You must ``compile'' the search string into a jump table. See -the source, @file{search.c}, for more information. +@node Future Work -- Specifiers, Future Work -- Display Tables, Future Work -- Macros, Future Work +@section Future Work -- Specifiers +@cindex future work, specifiers +@cindex specifiers, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@subheading Ideas To Work On When Their Time Has Come + +@itemize +@item +specifier-instance returns additional params (multiple-value) - the instantiator +used, the associated tag set, the locale found in, a code that can +be passed in as an additional param RESTART to restart an +instantiation process, e.g. to allow an instantiator to "inherit" +from another one higher up. Also, domain can be 'global (look only +in global specs) or "complex" - a list of the actual locales to look +in (e.g. a buffer - frame - a device - 'global) + +@item +pragmatic-specifier-domain (locale) +Converts a locale into a domain in a way that's "pragmatic" - does +what most users expect will happen, but is not clean. In +particular, handling of "buffer" requires trickiness, as mentioned +before. -Emacs changes the basic algorithms somewhat in order to handle -case-insensitive searches without a full-blown regular expression. +@item +ensure-instantiator-exists (specifier locale) +Ensures an actual instantiator exists in a locale, so that it can +later be futzed with. If none exists, one is constructed by first +calling pragmatic-specifier domain and then specifier-instance and +fetching out the instantiator for this call. + +@item +map-modifying-instantiators (specifier fun &optional locale tag-set) +Same args as map-specifier, but use the return value from the fun to +replace the instantiator. Called with three args (instantiator +locale tag-set) + +@item +map-modifying-instantiators-force (specifier fun &optional locale tag-set) +Same as previous, but calls ensure-instantiator-exists on each +locale before processing. +@end itemize -Regular expressions, on the other hand, have a trivial search -implementation: try a match at each position. (Under POSIX rules, it's -a bit more complex, because POSIX requires that you find the -@emph{longest} match in the text. This means you keep a record of the -best match so far, and find all the matches.) +NOTE: Can do preliminary implementation without Multiple Values - +instead create fun specifier-instance - that returns a list (and will +be deleted at some point) -The matching code for regular expressions is quite complex. First, the -regular expression itself is compiled. There are two basic approaches -that could be taken. The first is to compile the expression into tables -to drive a generic finite automaton emulator. This is the approach -given in many textbooks (Sedgewick's @emph{Algorithms} and Aho, Sethi, -and Ullmann's @emph{Compilers: Principles, Techniques, and Tools}, aka -``The Dragon Book'') as well as being used by the @file{lex} family of -lexical analysis engines. +@subheading specifier &c changes for glyphs -Emacs uses a somewhat different technique. The expression is compiled -into a form of bytecode, which is interpreted by a special interpreter. -The interpreter itself basically amounts to an inline implementation of -the finite automaton emulator. The advantage of this technique is that -it's easier to add special features, such as control of case-sensitivity -via a global variable. +@enumerate +@item +@itemize @bullet +@item +resizable vectors with funs to insert, delete elements (elements +shift accordingly) +@item +gap array vectors as an implementation of resizing vectors. +@end itemize -The compiler is not treated here. See the source, @file{regex.c}. The -interpreter, although it is divided into several functions, and looks -fearsomely complex, is actually quite simple in concept. However, -basically what you're doing there is a strcmp on steroids, right? +@item +You can @code{put} @code{get}, etc. on vectors to modify properties within +them. -@example -int -strcmp (char *p, /* pattern pointer */ - char *b) /* buffer pointer */ -@{ - while (*p++ == *b++) - ; - return *(--p) - *(--b); /* oops, we overshot */ -@} -@end example +@item +copy-over routines +routines that carefully copy one complex item OVER another one, +destroying the second in the process. I wrote one for lists. Need +a general copy-over-tree. -Really, it's no harder than that. (A bit of a white lie, OK?) +@item +improvement to specifier mapping routines e.g. -How does the regexp code generalize this? +map-modifying-instantiator and its force versions below, so that we +could implement in turns. -@enumerate @item -Depending on the pattern, @code{*b} may have a general relationship to -@code{*p}. @emph{I.e.}, direct comparison against @code{*p} is -generalized to include checks for set membership, and context dependent -properties. This depends on @code{&*b}. Of course that's meaningless -in C, so we use @code{b} directly, instead. +put-specifier-property (specifier which finds the key, value +instantiator in the locale, &opt locale possibly creating one +tag-set) if necessary and goes into the vector, changes it, and +puts it back into the specifier. @item -Although to ensure the algorithm terminates, @code{b} must advance step -by step, @code{p} can branch and jump. +Smarter add-spec-to-specifier + +If it notices that it's just replacing one instantiator with +another, instead of just copy-tree the first one and throw away the +other, use copy-over-tree to save lots of garbage when repeatedly +called. + +ILLEGIBLE: GOTO LOO BUI BUGS LAST PNOTE @item -The information returned is much greater, including information about -subexpressions. +When at image instantiate: +@itemize @bullet +@item +Some properties in the instantiators could be implemented through +dynamically modifying an existing image instance (e.g. when the +value of a slider or progress bar or text in a text field +changes). So when we hash, we only hash the part of the +instantiator that cannot be dynamically modified (We might need +to do something tricky here - allowing a :key property in hash +tables or @strong{ILLEGIBLE}). Anyway, so we need to generate an image +instance, and we mask off the dynamic properties and look up in +our hash table, and we get something back! But is it ours to +modify? (We already checked to see it wasn't exactly the same +dynamic properties that it had) Thus --- +@end itemize + +@item +Reference counting. Somehow or other, each image instance in the +cache needs to keep track of the instantiators that generated it. @end enumerate -We'll ignore (3). (2) is mostly interesting when compiling the regular -expression. Now we have +It might do this through some sort of special instantiator-reference +object. This points to the instantiator, where in the hierarchy the +instantiator is etc. When an instantiator gets removed, this +gu*ILLEGIBLE* values report not attached. Somehow that gets +communicated back to the image instance in the cache. So somehow or +other, the image instance in the cache knows who's using them and so +when you go and keep updating the slider value, by simply modifying an +instantiator, which efficiently changes the internal structure of this +specifier - eventually image instantiate notices that the image +instance it points has no other user and just modifiers it, but in +complex situations, some optimizations get lost, but everything is +still correct. -@example -@group -enum operator_t @{ - accept = 0, - exact, - any, - range, - group, /* actually, these are probably */ - repeat, /* turned into conditional code */ - /* etc */ -@}; -@end group +vs. -@group -enum status_t @{ - working = 0, - matched, - mismatch, - end_of_buffer, - error - @}; -@end group +Andy's set-image-instance-property, which achieves the same +optimizations much more easily, but -@group -struct pattern @{ - enum operator_t operator; - char char_value; - boolean range_table[256]; - /* etc, etc */ - @}; -@end group +@enumerate +@item +falls apart in any more complicated system -@group -char *p, /* pattern pointer */ - *b; /* buffer pointer */ +@item +only works because of the way the caching system in XEmacs works. +Any change (e.g. @strong{ILLEGIBLE} more of making the caches GQ instead +of GQ) is likely to make things stop working right in all but the +simplest situation. +@end enumerate -enum status_t -match (struct pattern *p, char *b) -@{ - enum status_t done = working; +@subheading Specifier improvements for support of specifier inheritance (necessary for the new font mapping API) - while (!(done = match_1_operator (p, b))) - @{ - struct pattern *p1 = p; - p = next_p (p, b); - b = next_b (p1, b); - @} - return done; -@} -@end group +'Fallback should be a locale/domain. + +@example +(get-specifier specifier &optional locale) + +#### If locale is omitted, should it be (current-buffer) or 'global? +#### Should argument not be optional? @end example -This format exposes the underlying finite automaton. +If a buffer is specified: find a window showing buffer by looking -All of them have the following structure, except that the @samp{next_*} -functions decide where to jump (for @samp{p}) and whether or not to -increment (for @samp{b}), rather than checking for satisfaction of a -matching condition. +@itemize @bullet +@item +at selected window +@item +at other windows on selected frame +@item +at selected windows on other frames in selected device +@item +at other windows on "" +@item +at selected windows on selected frames on other devices in selected +console. +@item +other windows sel from other devices sel con +@item +"" oth "" sel +@item +sel win sel from sel dev oth con +@item +oth win sel from sel dev oth con +@item +sel win oth from sel dev oth con +@item +oth win oth from sel dev oth con +@item +sel win sel from oth dev oth con +@item +oth win sel from oth dev oth con +@item +oth win oth from oth dev oth con +@end itemize -@example -enum status_t -match_1_operator (pattern *p, char *b) -@{ - if (! *b) return end_of_buffer; - switch (p->operator) - @{ - case accept: - return matched; - case exact: - if (*b != p->char_value) return mismatch; else break; - case any: - break; - case range: - /* range_table is computed in the regexp_compile function */ - if (! p->range_table[*b]) return mismatch; - /* etc, etc */ - @} - return working; -@} -@end example +If none, use buffer -> sel from -> etc. -Grouping, repetition, and alternation are handled by compiling the -subexpression and calling @code{match (p->subpattern, b)} recursively. +@example +Returns multiple values + second is instantiator + third is locale containing inst. + fourth is tag set + +(restart-specifier-instance ...) +@end example + +like specifier-instance, but allows restarting the lookup, for +implementing inheritance, etc. Obsoletes +specifier-matching-find-charset, or whatever it is. The restart +argument is opaque, and is returned as a multiple value of +restart-specifier-instance. (It's actually an integer with the low +bits holding the locale and the other bits count int to the list) +attached to the locale.) + +@node Future Work -- Display Tables, Future Work -- Making Elisp Function Calls Faster, Future Work -- Specifiers, Future Work +@section Future Work -- Display Tables +@cindex future work, display tables +@cindex display tables, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +#### It would also be really nice if you could specify that the +characters come out in hex instead of in octal. Mule does that by +adding a @code{ctl-hexa} variable similar to @code{ctl-arrow}, but +that's bogus -- we need a more general solution. I think you need to +extend the concept of display tables into a more general conversion +mechanism. Ideally you could specify a Lisp function that converts +characters, but this violates the Second Golden Rule and besides would +make things way way way way slow. -In terms of reading the actual code, there are five optimizations -(obfuscations, if you like) that have been done. +So instead, we extend the display-table concept, which was historically +limited to 256-byte vectors, to one of the following: @enumerate @item -An explicit "failure stack" has been substituted for recursion. - +A 256-entry vector, for backward compatibility; @item -The @code{match_1_operator}, @code{next_p}, and @code{next_b} functions -are actually inlined into the @code{match} function for efficiency. -Then the pointer movement is interspersed with the matching operations. +char-table, mapping characters to values; +@item +range-table, mapping ranges of characters to values; +@item +a list of the above. +@end enumerate + +The fourth option allows you to specify multiple display tables instead +of just one. Each display table can specify conversions for some +characters and leave others unchanged. The way the character gets +displayed is determined by the first display table with a binding for +that character. This way, you could call a function +@code{enable-hex-display} that adds a hex display-table to the list of +display tables for the current buffer. + +#### ...not yet implemented... Also, we extend the concept of "mapping" +to include a printf-like spec. Thus you can make all extended +characters show up as hex with a display table like this: + +@example + #s(range-table data ((256 524288) (format "%x"))) +@end example + +Since more than one display table is possible, you have +great flexibility in mapping ranges of characters. + +@node Future Work -- Making Elisp Function Calls Faster, Future Work -- Lisp Engine Replacement, Future Work -- Display Tables, Future Work +@section Future Work -- Making Elisp Function Calls Faster +@cindex future work, making Elisp function calls faster +@cindex making Elisp function calls faster, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{Abstract: }This page describes many optimizations that can be +made to the existing Elisp function call mechanism without too much +effort. The most important optimizations can probably be implemented +with only a day or two of work. I think it's important to do this work +regardless of whether we eventually decide to replace the Lisp engine. + +Many complaints have been made about the speed of Elisp, and in +particular about the slowness in executing function calls, and rightly +so. If you look at the implementation of the @code{funcall} function, +you'll notice that it does an incredible amount of work. Now logically, +it doesn't need to be so. Let's look first from the theoretical +standpoint at what absolutely needs to be done to call a Lisp function. + +First, let's look at the situation that would exist if we were smart +enough to have made lexical scoping be the default language policy. We +know at compile time exactly which code can reference the variables that +are the formal parameters for the function being called (specifically, +only the code that is part of that function's definition) and where +these references are. As a result, we can simply push all the values of +the variables onto a stack, and convert all the variable references in +the function definition into stack references. Therefore, binding +lexically-scoped parameters in preparation for a function call involves +nothing more than pushing the values of the parameters onto a stack and +then setting a new value for the frame pointer, at the same time +remembering the old one. Because the byte-code interpreter has a +stack-based architecture, however, the parameter values have already +been pushed onto the stack at the time of the function call invocation. +Therefore, binding the variables involves doing nothing at all, other +than dealing with the frame pointer. + +With dynamic scoping, the situation is somewhat more complicated. +Because the parameters can be referenced anywhere, and these references +cannot be located at compile time, their values have to be stored into a +global table that maps the name of the parameter to its current value. +In Elisp, this table is called the @dfn{obarray}. Variable binding in +Elisp is done using the C function @code{specbind()}. (This stands for +"special variable binding" where @dfn{special} is the standard Lisp +terminology for a dynamically-scoped variable.) What @code{specbind()} +does, essentially, is retrieve the old value of the variable out of the +obarray, remember the value by pushing it, along with the name of the +variable, onto what's called the @dfn{specpdl} stack, and then store the +new value into the obarray. The term "specpdl" means @dfn{Special +Variable Pushdown List}, where @dfn{Pushdown List} is an archaic computer +science term for a stack that used to be popular at MIT. These binding +operations, however, should still not take very much time because of the +use of symbols, i.e. because the location in the obarray where the +variable's value is stored has already been determined (specifically, it +was determined at the time that the byte code was loaded and the symbol +created), so no expensive hash table lookups need to be performed. + +An actual function invocation in Elisp does a great deal more work, +however, than was just outlined above. Let's just take a look at what +happens when one byte-compiled function invokes another byte-compiled +function, checking for places where unnecessary work is being done and +determining how to optimize these places. + +@enumerate +@item + +The byte-compiled function's parameter list is stored in exactly the +format that the programmer entered it in, which is to say as a Lisp +list, complete with @code{&optional} and @code{&rest} keywords. +This list has to be parsed for @emph{every} function invocation, which +means that for every element in a list, the element is checked to see +whether it's the @code{&optional} or @code{&rest} keywords, its +surrounding cons cell is checked to make sure that it is indeed a cons +cell, the @code{QUIT} macro is called, etc. What should be happening +here is that the argument list is parsed exactly once, at the time that +the byte code is loaded, and converted into a C array. The C array +should be stored as part of the byte-code object. The C array should +also contain, in addition to the symbols themselves, the number of +required and optional arguments. At function call time, the C array can +be very quickly retrieved and processed. +@item + +For every variable that is to be bound, the @code{specbind()} function +is called. This actually does quite a lot of things, including: + +@enumerate +@item + +Checking the symbol argument to the function to make sure it's actually +a symbol. +@item -@item -If the operator uses buffer context, the buffer pointer movement is -sometimes implicit in the operations retrieving the context. +Checking for specpdl stack overflow, and increasing its size as +necessary. +@item -@item -Some cases are combined into short preparation for individual cases, and -a "fall-through" into combined code for several cases. +Calling @code{symbol_value_buffer_local_info()} to retrieve buffer local +information for the symbol, and then processing the return value from +this function in a series of if statements. +@item -@item -The @code{pattern} type is not an explicit @samp{struct}. Instead, the -data (including, @emph{e.g.}, @samp{range_table}) is inlined into the -compiled bytecode. This leads to bizarre code in the interpreter like +Actually storing the old value onto the specpdl stack. +@item -@example -case range: - p += *(p + 1); break; -@end example +Calling @code{Fset()} to change the variable's value. -in @code{next_p}, because the compiled pattern is laid out +@end enumerate -@example -..., 'range', count, first_8_flags, second_8_flags, ..., next_op, ... -@end example @end enumerate -But if you keep your eye on the "switch in a loop" structure, you -should be able to understand the parts you need. +The entire series of calls to @code{specbind()} should be inline and +merged into the argument processing code as a single tight loop, with no +function calls in the vast majority of cases. The @code{specbind()} +logic should be streamlined as follows: +@enumerate +@item -@node MULE Character Sets and Encodings, The Lisp Reader and Compiler, Buffers and Textual Representation, Top -@chapter MULE Character Sets and Encodings -@cindex Mule character sets and encodings -@cindex character sets and encodings, Mule -@cindex encodings, Mule character sets and +The symbol argument type checking is unnecessary. +@item - Recall that there are two primary ways that text is represented in -XEmacs. The @dfn{buffer} representation sees the text as a series of -bytes (Ibytes), with a variable number of bytes used per character. -The @dfn{character} representation sees the text as a series of integers -(Ichars), one per character. The character representation is a cleaner -representation from a theoretical standpoint, and is thus used in many -cases when lots of manipulations on a string need to be done. However, -the buffer representation is the standard representation used in both -Lisp strings and buffers, and because of this, it is the ``default'' -representation that text comes in. The reason for using this -representation is that it's compact and is compatible with ASCII. +The check for the specpdl stack overflow needs to be done only once, not +once per argument. +@item -@menu -* Character Sets:: -* Encodings:: -* Internal Mule Encodings:: -* CCL:: -@end menu +All of the remaining logic should be boiled down as follows: -@node Character Sets -@section Character Sets -@cindex character sets +@enumerate +@item - A character set (or @dfn{charset}) is an ordered set of characters. A -particular character in a charset is indexed using one or more -@dfn{position codes}, which are non-negative integers. The number of -position codes needed to identify a particular character in a charset is -called the @dfn{dimension} of the charset. In XEmacs/Mule, all charsets -have dimension 1 or 2, and the size of all charsets (except for a few -special cases) is either 94, 96, 94 by 94, or 96 by 96. The range of -position codes used to index characters from any of these types of -character sets is as follows: +Retrieve the old value from the symbol's value cell. +@item -@example -Charset type Position code 1 Position code 2 ------------------------------------------------------------- -94 33 - 126 N/A -96 32 - 127 N/A -94x94 33 - 126 33 - 126 -96x96 32 - 127 32 - 127 -@end example +If this value is a symbol-value-magic object, then call the real +@code{specbind()} to do the work. +@item - Note that in the above cases position codes do not start at an -expected value such as 0 or 1. The reason for this will become clear -later. +Otherwise, we know that nothing complicated needs to be done, so we +simply push the symbol and its value onto the specpdl stack, and then +replace the value in the symbol's value cell. +@item - For example, Latin-1 is a 96-character charset, and JISX0208 (the -Japanese national character set) is a 94x94-character charset. +The only logic that we are omitting is the code in @code{Fset()} that +checks to make sure a constant isn't being set. These checks should be +made at the time that the byte code for the function is loaded and the C +array of parameters to the function is created. (Whether a symbol is +constant or not is generally known at XEmacs compile time. The only +issue here is with symbols whose names begin with a colon. These +symbols should simply be disallowed completely as parameter names.) - [Note that, although the ranges above define the @emph{valid} position -codes for a charset, some of the slots in a particular charset may in -fact be empty. This is the case for JISX0208, for example, where (e.g.) -all the slots whose first position code is in the range 118 - 127 are -empty.] +@end enumerate - There are three charsets that do not follow the above rules. All of -them have one dimension, and have ranges of position codes as follows: +@end enumerate -@example -Charset name Position code 1 ------------------------------------- -ASCII 0 - 127 -Control-1 0 - 31 -Composite 0 - some large number -@end example +Other optimizations that could be done are: - (The upper bound of the position code for composite characters has not -yet been determined, but it will probably be at least 16,383). +@itemize +@item - ASCII is the union of two subsidiary character sets: Printing-ASCII -(the printing ASCII character set, consisting of position codes 33 - -126, like for a standard 94-character charset) and Control-ASCII (the -non-printing characters that would appear in a binary file with codes 0 -- 32 and 127). +At the beginning of the function that implements the byte-code +interpreter (this is the Lisp primitive @code{byte-code}), the string +containing the actual byte code is converted into an array of integers. +I added this code specifically for MULE so that the byte-code engine +didn't have to deal with the complexities of the internal string format +for text. This conversion, however, is generally useful because on +modern processors accessing 32-bit values out of an array is +significantly faster than accessing unaligned 8-bit values. This +conversion takes time, though, and should be done once at load time +rather than each time the byte code is executed. This array should be +stored in the byte-code object. Currently, this is a bit tricky to do, +because @code{byte-code} is not actually passed the byte-code object, +but rather three of its elements. We can't just change @code{byte-code} +so that it is directly passed the byte-code object because this +function, with its existing argument calling pattern, is called directly +from compiled Elisp files. What we can and should do, however, is +create a subfunction that does take a byte-code object and actually +implements the byte-code interpreter engine. Whenever the C code wants +to execute byte code, it calls this subfunction. @code{byte-code} +itself also calls this subfunction after conjuring up an appropriate +byte-code object and storing its arguments into this object. With a +small amount of work, it's possible to do this conjuring in such a way +that it doesn't generate any garbage. +@item - Control-1 contains the non-printing characters that would appear in a -binary file with codes 128 - 159. +At the end of a function call, the parameter bindings that have been +done need to be undone. This is standardly done by calling +@code{unbind_to()}. Just as for a @code{specbind()}, this function does +a lot of work that is unnecessary in the vast majority of cases, and it +could also be inlined and streamlined. +@item - Composite contains characters that are generated by overstriking one -or more characters from other charsets. +As part of each Elisp function call, a whole bunch of checks are done +for a series of unlikely but possible conditions that may occur. These +include, for example, - Note that some characters in ASCII, and all characters in Control-1, -are @dfn{control} (non-printing) characters. These have no printed -representation but instead control some other function of the printing -(e.g. TAB or 8 moves the current character position to the next tab -stop). All other characters in all charsets are @dfn{graphic} -(printing) characters. +@itemize +@item - When a binary file is read in, the bytes in the file are assigned to -character sets as follows: +Calling the @code{QUIT} macro, which essentially involves +checking a global volatile variable to see whether additional processing +needs to be done. +@item -@example -Bytes Character set Range --------------------------------------------------- -0 - 127 ASCII 0 - 127 -128 - 159 Control-1 0 - 31 -160 - 255 Latin-1 32 - 127 -@end example +Checking whether a garbage collection needs to be done. +@item - This is a bit ad-hoc but gets the job done. +Checking the variable @code{debug_on_next_call}. +@item -@node Encodings -@section Encodings -@cindex encodings, Mule -@cindex Mule encodings +Checking for whether Elisp profiling is active. (An additional +optimization that's perhaps not worth the effort is to do some +post-processing on the array of integers after it has been converted. +For example, whenever a 16-bit value occurs in the byte code, it has +to be encoded as two separate 8-bit values. These values could be +combined. The tricky part here is that all of the places where a goto +occurs across the place where this modification is made would have to +have their offsets changed. Other such optimizations can easily be +imagined as well.) - An @dfn{encoding} is a way of numerically representing characters from -one or more character sets. If an encoding only encompasses one -character set, then the position codes for the characters in that -character set could be used directly. This is not possible, however, if -more than one character set is to be used in the encoding. +@end itemize - For example, the conversion detailed above between bytes in a binary -file and characters is effectively an encoding that encompasses the -three character sets ASCII, Control-1, and Latin-1 in a stream of 8-bit -bytes. +@item - Thus, an encoding can be viewed as a way of encoding characters from a -specified group of character sets using a stream of bytes, each of which -contains a fixed number of bits (but not necessarily 8, as in the common -usage of ``byte''). +With a little bit smarter code, it should be possible to make a +single trip variable that indicates whether any of these conditions is +true. This variable would be updated by any code that changes the +actual variables whose values are checked in the various checks just +mentioned. (By the way, all of this is occurring in the C function +@code{funcall_recording_as()}.) There is a little bit of code +between each of the checks. This code would simply have to be +duplicated between the two cases where this general trip variable is +true and is false. (Note: the optimization detailed in this item is +probably not worth doing on the first pass.) - Here are descriptions of a couple of common -encodings: +@end itemize + +@node Future Work -- Lisp Engine Replacement, Future Work -- Better Rendering Support, Future Work -- Making Elisp Function Calls Faster, Future Work +@section Future Work -- Lisp Engine Replacement +@cindex future work, lisp engine replacement +@cindex lisp engine replacement, future work @menu -* Japanese EUC (Extended Unix Code):: -* JIS7:: +* Future Work -- Lisp Engine Discussion:: +* Future Work -- Lisp Engine Replacement -- Implementation:: +* Future Work -- Startup File Modification by Packages:: @end menu -@node Japanese EUC (Extended Unix Code) -@subsection Japanese EUC (Extended Unix Code) -@cindex Japanese EUC (Extended Unix Code) -@cindex EUC (Extended Unix Code), Japanese -@cindex Extended Unix Code, Japanese EUC +@node Future Work -- Lisp Engine Discussion, Future Work -- Lisp Engine Replacement -- Implementation, Future Work -- Lisp Engine Replacement, Future Work -- Lisp Engine Replacement +@subsection Future Work -- Lisp Engine Discussion +@cindex future work, lisp engine discussion +@cindex lisp engine discussion, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{Abstract: }Recently there has been a great deal of talk on the +XEmacs mailing lists about potential changes to the XEmacs Lisp engine. +Usually the discussion has centered around the question which is better, +Common Lisp or Scheme? This is certainly an interesting debate topic, +but it didn't seem to have much practical relevance to me, so I vowed to +stay out of the discussion. Recently, however, it seems that people are +losing sight of the broader picture. For example, nobody seems to be +asking the question, ``"Would an extension language other than Lisp or +Scheme (perhaps not a Lisp variant at all) be more appropriate?"'' Nor +does anybody seem to be addressing what I consider to be the most +fundamental question, is changing the extension language a good thing to +do? + +I think it would be a mistake at this point in XEmacs development to +begin any project involving fundamental changes to the Lisp engine or to +the XEmacs Lisp language itself. It would take a huge amount of effort +to complete even part of this project, and would be a major drain on the +already-insufficient resources of the XEmacs development community. +Most of the gains that are purported to stem from a project such as this +could be obtained with far less effort by making more incremental +changes to the XEmacs core. I think it would be an even bigger mistake +to change the actual XEmacs extension language (as opposed to just +changing the Lisp engine, making few, if any, externally visible +changes). The only language change that I could possibly imagine +justifying would involve switching to some ubiquitous web language, such +as Java and JavaScript, or Perl. (Even among those, I think Java would +be the only possibility that really makes sense). + +In the rest of this document I'll present the broader issues that would +be involved in changing the Lisp engine or extension language. This +should make clear why I've come to believe as I do. + +@subheading Is everyone clear on the difference between interface and implementation? + +There seems to be a great deal of confusion concerning the difference +between interface and implementation. In the context of XEmacs, +changing the interface means switching to a different extension language +such as Common Lisp, Scheme, Java, etc. Changing the implementation +means using a different Lisp engine. There is obviously some relation +between these two issues, but there is no particular requirement that +one be changed if the other is changed. It is quite possible, for +example, to imagine taking the underlying engine for any of the various +Lisp dialects in existence, and adapting it so that it implements the +same Elisp extension language that currently exists. The vast majority +of the purported benefits that we would get from changing the extension +language could just as easily be obtained while making minimal changes +to the external Elisp interface. This way nearly all existing Elisp +programs would continue to work, there would be no need to translate +Elisp programs into some other language or to simultaneously support two +incompatible Lisp variants, and there would be no need for users or +package authors to learn a new extension language that would be just as +unfamiliar to the vast majority of them as Elisp is. -This encompasses the character sets Printing-ASCII, Japanese-JISX0201, -and Japanese-JISX0208-Kana (half-width katakana, the right half of -JISX0201). It uses 8-bit bytes. +@subheading Why should we change the Lisp engine? -Note that Printing-ASCII and Japanese-JISX0201-Kana are 94-character -charsets, while Japanese-JISX0208 is a 94x94-character charset. +Let's go over the possible reasons for changing the Lisp engine. -The encoding is as follows: +@subsubheading Speed. -@example -Character set Representation (PC=position-code) -------------- -------------- -Printing-ASCII PC1 -Japanese-JISX0201-Kana 0x8E | PC1 + 0x80 -Japanese-JISX0208 PC1 + 0x80 | PC2 + 0x80 -Japanese-JISX0212 PC1 + 0x80 | PC2 + 0x80 -@end example +Changing the Lisp engine might make XEmacs faster. However, +consider the following. +@enumerate +@item -@node JIS7 -@subsection JIS7 -@cindex JIS7 +XEmacs will get faster over time without any development effort at all +because computers will get faster. +@item + +Perhaps the biggest causes of the slowness of XEmacs are not related to +the Lisp engine at all. It has been asserted, for example, that the +slowness of XEmacs is primarily due to the redisplay mechanism, to the +handling of insertion and deletion of text in a buffer, to the event +loop, etc. Nobody has done any real studies to determine what the +actual cause of slowness is. +@item + +Emacs 18 seems plenty fast enough to most people. However, Emacs 18 +also had a worse Lisp engine and a worse byte compiler than XEmacs. +@item + +Significant speed increases in the execution of Lisp code could be +achieved without too much effort by working on the existing byte code +interpreter and function call mechanism a bit. -This encompasses the character sets Printing-ASCII, -Japanese-JISX0201-Roman (the left half of JISX0201; this character set -is very similar to Printing-ASCII and is a 94-character charset), -Japanese-JISX0208, and Japanese-JISX0201-Kana. It uses 7-bit bytes. +@end enumerate -Unlike Japanese EUC, this is a @dfn{modal} encoding, which -means that there are multiple states that the encoding can -be in, which affect how the bytes are to be interpreted. -Special sequences of bytes (called @dfn{escape sequences}) -are used to change states. +@subsubheading Memory usage. - The encoding is as follows: +A new Lisp engine with a better garbage collection mechanism might make +more efficient use of memory; for example, through the use of a +relocating garbage collector. However, consider this: -@example -Character set Representation (PC=position-code) -------------- -------------- -Printing-ASCII PC1 -Japanese-JISX0201-Roman PC1 -Japanese-JISX0201-Kana PC1 -Japanese-JISX0208 PC1 PC2 +@enumerate +@item +A new Lisp engine would probably have a larger memory footprint, perhaps +a significantly larger one. +@item + +The worst memory problems might not be due to Lisp object inefficiency +at all. The problems could simply be due mainly to the inefficient +buffer representation. Nobody has come up with any concrete numbers on +where the real problem lies. -Escape sequence ASCII equivalent Meaning ---------------- ---------------- ------- -0x1B 0x28 0x4A ESC ( J invoke Japanese-JISX0201-Roman -0x1B 0x28 0x49 ESC ( I invoke Japanese-JISX0201-Kana -0x1B 0x24 0x42 ESC $ B invoke Japanese-JISX0208 -0x1B 0x28 0x42 ESC ( B invoke Printing-ASCII -@end example +@end enumerate - Initially, Printing-ASCII is invoked. +@subsubheading Robustness. -@node Internal Mule Encodings -@section Internal Mule Encodings -@cindex internal Mule encodings -@cindex Mule encodings, internal -@cindex encodings, internal Mule +A new Lisp engine might well be more robust. (On the other hand, it +might not be. It is not always easy to tell). However, I think that +the biggest problems with robustness are in the part of the C code that +is not concerned with implementing the Lisp engine. The redisplay +mechanism and the unexec mechanism are probably the biggest sources of +robustness problems. I think the biggest robustness problems that are +related to the Lisp engine concern the use of GCPRO declarations. The +entire GCPRO mechanism is ill-conceived and unsafe. The only real way +to make this safe would be to do conservative garbage collection over +the C stack and to eliminate the GCPRO declarations entirely. But how +many of the Lisp engines that are being considered have such a mechanism +built into them? + +@subsubheading Maintainability. + +A new Lisp engine might well improve the maintainability of XEmacs by +offloading the maintenance of the Lisp engine. However, we need to make +very sure that this is, in fact, the case before embarking on a project +like this. We would almost certainly have to make significant +modifications to any Lisp engine that we choose to integrate, and +without the active and committed support and cooperation of the +developers of that Lisp engine, the maintainability problem would +actually get worse. + +@subsubheading Features. + +A new Lisp engine might have built in support for various features that +we would like to add to the XEmacs extension language, such as lexical +scoping and an object system. + +@subheading Why would we want to change the extension language? + +Possible reasons for changing the extension language include: + +@subsubheading More standard. + +Switching to a language that is more standard and more commonly in use +would be beneficial for various reasons. First of all, the language +that is more commonly used and more familiar would make it easier for +users to write their own extensions and in general, increase the +acceptance of XEmacs. Also, an accepted standard probably has had a lot +more thought put into it than any language interface created by the +XEmacs developers themselves. Furthermore, if our extension language is +being actively developed and supported, much of the work that we would +otherwise have to do ourselves is transferred elsewhere. + +However, both Scheme and Common Lisp flunk the familiarity test. +Neither language is being actively used for program development outside +of small research communities, and few prospective authors of XEmacs +extensions will be familiar with any Lisp variant for real world uses. +(I consider the argument that Scheme is often used in introductory +programming courses to be irrelevant. Many existing programmers were +taught Pascal in their introductory programming courses. How many of +them would actually be comfortable writing a program in Pascal?) +Furthermore, someone who wants to learn Lisp can't exactly go to their +neighborhood bookstore and pick up a book on this topic. + +@subsubheading Ease of use. + +There are endless arguments about which language is easiest to use. In +practice, this largely boils down to which languages are most familiar. + +@subsubheading Object oriented. + +The object-oriented paradigm is the dominant one in use today for new +languages. User interface concepts in particular are expressed very +naturally in an object-oriented system. However, neither Scheme nor +Common Lisp has been designed with object orientation in mind. There is +a standard object system for Common Lisp, but it is extremely complex +and difficult to understand. + +@node Future Work -- Lisp Engine Replacement -- Implementation, Future Work -- Startup File Modification by Packages, Future Work -- Lisp Engine Discussion, Future Work -- Lisp Engine Replacement +@subsection Future Work -- Lisp Engine Replacement -- Implementation +@cindex future work, lisp engine replacement, implementation +@cindex lisp engine replacement, implementation, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +Let's take a look at the sort of work that would be required if we were +to replace the existing Elisp engine in XEmacs with some other engine, +for example, the Clisp engine. I'm assuming here, of course, that we +are not going to be changing the interface here at the same time, which +is to say that we will be keeping the same Elisp language that we +currently have as the extension language for XEmacs, except perhaps for +incremental changes that we will make, such as lexical scoping and +proper structure support in an attempt to gradually move the language +towards an upwardly-compatible goal, such as Common Lisp. I am writing +this page primarily as food for thought. I feel fairly strongly that +actually doing this work would be a big waste of effort that would +inevitably become a huge time sink on the part of nearly everyone +involved in XEmacs development, and not only for the ones who were +supposed to be actually doing the engine change. I feel that most of +the desired changes that we want for the language and/or the engine can +be achieved with much less effort and time through incremental changes +to the existing code base. + +First of all, in order to make a successful Lisp engine change in +XEmacs, it is vitally important that the work be done through a series +of incremental stages where at the end of each stage XEmacs can be +compiled and run, and it works. It is tempting to try to make the +change all at once, but this would be disastrous. If the resulting +product worked at all, it would inevitably contain a huge number of +subtle and extremely difficult to track down bugs, and it would be next +to impossible to determine which of the myriad changes made introduced +the bug. + +Now let's look at what the possible stages of implementation could be. + +@subsubheading An Extra C Preprocessing Stage + +The first step would be to introduce another preprocessing stage for the +XEmacs C code, which is done before the C compiler itself is invoked on +the code, and before the standard C preprocessor runs. The C +preprocessor is simply not powerful enough to do many of the things we +would like to do in the C code. The existing results of this have been +a combination of a lot of hacked up and tricky-to-maintain stuff (such +as the @code{DEFUN} macro, and the associated @code{DEFSUBR}), as well +as code constructs that are difficult to write. (Consider for example, +attempting to do structured exception handling, such as catch/throw and +unwind-protect constructs), as well as code that is potentially or +actually unsafe (such as the uses of @code{alloca}), which could easily +cause stack overflow with large amounts of memory allocated in this +fashion.) The problem is that the C preprocessor does not allow macros +to have the power of an actual language, such as C or Lisp. What our +own preprocessor should do is allow us to define macros, whose +definitions are simply functions written in some language which are +executed at compile time, and whose arguments are the actual argument +for the macro call, as well as an environment which should have a data +structure representation of the C code in the file and allow this +environment to be queried and modified. It can be debated what the +language should be that these extensions are written in. Whatever the +language chosen, it needs to be a very standard language and a language +whose compiler or interpreter is available on all of the platforms that +we could ever possibly consider putting XEmacs to, which is basically to +say all the platforms in existence. One obvious choice is C, because +there will obviously be a C compiler available, because it is needed to +compile XEmacs itself. Another possibility is Perl, which is already +installed on most systems, and is universally available on all others. +This language has powerful text processing facilities which would +probably make it possible to implement the macro definitions more +quickly and easily; however, this might also encourage bad coding +practices in the macros (often simple text processing is not +appropriate, and more sophisticated parsing or recursive data structure +processing needs to be done instead), and we'd have to make sure that +the nested data structure that comprises the environment could be +represented well in Perl. Elisp would not be a good choice because it +would create a bootstrapping problem. Other possible languages, such as +Python, are not appropriate, because most programmers are unfamiliar +with this language (creating a maintainability problem) and the Python +interpreter would have to be included and compiled as part of the XEmacs +compilation process (another maintainability problem). Java is still +too much in flux to be considered at this point. + +The macro facility that we will provide needs to add two features to the +language: the ability to define a macro, and the ability to call a +macro. One good way of doing this would be to make use of special +characters that have no meaning in the C language (or in C++ for that +matter), and thus can never appear in a C file outside of comments and +strings. Two obvious characters are the @@ sign and the $ sign. We +could, for example, use @code{@@} defined to define new macros, and the +@code{$} sign followed by the macro name to call a macro. (Proponents +of Perl will note that both of these characters have a meaning in Perl. +This should not be a problem, however, because the way that macros are +defined and called inside of another macro should not be through the use +of any special characters which would in effect be extending the macro +language, but through function calls made in the normal way for the +language.) + +The program that actually implements this extra preprocessing stage +needs to know a certain amount about how to parse C code. In +particular, it needs to know how to recognize comments, strings, +character constants, and perhaps certain other kinds of C tokens, and +needs to be able to parse C code down to the statement level. (This is +to say it needs to be able to parse function definitions and to separate +out the statements, @code{if} blocks, @code{while} blocks, etc. within +these definitions. It probably doesn't, however need to parse the +contents of a C expression.) The preprocessing program should work +first by parsing the entire file into a data structure (which may just +contain expressions in the form of literal strings rather than a data +structure representing the parsed expression). This data structure +should become the environment parameter that is passed as an argument to +macros as mentioned above. The implementation of the parsing could and +probably should be done using @code{lex} and @code{yacc}. One good idea +is simply to steal some of the @code{lex} and @code{yacc} code that is +part of GCC. -In XEmacs/Mule, each character set is assigned a unique number, called a -@dfn{leading byte}. This is used in the encodings of a character. -Leading bytes are in the range 0x80 - 0xFF (except for ASCII, which has -a leading byte of 0), although some leading bytes are reserved. +Here are some possibilities that could be implemented as part of the +preprocessing: -Charsets whose leading byte is in the range 0x80 - 0x9F are called -@dfn{official} and are used for built-in charsets. Other charsets are -called @dfn{private} and have leading bytes in the range 0xA0 - 0xFF; -these are user-defined charsets. +@enumerate +@item - More specifically: +A proper way of doing the @code{DEFUN} macros. These could, for +example, take an argument list in the form of a Lisp argument list +(complete with keyword parameters and other complex features) and +automatically generate the appropriate @code{subr} structure, the +appropriate C function definition header, and the appropriate call to +the @code{DEFSUBR} initialization function. +@item -@example -Character set Leading byte -------------- ------------ -ASCII 0 -Composite 0x80 -Dimension-1 Official 0x81 - 0x8D - (0x8E is free) -Control-1 0x8F -Dimension-2 Official 0x90 - 0x99 - (0x9A - 0x9D are free; - 0x9E and 0x9F are reserved) -Dimension-1 Private 0xA0 - 0xEF -Dimension-2 Private 0xF0 - 0xFF -@end example +A truly safe and easy to use implementation of the @code{alloca} +function. This could allocate the memory in any fashion it chooses +(calling @code{malloc} using a large global array, or a series of such +arrays, etc.) an @code{insert} in the appropriate places to +automatically free up this memory. (Appropriate places here would be at +the end of the function and before any return statements. Non-local +exits can be handled in the function that actually implements the +non-local exit.) +@item -There are two internal encodings for characters in XEmacs/Mule. One is -called @dfn{string encoding} and is an 8-bit encoding that is used for -representing characters in a buffer or string. It uses 1 to 4 bytes per -character. The other is called @dfn{character encoding} and is a 19-bit -encoding that is used for representing characters individually in a -variable. +If we allow for the possibility of having an arbitrary Lisp engine, we +can't necessarily assume that we can call Lisp primitives implemented in +C from other C functions by simply making a function all. Perhaps +something special needs to happen when this is done. This could be +handled fairly easily by having our new and improved @code{DEFUN} macro +define a new macro for use when calling a primitive. +@end enumerate -(In the following descriptions, we'll ignore composite characters for -the moment. We also give a general (structural) overview first, -followed later by the exact details.) +@subsubheading Make the Existing Lisp Engine be Self-contained. -@menu -* Internal String Encoding:: -* Internal Character Encoding:: -@end menu +The goal of this stage is to gradually build up a self-contained Lisp +engine out of the existing XEmacs core, which has no dependencies on any +of the code elsewhere in the XEmacs core, and has a well-defined and +black box-style interface. (This is to say that the rest of the C code +should not be able to access the implementation of the Lisp engine, and +should make as few assumptions as possible about how this implementation +works). The Lisp engine could, and probably should, be built up as a +separate library which can be compiled on its own without any of the +rest of the XEmacs C code, and can be tested in this configuration as +well. + +The creation of this engine library should be done as a series of +subsets, each of which moves more code out of the XEmacs core and into +the engine library, and XEmacs should be compilable and runnable between +each sub-step. One possible series of sub-steps would be to first +create an engine that does only object allocation and garbage +collection, then as a second sub-step, move in the code that handles +symbols, symbol values, and simple binding, and then finally move in the +code that handles control structures, function calling, @code{byte-code} +execution, exception handling, etc. (It might well be possible to +further separate this last sub-step). + +@subsubheading Removal of Assumptions About the Lisp Engine Implementation + +Currently, the XEmacs C code makes all sorts of assumptions about the +implementation of the Lisp engine, particularly in the areas of object +allocation, object representation, and garbage collection. A different +Lisp engine may well have different ways of doing these implementations, +and thus the XEmacs C code must be rid of any assumptions about these +implementations. This is a tough and tedious job, but it needs to be +done. Here are some examples: -@node Internal String Encoding -@subsection Internal String Encoding -@cindex internal string encoding -@cindex string encoding, internal -@cindex encoding, internal string +@enumerate +@item -ASCII characters are encoded using their position code directly. Other -characters are encoded using their leading byte followed by their -position code(s) with the high bit set. Characters in private character -sets have their leading byte prefixed with a @dfn{leading byte prefix}, -which is either 0x9E or 0x9F. (No character sets are ever assigned these -leading bytes.) Specifically: +@code{GCPRO} must go. The @code{GCPRO} mechanism is tedious, +error-prone, unmaintainable, and fundamentally unsafe. As anyone who +has worked on the C Core of XEmacs knows, figuring out where to insert +the @code{GCPRO} calls is an exercise in black magic, and debugging +crashes as a result of incorrect @code{GCPROing} is an absolute +nightmare. Furthermore, the entire mechanism is fundamentally unsafe. +Even if we were to use the extra preprocessing stage detailed above to +automatically generate @code{GCPRO} and @code{UNGCPRO} calls for all +Lisp object variables occurring anywhere in the C code, there are still +places where we could be bitten. Consider, for example, code which +calls @code{cons} and where the two arguments to this functions are both +calls to the @code{append} function. Now the @code{append} function +generates new Lisp objects, and it also calls @code{QUIT}, which could +potentially execute arbitrary Lisp code and cause a garbage collection +before returning control to the @code{append} function. Now in order to +generate the arguments to the @code{cons} function, the @code{append} +function is called twice in a row. When the first @code{append} call +returns, new Lisp data has been created, but has no @code{GCPRO} +pointers to it. If the second @code{append} call causes a garbage +collection, the Lisp data from the first @code{append} call will be +collected and recycled, which is likely to lead to obscure and +impossible-to-debug crashes. The only way around this would be to +rewrite all function calls whose parameters are Lisp objects in terms of +temporary variables, so that no such function calls ever contain other +function calls as arguments. This would not only be annoying to +implement, even in a smart preprocessor, but would make the C code +become incredibly slow because of all the constant updating of the +@code{GCPRO} lists. +@item -@example -Character set Encoding (PC=position-code, LB=leading-byte) -------------- -------- -ASCII PC-1 | -Control-1 LB | PC1 + 0xA0 | -Dimension-1 official LB | PC1 + 0x80 | -Dimension-1 private 0x9E | LB | PC1 + 0x80 | -Dimension-2 official LB | PC1 + 0x80 | PC2 + 0x80 | -Dimension-2 private 0x9F | LB | PC1 + 0x80 | PC2 + 0x80 -@end example +The only proper solution here is to completely do away with the +@code{GCPRO} mechanism and simply do conservative garbage collection +over the C stack. There are already portable implementations of +conservative pointer marking over the C stack, and these could easily be +adapted for use in the Elisp garbage collector. If, as outlined above, +we use an extra preprocessing stage to create a new version of +@code{alloca} that allocates its memory elsewhere than actually on the C +stack, and we ensure that we don't declare any large arrays as local +variables, but instead use @code{alloca}, then we can be guaranteed that +the C stack is small and thus that the conservative pointer marking +stage will be fast and not very likely to find false matches. +@item - The basic characteristic of this encoding is that the first byte -of all characters is in the range 0x00 - 0x9F, and the second and -following bytes of all characters is in the range 0xA0 - 0xFF. -This means that it is impossible to get out of sync, or more -specifically: +Removing the @code{GCPRO} declarations as just outlined would also +remove the assumption currently made that garbage collection can occur +only in certain places in the C code, rather than in any arbitrary spot. +(For example, any time an allocation of Lisp data happens). In order to +make things really safe, however, we also have to remove another +assumption as detailed in the following item. +@item + +Lisp objects might be relocatable. Currently, the C code assumes that +Lisp objects other than string data are not relocatable and therefore +it's safe to pass around and hold onto the actual pointers for the C +structures that implement the Lisp objects. Current code, for example, +assumes that a @code{Lisp_Object} of type buffer and a C pointer to a +@code{struct buffer} mean basically the same thing, and indiscriminately +passes the two kinds of buffer pointers around. With relocatable Lisp +objects, the pointers to the C structures might change at any time. +(Remember, we are now assuming that a garbage collection can happen at +basically any point). All of the C code needs to be changed so that +Lisp objects are always passed around using a Lisp object type, and the +underlying pointers are only retrieved at the time when a particular +data element out of the structure is needed. (As an aside, here's +another reason why Lisp objects, instead of pointers, should always be +passed around. If pointers are passed around, it's conceivable that at +the time a garbage collection occurs, the only reference to a Lisp +object (for example, a deleted buffer) would be in the form of a C +pointer rather than a Lisp object. In such a case, the conservative +pointer marking mechanism might not notice the reference, especially if, +in an attempt to eliminate false matches and make the code generally +more efficient, it will be written so that it will look for actual Lisp +object references.) +@item + +I would go a step farther and completely eliminate the macros that +convert a Lisp object reference into a C pointer. This way the only way +to access an element out of a Lisp object would be to use the macro for +that element, which in one atomic operation de-references the Lisp +object reference and retrieves the value contained in the element. We +probably do need the ability to retrieve actual C pointers, though. For +example, in the case where an array is stored in a Lisp object, or +simply for efficiency purposes where we might want some code to retrieve +the C pointer for a Lisp object, and work on that directly to avoid a +whole bunch of extra indirections. I think the way to do this would be +through the use of a special locking construct implemented as part of +the extra preprocessor stage mentioned above. This would essentially be +what you might call a @dfn{lock block}, just like a @code{while} block. +You'd write the word @code{lock} followed by a parenthesized expression +that retrieves the C pointer and stores it into a variable that is +scoped only within the lock block and followed in turn by some code in +braces, which is the actual code associated with the lock block, and +which can make use of this pointer. While the code inside the lock +block is executing, that particular pointer and the object pointed to by +it is guaranteed not to be relocated. +@item + +If all the XEmacs C code were converted according to these rules, there +would be no restrictions on the sorts of implementations that can be +used for the garbage collector. It would be possible, for example, to +have an incremental asynchronous relocating garbage collector that +operated continuously in another thread while XEmacs was running. +@item + +The C implementation of Lisp objects might not, and probably should not, +be visible to the rest of the XEmacs C code. It should theoretically be +possible, for example, to implement Lisp objects entirely in terms of +association lists, rather than using C structures in the standard way. +(This may be an extreme example, but it's good to keep in mind an +example such as this when cleaning up the XEmacs C code). The changes +mentioned in the previous item would go a long way towards removing this +assumption. The only places where this assumption might still be made +would be inside of the lock blocks where an actual pointer is retrieved. +(Also, of course, we'd have to change the way that Lisp objects are +defined in C so that this is done with some function calls and new and +improved macros rather than by having the XEmacs C code actually define +the structures. This sort of thing would probably have to be done in +any case once the allocation mechanism is moved into a separate +library.) With some thought it should be possible to define the lock +block interface in such a way as to remove any assumptions about the +implementation of Lisp objects. +@item + +C code may not be able to call Lisp primitives that are defined in C +simply by making standard C function calls. There might need to be some +wrapper around all such calls. This could be achieved cleanly through +the extra preprocessing step mentioned above, in line with the example +described there. -@enumerate -@item -Given any byte position, the beginning of the character it is -within can be determined in constant time. -@item -Given any byte position at the beginning of a character, the -beginning of the next character can be determined in constant -time. -@item -Given any byte position at the beginning of a character, the -beginning of the previous character can be determined in constant -time. -@item -Textual searches can simply treat encoded strings as if they -were encoded in a one-byte-per-character fashion rather than -the actual multi-byte encoding. @end enumerate - None of the standard non-modal encodings meet all of these -conditions. For example, EUC satisfies only (2) and (3), while -Shift-JIS and Big5 (not yet described) satisfy only (2). (All -non-modal encodings must satisfy (2), in order to be unambiguous.) +@subsubheading Actually Replacing the Engine. -@node Internal Character Encoding -@subsection Internal Character Encoding -@cindex internal character encoding -@cindex character encoding, internal -@cindex encoding, internal character +Once we've done all of the work mentioned in the previous steps (and +admittedly, this is quite a lot of work), we should have an XEmacs that +still uses what is essentially the old and previously existing Lisp +engine, but which is ready to have its Lisp engine replaced. The +replacement might proceed as follows: - One 19-bit word represents a single character. The word is -separated into three fields: +@enumerate +@item -@example -Bit number: 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 - <------------> <------------------> <------------------> -Field: 1 2 3 -@end example +Identify any further changes that need to be made to the engine +interface that we have defined as a result of the previous steps so that +features and idiosyncrasies of various Lisp engines that we examine +could be properly supported. +@item - Note that fields 2 and 3 hold 7 bits each, while field 1 holds 5 bits. +Pick a Lisp engine and write an interface layer that sits on top of this +Lisp engine and makes it adhere to what I'll now call the XEmacs Lisp +engine interface. +@item -@example -Character set Field 1 Field 2 Field 3 -------------- ------- ------- ------- -ASCII 0 0 PC1 - range: (00 - 7F) -Control-1 0 1 PC1 - range: (00 - 1F) -Dimension-1 official 0 LB - 0x80 PC1 - range: (01 - 0D) (20 - 7F) -Dimension-1 private 0 LB - 0x80 PC1 - range: (20 - 6F) (20 - 7F) -Dimension-2 official LB - 0x8F PC1 PC2 - range: (01 - 0A) (20 - 7F) (20 - 7F) -Dimension-2 private LB - 0xE1 PC1 PC2 - range: (0F - 1E) (20 - 7F) (20 - 7F) -Composite 0x1F ? ? -@end example +Strongly consider creating, if we haven't already done so, a test suite +that can test the XEmacs Lisp engine interface when used with a +stand-alone Lisp engine. +@item - Note that character codes 0 - 255 are the same as the ``binary encoding'' -described above. +Test the hell out of the Lisp engine that we've chosen when combined +with its XEmacs Lisp engine interface layer as a stand-alone program. +@item -@node CCL -@section CCL -@cindex CCL +Now finally attach this stand-alone program to XEmacs itself. Debug and +fix any further problems that ensue (and there inevitably will be such +problems), updating the test suite as we go along so that if it were run +again on the old and buggy interfaced Lisp engine, it would note the +bug. -@example -CCL PROGRAM SYNTAX: - CCL_PROGRAM := (CCL_MAIN_BLOCK - [ CCL_EOF_BLOCK ]) - - CCL_MAIN_BLOCK := CCL_BLOCK - CCL_EOF_BLOCK := CCL_BLOCK - - CCL_BLOCK := STATEMENT | (STATEMENT [STATEMENT ...]) - STATEMENT := - SET | IF | BRANCH | LOOP | REPEAT | BREAK - | READ | WRITE - - SET := (REG = EXPRESSION) | (REG SELF_OP EXPRESSION) - | INT-OR-CHAR - - EXPRESSION := ARG | (EXPRESSION OP ARG) - - IF := (if EXPRESSION CCL_BLOCK CCL_BLOCK) - BRANCH := (branch EXPRESSION CCL_BLOCK [CCL_BLOCK ...]) - LOOP := (loop STATEMENT [STATEMENT ...]) - BREAK := (break) - REPEAT := (repeat) - | (write-repeat [REG | INT-OR-CHAR | string]) - | (write-read-repeat REG [INT-OR-CHAR | string | ARRAY]?) - READ := (read REG) | (read REG REG) - | (read-if REG ARITH_OP ARG CCL_BLOCK CCL_BLOCK) - | (read-branch REG CCL_BLOCK [CCL_BLOCK ...]) - WRITE := (write REG) | (write REG REG) - | (write INT-OR-CHAR) | (write STRING) | STRING - | (write REG ARRAY) - END := (end) - - REG := r0 | r1 | r2 | r3 | r4 | r5 | r6 | r7 - ARG := REG | INT-OR-CHAR - OP := + | - | * | / | % | & | '|' | ^ | << | >> | <8 | >8 | // - | < | > | == | <= | >= | != - SELF_OP := - += | -= | *= | /= | %= | &= | '|=' | ^= | <<= | >>= - ARRAY := '[' INT-OR-CHAR ... ']' - INT-OR-CHAR := INT | CHAR +@end enumerate -MACHINE CODE: +@node Future Work -- Startup File Modification by Packages, , Future Work -- Lisp Engine Replacement -- Implementation, Future Work -- Lisp Engine Replacement +@subsection Future Work -- Startup File Modification by Packages +@cindex future work, startup file modification by packages +@cindex startup file modification by packages, future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +OK, we need to create a design document for all of this, including: + +PRINCIPLE #1: Whenever you have auto-generated stuff, @strong{CLEARLY} +indicate this in comments around the stuff. These comments get +searched for, and used to locate the existing generated stuff to +replace. Custom currently doesn't do this. + +PRINCIPLE #2: Currently, lots of functions want to add code to the +.emacs. (e.g. I get prompted for my mail address from +add-change-log-entry, and then prompted if I want to make this +permanent). There needs to be a Lisp API for working with arbitrary +code to be added to a user's startup. This API hides all the details +of which file to put the fragment in, where in it, how to mark it with +magical comments of the right kind so that previous fragments can be +replaced, etc. + +PRINCIPLE #3: @strong{ALL} generated stuff should be loaded before any +user-written init stuff. This way the user can override the generated +settings. Although in the case of customize, it may work when the +custom stuff is at the end of the init file, it surely won't work for +arbitrary code fragments (which typically do @code{setq} or the like). + +PRINCIPLE #4: As much as possible, generated stuff should be place in +separate files from non-generated stuff. Otherwise it's inevitable +that some corruption is going to result. + +PRINCIPLE #5: Packages are encouraged, as much as possible, to work +within the customize model and store all their customizations there. +However, if they really need to have their own init files, these files +should be placed in .xemacs/, given normal names +(e.g. @file{saved-abbrevs.el} not .abbrevs), and there should be some magic +comment at the top of the file that causes it to get automatically +loaded while loading a user's init file. (Alternatively, the +above-named API could specify a function that lets a package specify +that they want such-and-such file loaded from the init file, and have +the specifics of this get handled correctly.) + +OVERARCHING GOAL: The overarching goal is to provide a unified +mechanism for packages to store state and setting information about +the user and what they were doing when XEmacs exited, so that the same +or a similar environment can be automatically set up the next time. +In general, we are working more and more towards being a truly GUI app +where users' settings are easy to change and get remembered correctly +and consistently from one session to the next, rather than requiring +nasty hacking in elisp. + +Hrvoje, do you have any interest in this? How about you, Martin? +This seems like it might be up your alley. This stuff has been +ad-hocked since kingdom come, and it's high time that we make this +work properly so that it could be relied upon, and a lot of things +could "just work". + + +@node Future Work -- Better Rendering Support, , Future Work -- Lisp Engine Replacement, Future Work +@section Future Work -- Better Rendering Support +@cindex future work, better rendering support +@cindex better rendering support, future work + +This section was written by Stephen Turnbull <stephen@@xemacs.org>, so +don't blame Ben (or Eric and Matthias, for that matter). Feel free to +add, edit, and share the blame, guys! + +@c #### make these @urlref's!! +As of late November 2004, this principally means adding support for the +@file{Xft} library, which provides a more robust @emph{font +configuration} mechanism via Keith Packard's @file{fontconfig} library +improved glyph rendering, including antialiasing, via the +@file{freetype} library, and client-side rendering (saving bandwidth and +server memory) via the @file{XRender extension}. In fact, patches which +provide Xft support have been available for several years, but the +authors have been unwilling to deal with several important issues which +block integration. These are @emph{Mule}, and more generally, +@emph{face} support; @emph{widget} support (including the toolbar and +menubar); and @emph{redisplay refactoring}. + +@c Describe Alexey Gladkov and Yury Konovalov's work. + +However, in late 2003 Eric Knauel <knauel@@informatik.uni-tuebingen.de> +and Matthias Neubauer <neubauer@@informatik.uni-freiburg.de> put forward +a relatively complete patch which was robust to daily use in ISO 8859-1 +locales, and Stephen Turnbull began work on the integration issues. At +this point a (private) CVS branch is available for Stephen's patch +(branch point tag @samp{sjt-xft-bp}, branch tag @samp{sjt-xft}), and +one may be made available for the Knauel-Matthias patch soon. -The machine code consists of a vector of 32-bit words. -The first such word specifies the start of the EOF section of the code; -this is the code executed to handle any stuff that needs to be done -(e.g. designating back to ASCII and left-to-right mode) after all -other encoded/decoded data has been written out. This is not used for -charset CCL programs. +@menu +* Better Rendering Support -- Issues:: +* Better Rendering Support -- Implementation:: +* Better Rendering Support -- Current Status:: +* Better Rendering Support -- Configuration with the Interim Patches:: +@end menu -REGISTER: 0..7 -- referred by RRR or rrr -OPERATOR BIT FIELD (27-bit): XXXXXXXXXXXXXXX RRR TTTTT - TTTTT (5-bit): operator type - RRR (3-bit): register number - XXXXXXXXXXXXXXXX (15-bit): - CCCCCCCCCCCCCCC: constant or address - 000000000000rrr: register number +@node Better Rendering Support -- Issues, Better Rendering Support -- Implementation, , Future Work -- Better Rendering Support +@subsection Better Rendering Support -- Issues +@cindex better rendering support, issues +@cindex issues, better rendering support + +Of course it's ``unfair'' to demand that the implementers of a nice +feature like anti-aliasing support deal with accumulated cruft of the +last few years, but somebody must, sometime soon. Even core developers +are complaining about how slow XEmacs is in some applications, and there +is reason to believe that some of the problem is in redisplay. +Adding more @emph{ad hoc} features to redisplay will make the whole +module more complex and unintelligible. Even if it doesn't inherently +further detract from efficiency, it will surely make reform and +refactoring harder. + +Similar considerations apply to Mule support. If Xft support is not +carefully designed, or implemented with Mule support soon, it will +undoubtedly make later Mule implementation far more difficult than it +needs to be, and require redundant work be done (@emph{e.g.}, on +@samp{Options} menu support). + +Besides the design issue---and many users are requesting more +flexibility, primarily face support, from the widgets---with widget +support there is also an aesthetic issue. It is horribly unimpressive to +have clunky bitmapped fonts on the decorations when pleasant antialiased +fonts are available in the buffer. + +Finally, these issues interact. Widgets and faces are inherently +heavyweight objects, requiring orders of magnitude more computation than +simply displaying a string in a fixed font. This will have an +efficiency impact, of course. And they interact with each other; Mule +was designed for use in buffers and display in Emacs windows---but a +widget's content is usually not a buffer, and widgets need not be +displayed in a window, but may appear in other contexts, especially in +the gutters. So specifiers will probably have to be reworked, in order +to properly support display of different faces in non-buffer, non-window +contexts. + +@node Better Rendering Support -- Implementation, Better Rendering Support -- Current Status, Better Rendering Support -- Issues, Future Work -- Better Rendering Support +@subsection Better Rendering Support -- Implementation +@cindex better rendering support, implementation +@cindex implementation, better rendering support + +Stephen is thinking in terms of the following components of a +comprehensive proposal. + +@table @strong +@item Font configuration +In XEmacs, font configuration is handled via @emph{faces}. Currently +XEmacs uses a special type of @emph{font specifier} to map XEmacs +locales to font names. Especially under X11, this can cause annoying +problems because of the unreliability of X servers' mappings from +@samp{XLFD} names to X11 fonts, over which XEmacs has no influence +whatsoever. However, the @file{fontconfig} library which is used with +@file{Xft} provides much more reliable mapping, along with a more +reliably parsable naming scheme similar to that used by TrueType fonts +on MS Windows and the Macintosh. Since the capabilities of font +specifiers and @file{fontconfig} overlap, we should consider using +@file{fontconfig} instead of @samp{XLFD} names. This implies that use +of @file{Xft}'s rendering functionality should be separated from use of +@file{fontconfig}. + +@item Font menus +The @samp{Options->Font} and @samp{Options->Font Sizes} menus are +broken, by design, not just by @file{Xft}. Although they work better +in Eric and Matthias's patch than in Stephen's, even their version has +the problem that many fonts are unavailable because they don't match the +current size---which is very strange, since @file{Xft} fonts are of +course scalable. But the whole idea of requiring that the font match +the size is strange. And the @samp{Options->Font Weights} menu is just +disabled, and has been for eons. + +@item X resources +Currently in Stephen's patch there are @emph{four} treatments of font +resources. There are the @samp{XEmacs.@var{face}.attributeFont} +resources used to set a single global font specification. In the +widgets, some (still) have a @samp{font} resource using the automatic +@file{Xt} resource conversion to @samp{FontStruct}, some have separate +@samp{font} and @samp{xftFont} resources with the former automatically +converted to @samp{FontStruct} by @file{Xt} and the latter left as a +string, to be converted by @samp{XftParseName} later, and some have a +single @samp{font} resource which is converted to @samp{FontStruct} by +@file{Xt} or the latter left as a string, depending on whether +@file{Xft} was enabled by @samp{configure} or not. + +Stephen thinks that all of these should be converted to use the face +approach, perhaps with some way to set specifications for individual +widgets, frames, or buffers. This will require some careful design work +to incorporate face support in the widgets. We should just accept any +or all of @samp{font}, @samp{fontSet}, and @samp{fontList} resources, +treat them all as lists of font names, either @samp{XLFD}- or +@file{fontconfig}-style, parse them ourselves (ie, not use the @file{Xt} +resource manager), and add them to font specifiers as appropriate. But +this will require a bit of thought to obey POLA vis-a-vis usual @file{Xt} +conventions. + +@item Rendering engine objects +With the introduction of the ``Xft patch,'' the X11, Macintosh, and MS +Windows platforms are all able to support multiple font rendering +engines in the same binary. Generically, there are several tasks that +must be accomplished to render text on the display. In both cases the +code is rather disorganized, with substantial cross-platform duplication +of similar routines. While it may not be worthwhile to go the whole way +to @samp{RENDERER_HAS_METHOD} and @samp{MAYBE_RENDMETH}, refactoring +these modules around the notion of interfacing a ``generic rendering +engine interface'' to ``text'' seems like a plausible way to focus this +work. + +Further evidence for this kind of approach is a bug recently fixed in +the @samp{xft-sjt} branch. XEmacs was crashing because the Athena Label +widget tried to access a nonexistent font in its initialization +routine. The font didn't exist because although no core X11 font +corresponding to the spec existed, an Xft font was found. So the XEmacs +font instance existed but it did not specify an X11 core font, only the +Xft font. When this object was used to initialize the font for the +Label widget, None (0) was passed to XtSetArgs, then XtCreateWidget was +called, and the internal initialization routine attempted to access that +(nonexistent) font while computing an X11 graphics context (GC). + +A similar issue applies to colors, but there Xft colors keep the pixel +data internally, so (serendipitously) the X11 color (@emph{i.e.}, pixel) +member does get updated. + +@item Colors, fonts, and faces +Besides the rendering engine itself, the XEmacs implementations of these +objects are poorly supported by current widget implementations, +including the traditional menubar and toolbar, as well as the more +recent button, tab control, and progress bar widgets. The refactoring +suggested under ``Rendering engine objects'' should be conducted with an +eye to making these widgets support faces, perhaps even to the extent of +allowing rendering to X pixmaps (which some Athena widgets support, +although they will not support rendering via Xft directly). Especially +with @samp{XRender} technology this should not be horribly inefficient. + +@item Specifiers, charsets, and languages +Traditionally Mule uses a rather rigid and low-level abstraction, the +@emph{charset}, to characterize font repertoires. Unfortunately, +support for a given charset is generally neither necessary nor +sufficient to support a language. Worse, although X11's only means for +indicating font repertoires is the font's @emph{registry}, the actual +repertoire of many fonts is either deficient or font-dependent. The +only convenience is that the registry maps directly to a Mule charset in +most cases, and vice versa. + +To date, XEmacs Mule has supported identification of appropriate fonts +to support a language's repertoire of characters by identifying the +repertoire as a subset of a union of charsets. To each charset there is +a regular expression matching the registry portion of a font name. Then +instantiation of a font proceeds by identifying the specifier domain, +and then walking down the list of specifications, matching the regexp +against font names until a match is found. That font is requested from +the system, and if not found, the process continues similarly until a +font that can be loaded is found. + +This has several problems. First, there's no guarantee that the union +will be disjoint. This problem manifests both in the case of display of +Unicode representations of text in the @samp{POSIX} default locale, +where glyphs are typically drawn from several inappropriate fonts. A +similar problem often occurs, though for a different reason, in +multilingual messages composed using @file{Gnus}'s @samp{message-mode} +and MIME support. This problem @emph{cannot} be avoided with the +current design; it is quite possible that a font desired in one context +will be shadowed by a font intended to get higher priority in a +semantically different but syntactically similar (as far as Mule can +tell) context. (Of course, one could attach a different face as a text +property, but that requires programming support; it can't be done by +user configuration.) The problem is only exacerbated as more and more +Unicode fonts, supporting large repertoires with substantial overlap +across fonts, are designed and published. + +A second problem is that registry names are often inaccurate. For +example, the Japanese JIS X 0208 standard was first published in 1978 +(as a relabelling of an older standard). It was then revised in 1983, +again in 1990, and once again in 2000, with slight changes to the +repertoire and mapping in each revision. Technically, these standards +can be distinguished in properly named fonts as @samp{jisx0208.1978}, +@samp{jisx0208.1983}, @samp{jisx0208.1990}, @samp{jisx0208.2000}, but +all of them are commonly simply labelled @samp{jisx0208}, and Western +distributors, of course, generally lack the expertise to correctly +relabel them. + +A third problem is that you generally can't tell if there are ``holes'' +in the repertoire until you try to display the glyph. + +All of this tends to break standard idioms for handling Mule fonts in +@file{init} files because they depend on charsets being disjoint +repertoires. + +The TrueType fonts (and the later OpenType standard) provides for a +proper character set query (as a Boolean vector indexed by Unicode code +points), as well as providing a list of supported languages. + +I propose that we take advantage of these latter facilities by allowing +a font to be specified either as a string (a font name), or as a list +whose head is the font name and whose tail is a list of languages and +Mule charsets (for backward compatibility) that user intends to use the +font to display. This will probably require a change to the specifier +code. + +As mentioned above, specifiers will probably also have to be enhanced to +recognize @samp{widget} locales and domains, instead of the current hack +where special @samp{widget} and @samp{gui-element} faces are created. -AAAA: 00000 + - 00001 - - 00010 * - 00011 / - 00100 % - 00101 & - 00110 | - 00111 ~ +@item Customize - 01000 << - 01001 >> - 01010 <8 - 01011 >8 - 01100 // - 01101 not used - 01110 not used - 01111 not used +Customize needs to deal with all this stuff!! +@end table - 10000 < - 10001 > - 10010 == - 10011 <= - 10100 >= - 10101 != -OPERATORS: TTTTT RRR XX.. +@node Better Rendering Support -- Current Status, Better Rendering Support -- Configuration with the Interim Patches, Better Rendering Support -- Implementation, Future Work -- Better Rendering Support +@subsection Better Rendering Support -- Current Status +@cindex better rendering support, current status +@cindex current status, better rendering support + +Stephen has a branch containing his stuff in XEmacs CVS. The branch +point tag is @samp{sjt-xft-bp}, roughly corresponding to XEmacs 21.5.18, +and branch tag is @samp{sjt-xft}. -SetCS: 00000 RRR C...C RRR = C...C -SetCL: 00001 RRR ..... RRR = c...c - c.............c -SetR: 00010 RRR ..rrr RRR = rrr -SetA: 00011 RRR ..rrr RRR = array[rrr] - C.............C size of array = C...C - c.............c contents = c...c +@subsubsection Bugs Reported in sjt-xft -Jump: 00100 000 c...c jump to c...c -JumpCond: 00101 RRR c...c if (!RRR) jump to c...c -WriteJump: 00110 RRR c...c Write1 RRR, jump to c...c -WriteReadJump: 00111 RRR c...c Write1, Read1 RRR, jump to c...c -WriteCJump: 01000 000 c...c Write1 C...C, jump to c...c - C...C -WriteCReadJump: 01001 RRR c...c Write1 C...C, Read1 RRR, - C.............C and jump to c...c -WriteSJump: 01010 000 c...c WriteS, jump to c...c - C.............C - S.............S - ... -WriteSReadJump: 01011 RRR c...c WriteS, Read1 RRR, jump to c...c - C.............C - S.............S - ... -WriteAReadJump: 01100 RRR c...c WriteA, Read1 RRR, jump to c...c - C.............C size of array = C...C - c.............c contents = c...c - ... -Branch: 01101 RRR C...C if (RRR >= 0 && RRR < C..) - c.............c branch to (RRR+1)th address -Read1: 01110 RRR ... read 1-byte to RRR -Read2: 01111 RRR ..rrr read 2-byte to RRR and rrr -ReadBranch: 10000 RRR C...C Read1 and Branch - c.............c - ... -Write1: 10001 RRR ..... write 1-byte RRR -Write2: 10010 RRR ..rrr write 2-byte RRR and rrr -WriteC: 10011 000 ..... write 1-char C...CC - C.............C -WriteS: 10100 000 ..... write C..-byte of string - C.............C - S.............S - ... -WriteA: 10101 RRR ..... write array[RRR] - C.............C size of array = C...C - c.............c contents = c...c - ... -End: 10110 000 ..... terminate the execution +@table @code +@item ChangeLogs +A lot of these, especially for Eric and Matthias's work, are missing. +Mea culpa. + +@item Options->Font +@itemx 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, +@samp{default} does not. +@end table -SetSelfCS: 10111 RRR C...C RRR AAAAA= C...C - ..........AAAAA -SetSelfCL: 11000 RRR ..... RRR AAAAA= c...c - c.............c - ..........AAAAA -SetSelfR: 11001 RRR ..Rrr RRR AAAAA= rrr - ..........AAAAA -SetExprCL: 11010 RRR ..Rrr RRR = rrr AAAAA c...c - c.............c - ..........AAAAA -SetExprR: 11011 RRR ..rrr RRR = rrr AAAAA Rrr - ............Rrr - ..........AAAAA -JumpCondC: 11100 RRR c...c if !(RRR AAAAA C..) jump to c...c - C.............C - ..........AAAAA -JumpCondR: 11101 RRR c...c if !(RRR AAAAA rrr) jump to c...c - ............rrr - ..........AAAAA -ReadJumpCondC: 11110 RRR c...c Read1 and JumpCondC - C.............C - ..........AAAAA -ReadJumpCondR: 11111 RRR c...c Read1 and JumpCondR - ............rrr - ..........AAAAA + +@node Better Rendering Support -- Configuration with the Interim Patches, , Better Rendering Support -- Current Status, Future Work -- Better Rendering Support +@subsection Better Rendering Support -- Configuration with the Interim Patches +@cindex better rendering support, configuration with the interim patches +@cindex configuration with the interim patches, better rendering support + +For Stephen's @samp{sjt-xft} branch, you should keep the following in +mind when configuring: + +@itemize +@item +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 +@itemize +@item +menubars +@item +tab controls +@end itemize + +Here are the resources I use. @strong{Warning:} @emph{This interface +will change.} The tab control has separate Font and XftFont resources, +and uses the X resource manager to instantiate a FontStruct from the +Font resource. The menubar on the other hand uses Font for both, but +converts to FontStruct if Xft is not compiled in, and leaves it as a +string if Xft is compiled in. There is no equivalent 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 revert to a simple string representation for +this resource, and convert to a face in XEmacs rather than a font in +Xt/Xft. +@example +XEmacs*Tabs.xftFont: Bitstream Vera Sans-18 +XEmacs*menubar.font: Bitstream Vera Sans-18 +XEmacs.modeline.attributeFont: Bitstream Charter-26 +XEmacs.default.attributeFont: Bitstream Vera Sans Mono-24 +@end example +No, I don't understand why I need to use different point sizes to get +what looks like good balance to my eyes. I do highly recommend use of a +proportional font in the modeline because it allows a lot more text to +fit there. + +@item +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 @code{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 @code{define-specifier-tag} like this: + +@example +(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) @end example +@end itemize -@node The Lisp Reader and Compiler, Lstreams, MULE Character Sets and Encodings, Top -@chapter The Lisp Reader and Compiler -@cindex Lisp reader and compiler, the -@cindex reader and compiler, the Lisp -@cindex compiler, the Lisp reader and -Not yet documented. +@node Future Work Discussion, Old Future Work, Future Work, Top +@chapter Future Work Discussion +@cindex future work, discussion +@cindex discussion, future work + +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. -@node Lstreams, Consoles; Devices; Frames; Windows, The Lisp Reader and Compiler, Top -@chapter Lstreams -@cindex lstreams +@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:: +@end menu - An @dfn{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. +@node Discussion -- Garbage Collection, Discussion -- Glyphs, Future Work Discussion, Future Work Discussion +@section Discussion -- Garbage Collection +@cindex discussion, garbage collection +@cindex garbage collection, discussion @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. +* Discussion -- Pure Space:: +* Discussion -- Hashtable-Based Marking and Cleanup:: +* Discussion -- The Anti-Cons:: @end menu -@node Creating an Lstream -@section Creating an Lstream -@cindex lstream, creating an +@node Discussion -- Pure Space, Discussion -- Hashtable-Based Marking and Cleanup, Discussion -- Garbage Collection, Discussion -- Garbage Collection +@subsection Discussion -- Pure Space +@cindex discussion, pure space +@cindex pure space, discussion -Lstreams come in different types, depending on what is being interfaced -to. Although the primitive for creating new lstreams is -@code{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. +On Tue, Oct 12, 1999 at 03:36:59AM -0700, Ben Wing wrote: -All lstream creation functions take a @var{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. +So what am I missing here? - @var{mode} is a string, one of +In response, Olivier Galibert wrote: -@table @code -@item "r" - Open for reading. -@item "w" - Open for writing. -@item "rc" - Open for reading, but ``read'' never returns partial MULE characters. -@item "wc" - Open for writing, but never writes partial MULE characters. -@end table +Two things: +@enumerate +@item +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: + +@itemize @bullet +@item +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. +@item +move the markbit outside of the lrecord. +@end itemize + +The second solution is more appealing to me for a bunch of reasons: +@itemize @bullet +@item +more things are shared than only what is purecopied (not yet used +functions come to mind) +@item +no more "the only references to this non-purecopied object are from +purecopied objects, XEmacs will self-destruct in ten seconds" kind +of bugs. +@item +removing flags goes the right way towards implementing Jan's +allocator ideas. +@item +it becomes probably easier to experiment with the GC code +@end itemize + +@item +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. +@end enumerate + +@node Discussion -- Hashtable-Based Marking and Cleanup, Discussion -- The Anti-Cons, Discussion -- Pure Space, Discussion -- Garbage Collection +@subsection Discussion -- Hashtable-Based Marking and Cleanup +@cindex discussion, hashtable-based marking and cleanup +@cindex hashtable-based marking and cleanup, discussion + +On 10/12/1999 5:49 PM Ben Wing wrote: + +OK, I can see the advantages. But: + +@enumerate +@item +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.) + +@item +I think you should @strong{expand} the concept of read-only objects so +that @strong{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 +@code{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. +@end enumerate + +BTW there is a wonderful book all about garbage collection by Jones and +Lins. Ever seen it? + +@example +http://www.amazon.com/exec/obidos/ASIN/0471941484/qid=939775572/sr=1-1/002-3092633-2509405 +@end example + +@node Discussion -- The Anti-Cons, , Discussion -- Hashtable-Based Marking and Cleanup, Discussion -- Garbage Collection +@subsection Discussion -- The Anti-Cons +@cindex discussion, the anti-cons +@cindex the anti-cons, discussion + +From: "Ben Wing" <ben@@666.com> +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: + +@example +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 +@end example + +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 -@node Lstream Types -@section Lstream Types -@cindex lstream types -@cindex types, lstream +http://research.microsoft.com/Users/simonpj/Papers/weak.htm -@table @asis -@item stdio +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. -@item filedesc +Ben> implementing this in the current xemacs framework is mostly +Ben> trivial. -@item lisp-string +Ben> michael, would such an object get in the way of your new gc? -@item fixed-buffer +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. -@item resizing-buffer +Can you wait until next week? I'll try to come up with a battle plan +then. -@item dynarr +From: sperber@@informatik.uni-tuebingen.de (Michael Sperber [Mr. Preprocessor]) +Date: Tue, 28 May 2002 16:14:20 +0200 -@item lisp-buffer +We've now started implementing ephemerons as a building block for the +more involved weakness-involving data structures: -@item print +The relevant reference is -@item decoding +Barry Hayes. Ephemerons: A New Finalization Mechanism. +OOPSLA 1997. 176--183 -@item encoding -@end table +The idea is this: -@node Lstream Functions -@section Lstream Functions -@cindex lstream functions +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. -@deftypefun {Lstream *} Lstream_new (Lstream_implementation *@var{imp}, const char *@var{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). -@end deftypefun +This allows implementing, AFAICS, the other data structures involving +weakness, such as weak hash tables and their various mutants. -@deftypefun void Lstream_set_buffering (Lstream *@var{lstr}, Lstream_buffering @var{buffering}, int @var{buffering_size}) -Change the buffering of a stream. See @file{lstream.h}. By default the -buffering is @code{STREAM_BLOCK_BUFFERED}. -@end deftypefun +We're also planning to come up with a more comprehensive solution for +finalization, but some design snags remain to be worked out. -@deftypefun int Lstream_flush (Lstream *@var{lstr}) -Flush out any pending unwritten data in the stream. Clear any buffered -input data. Returns 0 on success, -1 on error. -@end deftypefun +@node Discussion -- Glyphs, Discussion -- Dialog Boxes, Discussion -- Garbage Collection, Future Work Discussion +@section Discussion -- Glyphs +@cindex discussion, glyphs +@cindex glyphs, discussion -@deftypefn Macro int Lstream_putc (Lstream *@var{stream}, int @var{c}) -Write out one byte to the stream. This is a macro and so it is very -efficient. The @var{c} argument is only evaluated once but the @var{stream} -argument is evaluated more than once. Returns 0 on success, -1 on -error. -@end deftypefn +Some comments (not always pretty!) by Ben: -@deftypefn Macro int Lstream_getc (Lstream *@var{stream}) -Read one byte from the stream. This is a macro and so it is very -efficient. The @var{stream} argument is evaluated more than once. Return -value is -1 for EOF or error. -@end deftypefn +March 20, 2000 -@deftypefn Macro void Lstream_ungetc (Lstream *@var{stream}, int @var{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 @var{c} argument is only evaluated once but the @var{stream} -argument is evaluated more than once. -@end deftypefn +Andy, I use the tab widgets but I've been having lots of problems. -@deftypefun int Lstream_fputc (Lstream *@var{stream}, int @var{c}) -@deftypefunx int Lstream_fgetc (Lstream *@var{stream}) -@deftypefunx void Lstream_fungetc (Lstream *@var{stream}, int @var{c}) -Function equivalents of the above macros. -@end deftypefun +1] Sometimes clicking on them does nothing. -@deftypefun Bytecount Lstream_read (Lstream *@var{stream}, void *@var{data}, Bytecount @var{size}) -Read @var{size} bytes of @var{data} from the stream. Return the number -of bytes read. 0 means EOF. -1 means an error occurred and no bytes -were read. -@end deftypefun +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. -@deftypefun Bytecount Lstream_write (Lstream *@var{stream}, void *@var{data}, Bytecount @var{size}) -Write @var{size} bytes of @var{data} to the stream. Return the number -of bytes written. -1 means an error occurred and no bytes were written. -@end deftypefun +March 23, 2000 -@deftypefun void Lstream_unread (Lstream *@var{stream}, void *@var{data}, Bytecount @var{size}) -Push back @var{size} bytes of @var{data} onto the input queue. The next -call to @code{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. -@end deftypefun +I'm very confused. The SIGIO timer is used @strong{only} for C-g. It has +nothing to do with any other events. (sit-for 0) ought to -@deftypefun int Lstream_close (Lstream *@var{stream}) -Close the stream. All data will be flushed out. -@end deftypefun +(1) cause all pending non-command events to get executed, and +(b) do redisplay -@deftypefun void Lstream_reopen (Lstream *@var{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. -@end deftypefun +However, sit-for gets preempted by input coming in. -@deftypefun void Lstream_rewind (Lstream *@var{stream}) -Rewind the stream to the beginning. -@end deftypefun +What about (sit-for 0.1)? -@node Lstream Methods -@section Lstream Methods -@cindex lstream methods +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: -@deftypefn {Lstream Method} Bytecount reader (Lstream *@var{stream}, unsigned char *@var{data}, Bytecount @var{size}) -Read some data from the stream's end and store it into @var{data}, which -can hold @var{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 @var{size} is less than -this granularity. (This will happen frequently for streams that need to -return whole characters, because @code{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 @code{Lstream_read()} with a very small size. +@example +(wait-for-event redisplay &rest event-specs) +@end example -This function can be @code{NULL} if the stream is output-only. -@end deftypefn +Waits for one of the event specifications specified to happen. Returns +something about what happened. -@deftypefn {Lstream Method} Bytecount writer (Lstream *@var{stream}, const unsigned char *@var{data}, Bytecount @var{size}) -Send some data to the stream's end. Data to be sent is in @var{data} -and is @var{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 -@code{EWOULDBLOCK} errors.) This function can be @code{NULL} if the -stream is input-only. -@end deftypefn +REDISPLAY controls the behavior of redisplay during waiting. Something +like -@deftypefn {Lstream Method} int rewinder (Lstream *@var{stream}) -Rewind the stream. If this is @code{NULL}, the stream is not seekable. -@end deftypefn +@itemize @bullet +@item +nil (never redisplay), +@item +t (redisplay when it seems appropriate), etc. +@end itemize -@deftypefn {Lstream Method} int seekable_p (Lstream *@var{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. -@end deftypefn +EVENT-SPECS could be -@deftypefn {Lstream Method} int flusher (Lstream *@var{stream}) -Perform any additional operations necessary to flush the data in this -stream. -@end deftypefn +@example +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 +@end example -@deftypefn {Lstream Method} int pseudo_closer (Lstream *@var{stream}) -@end deftypefn +The existing functions @code{next-event}, @code{next-command-event}, +@code{accept-process-output}, @code{sit-for}, @code{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. -@deftypefn {Lstream Method} int closer (Lstream *@var{stream}) -Perform any additional operations necessary to close this stream down. -May be @code{NULL}. This function is called when @code{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. -@end deftypefn +But you said something about need a magic event to invoke redisplay? +Why is that? -@deftypefn {Lstream Method} Lisp_Object marker (Lisp_Object @var{lstream}, void (*@var{markfun}) (Lisp_Object)) -Mark this object for garbage collection. Same semantics as a standard -@code{Lisp_Object} marker. This function can be @code{NULL}. -@end deftypefn +April 2, 2000 -@node Consoles; Devices; Frames; Windows, The Redisplay Mechanism, Lstreams, 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; +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. -@menu -* Introduction to Consoles; Devices; Frames; Windows:: -* Point:: -* Window Hierarchy:: -* The Window Object:: -@end menu +April 5, 2000 -@node Introduction to 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; +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 -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. +@enumerate +@item +hide the logic to do this in the c code; the lisp code should do +nothing other than call (redisplay widget) - 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. +@item +make sure your event-cycling code processes @strong{NO} events at all. this +includes non-user events. queue the events instead. +@end enumerate - 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. +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. - 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. +April 6, 2000 -@node Point -@section Point -@cindex point +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. - 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}. +also, these dialog boxes, and this function make-dialog-frame, should -@node Window Hierarchy -@section Window Hierarchy -@cindex window hierarchy -@cindex hierarchy of windows +@enumerate +@item +be in @file{dialog.el}, not gutter-items.el. +@item +when possible, be placed in the interactive spec of standard lisp +functions rather than accessed directly from @file{menubar-items.el} +@item +wrapped in calls to should-use-dialog-box-p, so the user has control +over when dialog boxes appear. +@end enumerate - 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. +April 7, 2000 - 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. +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 @strong{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 @strong{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 @strong{have} to worry about pixel +heights and widths @strong{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: - Here are some rules: +@example +> 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 +> @strong{created} frame, so you end up in a catch 22 unless you do what I've done. +@end example + +[Ben proposes other ways to avoid exposing all the guts, as in +@code{make-gutter-only-dialog-frame}:] @enumerate @item -Horizontal combination windows can never have children that are -horizontal combination windows; same for vertical. +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. @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. +[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. +@end enumerate -@item -Every combination window must have at least two children. +April 15, 2000 +I don't understand when you say "the various types of callback". Are +you using the callback for various different purposes? -@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. +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. -@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. +April 17, 2000 -@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}. +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. -@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. +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. -@item -The list of children for a window is threaded through the -@code{next} and @code{prev} fields of each child window. +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? -@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. +@node Discussion -- Dialog Boxes, Discussion -- Multilingual Issues, Discussion -- Glyphs, Future Work Discussion +@section Discussion -- Dialog Boxes +@cindex discussion, dialog boxes +@cindex dialog boxes, discussion -@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 +@example +From: + Ben Wing <ben@@666.com> + 10/7/1999 5:57 PM -@node The Window Object -@section The Window Object -@cindex window object, the -@cindex object, the window + Subject: + Re: Animated gif patch (2) + To: + Andy Piper <andy@@xemacs.org> + CC: + xemacs-review@@xemacs.org, xemacs-beta@@xemacs.org - 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. +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. -@item dedicated -Non-@code{nil} if this window is dedicated to its buffer. +ben -@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. +From: + Ben Wing <ben@@666.com> + 9/7/1999 8:50 PM + + Subject: + Re: Layouts done + To: + Andy Piper <andyp@@beasys.com> + + + + +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 <ben@@666.com> + 8/10/1999 11:11 PM + + Subject: + Re: Widgets + To: + Andy Piper <andy@@xemacs.org> + + + + +I think you might have misinterpreted what i meant. I meant to say that XEmacs should +implement the @strong{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 @strong{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. -@item start -The position in the buffer that is the first character to be displayed -in the window. +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). -@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. +ben -@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. +From: + Ben Wing <ben@@666.com> + 7/21/1999 2:44 AM + + Subject: + Re: Tabs 'n widgets screenshot + To: + Andy Piper <andy@@xemacs.org> + 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 @strong{NOT} extra graphical junk +placed in the gutters of a buffer but are GUI objects with @strong{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 @strong{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 <ben@@666.com> + 6/30/1999 3:30 PM + + Subject: + Re: Focus Help! + To: + Andy Piper <andy@@xemacs.org> + CC: + Ben Wing <ben@@xemacs.org>, 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 @strong{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 @code{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 @file{simple.el} and @file{menubar-items.el}, do you think +you could add the @code{EnumPrinters()} +support and fix up the GUI? If you don't feel comfortable with the GUI, at +least do the @code{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. -@item left -This is the left-hand edge of the window, measured in columns. (The -leftmost column on the screen is @w{column 0}.) +ben -@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. +April 19, 2000 -@item width -The width of the window, measured in columns. +Kirill 'Big K' Katsnelson wrote: -@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. +> 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 + +@end example + +@node Discussion -- Multilingual Issues, Discussion -- Instantiators and Generic Property Accessors, Discussion -- Dialog Boxes, Future Work Discussion +@section Discussion -- Multilingual Issues +@cindex discussion, multilingual issues +@cindex multilingual issues, discussion + +@example + + 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 +@strong{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. -@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. +ben -@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. +From: + Ben Wing <ben@@666.com> + 12/23/1999 3:34 AM -@item use_time -This is the last time that the window was selected. The function -@code{get-lru-window} uses this field. + Subject: + Re: check process state before accessing coding_stream (fix PR#1061) + To: + "Stephen J. Turnbull" <turnbull@@sk.tsukuba.ac.jp> + CC: + XEmacs Developers <xemacs-beta@@xemacs.org> -@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. +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. -@item 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 @code{nil}. -@end table +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. -@node The Redisplay Mechanism, Extents, Consoles; Devices; Frames; Windows, Top -@chapter The Redisplay Mechanism -@cindex redisplay mechanism, the +ben - 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. +"Stephen J. Turnbull" wrote: - When working with the redisplay mechanism, remember the Golden Rules -of Redisplay: +> >>>>> "Ben" == Ben Wing <ben@@666.com> 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 <ben@@666.com> + 12/21/1999 2:22 AM + + Subject: + Re: check process state before accessing coding_stream (fix PR#1061) + To: + "Stephen J. Turnbull" <turnbull@@sk.tsukuba.ac.jp> + CC: + XEmacs Developers <xemacs-beta@@xemacs.org> -@enumerate -@item -It Is Better To Be Correct Than Fast. -@item -Thou Shalt Not Run Elisp From Within Redisplay. -@item -It Is Better To Be Fast Than Not To Be. -@end enumerate -@menu -* Critical Redisplay Sections:: -* Line Start Cache:: -* Redisplay Piece by Piece:: -@end menu -@node Critical Redisplay Sections -@section Critical Redisplay Sections -@cindex redisplay sections, critical -@cindex critical redisplay sections -Within this section, we are defenseless and assume that the -following cannot happen: -@enumerate -@item -garbage collection -@item -Lisp code evaluation -@item -frame size changes -@end enumerate +"Stephen J. Turnbull" wrote: + +> >>>>> "Ben" == Ben Wing <ben@@666.com> 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. -We ensure (3) by calling @code{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. +ben -If @code{Fsignal()} is called during this critical section, we -will @code{abort()}. +> +> +> -- +> 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 @file{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 <ben@@666.com> + 12/14/1999 11:00 PM + + Subject: + Re: Mule UI disaster: displaying character tables + To: + Hrvoje Niksic <hniksic@@iskon.hr> + CC: + XEmacs vs Mule <xemacs-mule@@xemacs.org> + + + + +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 +@strong{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 @strong{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. -If garbage collection is called during this critical section, -we simply return. #### We should abort instead. +ben -#### If a frame-size change does occur we should probably -actually be preempting redisplay. +Hrvoje Niksic wrote: -@node Line Start Cache -@section Line Start Cache -@cindex line start cache +> Ben Wing <ben@@666.com> 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 <ben@@666.com> + 12/14/1999 12:20 AM + + Subject: + Re: Mule UI disaster: displaying character tables + To: + "Stephen J. Turnbull" <turnbull@@sk.tsukuba.ac.jp> + CC: + XEmacs vs Mule <xemacs-mule@@xemacs.org> + + + + +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. - 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. +ben - 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. +"Stephen J. Turnbull" wrote: - 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? +> >>>>> "Hrvoje" == Hrvoje Niksic <hniksic@@iskon.hr> 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 <ben@@666.com> + 12/14/1999 10:28 PM + + Subject: + Re: Autodetect proposal; specifer questions/suggestions + To: + "Stephen J. Turnbull" <turnbull@@sk.tsukuba.ac.jp> + + + + +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 <ben@@666.com> 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 @file{<package>-faces.el} (or @file{<package>-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 <ben@@666.com> + 11/18/1999 9:02 PM + + Subject: + Re: Char-related crashes (hopefully) fixed + To: + "Stephen J. Turnbull" <turnbull@@sk.tsukuba.ac.jp> + CC: + XEmacs Beta List <xemacs-beta@@xemacs.org> + + + + +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 - 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. +> 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 <ben@@666.com> 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 @strong{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 <ben@@666.com> + 11/16/1999 11:03 PM + + Subject: + Re: Char-related crashes (hopefully) fixed + To: + Yoshiki Hayashi <t90553@@m.ecc.u-tokyo.ac.jp> + CC: + Hrvoje Niksic <hniksic@@iskon.hr>, + XEmacs Beta List <xemacs-beta@@xemacs.org> + + + + +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 @strong{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 <hniksic@@iskon.hr> 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. - 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: -@itemize @bullet -@item -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. -@item -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. -@end itemize +@end example - In case you're wondering, the Second Golden Rule of Redisplay is not -applicable. +@node Discussion -- Instantiators and Generic Property Accessors, Discussion -- Switching to C++, Discussion -- Multilingual Issues, Future Work Discussion +@section Discussion -- Instantiators and Generic Property Accessors +@cindex discussion, instantiators and generic property accessors +@cindex instantiators and generic property accessors, discussion + +From: Ben Wing <ben@@666.com> +Date: Sun, 05 May 2002 05:40:07 -0700 +Subject: generic functions, new instantiator API + +I've been reading the C++ manual and getting polymorphism, inheritance, +generic functions, etc. in my head. + +We have our own "generic function" already in terms of `get', `put', +etc. which accept various objects. i'm thinking of extending them so +they can accept, as well as objects, lists (either alists or plists) +or plist-style vectors, and manipulate their properties. what do +people think of this? + +Also, i'm designing a new API for "instantiators", which are objects +whose main purpose is to hold properties and provide a way of notifying +their containing specifiers when they change. Instantiator objects are +used when the instantiator gets sufficiently complicated that using +lists and vectors gets unwieldy -- e.g. when creating widget trees, such +as would appear in dialog boxes. you want the ability to +programmatically traipse up and down the tree and dynamically modify a +part of the tree -- e.g. a property on a single widget -- as necessary, +and have the internal code automatically notice this change and performs +any necessary updates. lists and vectors are too low-level for this -- +no way to get their parent, no way for internal code to be notified when +changes occur, can't always maintain object identity when making +property changes, no way to error-check illegal changes, etc. + +You could also extend this api to cover toolbars; it would probably make +toolbar manipulation significantly easier. but you'd have to think +about backward compatibility in such cases. + +here is what the api looks like so far -- making use of a newly-added +facility for keyword args in primitives. comments are welcome. + +@example +DEFUN ("make-instantiator", Fmake_instantiator, 1, MANY, 0, /* +Create a new instantiator object from TYPE and PROPS. +TYPE should be one of the image instantiator formats described in +`make-glyph'. +The rest of the arguments should be keyword properties and associated +values, +as also described in `make-glyph'. + +TYPE can also be an old-style vector instantiator. + +Instantiator objects can be used as instantiators (see `make-specifier') in +glyphs in place of old-style vector instantiators. They are especially +used for complicated, nested graphical elements such as widgets (buttons, +text fields, etc.) -- in fact, widget instantiators will automatically be +converted into instantiator objects if they are given in vector format. + +Individual properties on instantiators can be manipulated using +`set-instantiator-property'. If the property's value is a list (for +example, a list of children), you can also use `add-instantiator-item' +to add or insert individual elements in the list. + +`delete-instantiator-item' can be used to delete individual items in the +list; +`get-instantiator-item' to locate individual items in the list; and +`get-instantiator-item-position' to return the position of individual +items in +the list. + +`map-instantiator' can be used to (recursively or not) map over an +instantiator and its children. + +`find-instantiator' can be used to (recursively or not) locate an +instantiator +in a tree composed of an instantiator and its descendants. +*/ + /* (type &rest props) */ + (int nargs, Lisp_Object *args)) +@{ + /* ^^#### */ return Qnil; +@} -@node Redisplay Piece by Piece -@section Redisplay Piece by Piece -@cindex redisplay piece by piece +DEFUN ("set-instantiator-property", Fset_instantiator_property, 3, 3, 0, /* +Set property PROP to VALUE in INSTANTIATOR. +INSTANTIATOR should have been created with `make-instantiator'. +Valid properties depend on the instantiator type and are described in +`make-glyph'. For properties that are lists of items, individual items +can be added or deleted using `add-instantiator-item' and +`delete-instantiator-item'. + +For compatibility, this also accepts an old-style vector instantiator, and +destructively modifies it; in this case, adding a property requires +creating a new vector, which is returned. You need to use +`set-glyph-image' on glyphs, or `set-specifier-dirty-flag' on the result of +`glyph-image', to register instantiator changes to vector +instantiators. (New-style instantiators automatically convey property +changes to any glyphs they have been attached to.) +*/ + (instantiator, prop, value)) +@{ + Lisp_Object *elt; + int len; -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. + /* ^^#### */ + CHECK_VECTOR (instantiator); + if (!KEYWORDP (prop)) + invalid_argument ("instantiator property must be a keyword", prop); -Redisplay happens in three phases: + elt = XVECTOR_DATA (instantiator); + len = XVECTOR_LENGTH (instantiator); -@enumerate -@item -Determine desired display in area that needs redisplay. -Implemented by @code{redisplay.c} -@item -Compare desired display with current display -Implemented by @code{redisplay-output.c} -@item -Output changes Implemented by @code{redisplay-output.c}, -@code{redisplay-x.c}, @code{redisplay-msw.c} and @code{redisplay-tty.c} -@end enumerate + for (len -= 2; len >= 1; len -= 2) + @{ + if (EQ (elt[len], prop)) + @{ + elt[len + 1] = value; + break; + @} + @} -Steps 1 and 2 are device-independent and relatively complex. Step 3 is -mostly device-dependent. + /* Didn't find it so add it. */ + if (len < 1) + @{ + Lisp_Object alist = Qnil, result; + struct gcpro gcpro1; -Determining the desired display + GCPRO1 (alist); + alist = tagged_vector_to_alist (instantiator); + alist = Fcons (Fcons (prop, value), alist); + result = alist_to_tagged_vector (elt[0], alist); + free_alist (alist); + RETURN_UNGCPRO (result); + @} -Display attributes are stored in @code{display_line} structures. Each -@code{display_line} consists of a set of @code{display_block}'s and each -@code{display_block} contains a number of @code{rune}'s. Generally -dynarr's of @code{display_line}'s are held by each window representing -the current display and the desired display. + return instantiator; +@} -The @code{display_line} structures are tightly tied to buffers which -presents a problem for redisplay as this connection is bogus for the -modeline. Hence the @code{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. +DEFUN ("instantiator-property", Finstantiator_property, 2, 3, 0, /* +Return the property PROP of INSTANTIATOR, or DEFAULT if PROP has no value. +INSTANTIATOR should have been created with `make-instantiator'. +*/ + (instantiator, prop, default_)) +@{ + /* ^^#### */ return Qnil; +@} -The guts of @code{display_line} generation are in -@code{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. +DEFUN ("instantiator-properties", Finstantiator_properties, 1, 1, 0, /* +Return a plist of all defined properties in INSTANTIATOR. +INSTANTIATOR should have been created with `make-instantiator'. +*/ + (instantiator)) +@{ + /* ^^#### */ return Qnil; +@} -Gutter redisplay is different. Because the data to display is stored in -a string we cannot use @code{create_text_block}. Instead we use -@code{create_text_string_block} which performs the same function as -@code{create_text_block} but for strings. Many of the complexities of -@code{create_text_block} to do with cursor handling and selective -display have been removed. +DEFUN ("instantiator-type", Finstantiator_type, 1, 1, 0, /* +Return the type of INSTANTIATOR. +INSTANTIATOR should have been created with `make-instantiator'. +Valid types are the instantiator formats described in `make-glyph'. +*/ + (instantiator)) +@{ + /* ^^#### */ return Qnil; +@} -@node Extents, Faces, The Redisplay Mechanism, Top -@chapter Extents -@cindex extents +DEFUN ("instantiator-parent", Finstantiator_parent, 1, 1, 0, /* +Return the parent of INSTANTIATOR. +INSTANTIATOR should have been created with `make-instantiator'. +*/ + (instantiator)) +@{ + /* ^^#### */ return Qnil; +@} -@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. -@end menu +DEFUN_WITH_KEYWORDS ("map-instantiator", Fmap_instantiator, 2, 2, 1, 0, +0, /* +Map FUN recursively over INSTANTIATOR and its descendants. +FUN is called with one argument, the INSTANTIATOR. +If:norecurse is non-nil, don't recurse, just map over the direct +children (not including the instantiator itself). +*/ + (fun, instantiator), + (norecurse)) +@{ + /* ^^#### */ return Qnil; +@} -@node Introduction to Extents -@section Introduction to Extents -@cindex extents, introduction to +DEFUN_WITH_KEYWORDS ("find-instantiator", Ffind_instantiator, 3, 3, + 1, 0, 0, /* +Find an instantiator by PROP and VALUE in INSTANTIATOR and its descendants. +Returns first item which has PROP set to VALUE. +If:norecurse is non-nil, don't recurse, just look through the direct +children (not including the instantiator itself). +*/ + (instantiator, prop, value), + (norecurse)) +@{ + /* ^^#### */ return Qnil; +@} - 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. +DEFUN_WITH_KEYWORDS ("add-instantiator-item", Fadd_instantiator_item, 3, +3, 7, + 0, 0, /* +Add an item to an instantiator property that's a list of items. +\(E.g. the children of an instantiator). PROP is the property whose list of +items is being modified, and ITEM is the item to add. To insert somewhere +before the end, use one of the keywords: + +--:position specifies a zero-based index of an item, and the new item +will be +inserted just before the item indicated by the position. Negative numbers +count from the end -- thus -1 will cause insertion before the last item, -2 +before the second-to-last item, etc. + +--:before-item and :after-item specify items to insert before or after. +:test (defaults to `eq') can be used to specify the way to compare the given +item with existing items. + +--:before-property and :after-property search for an item to insert +before or +after by looking for an item with the given property. If :value is +given, the +property must have that value; otherwise, it simply must exist. This method +of insertion works if the items in PROP's list are anything that can have or +hold properties. \("To have and to hold, for ever and ever ...") This +includes: - Extent endpoints are stored using memory indices (see @file{insdel.c}), -to minimize the amount of adjusting that needs to be done when -characters are inserted or deleted. +-- any object for which `get' works +-- else, if object is a vector, assume it's a plist-style vector +-- else, if object is a cons, and its first element is also a cons, + assume it's an alist +-- else, if object is a cons, assume it's a plist +*/ + (instantiator, prop, item), + (position, before_item, after_item, test, + before_property, after_property, value)) +@{ + /* ^^#### */ return Qnil; +@} - (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.) +DEFUN_WITH_KEYWORDS ("delete-instantiator-item", Fdelete_instantiator_item, + 2, 2, 5, 0, 0, /* +Delete an item in an instantiator property that's a list of items. + +\(E.g. the children of an instantiator). PROP is the property whose list is +being searched. One of these keywords should be given: + +--:position specifies a zero-based index of an item. Negative numbers +count from the end -- thus -1 will cause insertion before the last item, -2 +before the second-to-last item, etc. + +--:item specifies the item to delete. :test (defaults to `eq') can be +used to +specify the way to compare the given item with existing items. + +--:property searches for an item with the given property. If :value is +given, the property must have that value; otherwise, it simply must exist. +This method of insertion works if the items in PROP's list are anything that +can have or hold properties -- see `add-instantiator-item'. +*/ + (instantiator, prop), + (item, test, position, property, value)) +@{ + /* ^^#### */ return Qnil; +@} -@node Extent Ordering -@section Extent Ordering -@cindex extent ordering +DEFUN_WITH_KEYWORDS ("get-instantiator-item", Fget_instantiator_item, + 2, 2, 3, 0, 0, /* +Get an item in an instantiator property that's a list of items. + +\(E.g. the children of an instantiator). PROP is the property whose list is +being searched. One of these keywords should be given: + +--:position specifies a zero-based index of an item. Negative numbers +count +from the end -- thus -1 will cause insertion before the last item, -2 before +the second-to-last item, etc. + +--:property searches for an item with the given property. If :value is +given, the property must have that value; otherwise, it simply must exist. +This method of insertion works if the items in PROP's list are anything that +can have or hold properties -- see `add-instantiator-item'. +*/ + (instantiator, prop), + (position, property, value)) +@{ + /* ^^#### */ return Qnil; +@} - Extents are compared using memory indices. There are two orderings -for extents and both orders are kept current at all times. The normal -or @dfn{display} order is as follows: +DEFUN_WITH_KEYWORDS ("get-instantiator-item-position", + Fget_instantiator_item_position, + 2, 2, 4, 0, 0, /* +Return an item's position in an instantiator property that's a list of +items. + +\(E.g. the children of an instantiator). PROP is the property whose list is +being searched. One of these keywords should be given: + +--:item specifies the item to search for. :test (defaults to `eq') can be +used to specify the way to compare the given item with existing items. + +--:property searches for an item with the given property. If :value is +given, the property must have that value; otherwise, it simply must exist. +This method of insertion works if the items in PROP's list are anything that +can have or hold properties -- see `add-instantiator-item'. +*/ + (instantiator, prop), + (item, test, property, value)) +@{ + /* ^^#### */ return Qnil; +@} -@example -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 +DEFUN ("image-instance-instantiator", Fimage_instance_instantiator, 1, +1, 0, /* +Return the instantiator from which IMAGE-INSTANCE was created. +*/ + (image_instance)) +@{ + /* ^^#### */ return Qnil; +@} @end example - So if two extents begin at the same position, the larger of them is the -earlier one in the display order (@code{EXTENT_LESS} is true). - - For the e-order, the same thing holds: +some other useful stuff: @example -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 +DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /* +Return a new `image-instance' object. + +Image-instance objects encapsulate the way a particular glyph (pixmap, +widget, etc.) is displayed on a particular device. In most circumstances, +you do not need to directly create image instances; instead, you create a +glyph using `make-glyph' and add settings (or "instantiators") onto it +using `set-glyph-image', and XEmacs creates the image instances as +necessary. However, it may occasionally be useful to explicitly create +image instances, if you want more control over the instantiation process. + +For more information on instantiators and instances, see `make-specifier'. + +DATA is an image instantiator, which describes the image; see `make-glyph' +for a description of the allowed values. + +The most likely circumstance where you need to deal directly with image +instances is in widget callbacks -- e.g. the callback that's executed when +a button is pressed in a dialog box of type `general' (see +`make-dialog-box'). In this case, the widget that was activated is +described by an image instance. (The callback is usually be written as an +interactive function with an interactive spec of (interactive \"e\"), and a +single `event' argument. The event will be an activate event, describing +the user action that trigged the callback. The image instance is +retrievable from the event using `event-image-instance'. Handling the +action may involve setting properties on the image instance or other image +instances in the dialog box in which the widget is usually contained -- or +changing the instantiator that generated the image instance, if you want +permanent changes that will be reflected the next time the dialog box is +popped up. Properties on an image instance are set using +`set-image-instance-property'. If the widget is part of a hierarchy of +widgets (as is usually the case in a dialog box, but may not apply if the +widget was inserted by itself in a buffer [by creating a glyph and +attaching it to an extent -- see `make-glyph']), there will be a +corresponding hierarchy of image instances to describe this particular +instance of the dialog box. You can retrieve other image instances in the +hierarchy using primitives such as `image-instance-parent', +`image-instance-children', and `find-image-instance'. @end example - So if two extents end at the same position, the smaller of them is the -earlier one in the e-order (@code{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''. -@node Format of the Extent Info -@section Format of the Extent Info -@cindex extent info, format of the - An extent-info structure consists of a list of the buffer or string's -extents and a @dfn{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 @code{_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 @code{_force} version if you need the extent_info -structure to be there. +@example +(defun image-instance-property (image-instance property &optional default) + "Return the given property of the given image instance. +Returns DEFAULT if the property or the property method do not exist for +the image instance in the domain." + (check-argument-type 'image-instance-p image-instance) + (get image-instance property default)) + +(defun set-image-instance-property (image-instance prop value) + "Set the property PROP on IMAGE-INSTANCE to VALUE. +Only certain properties of the image instance can be changed, and they +represent \"temporary\" changes. If you want to make permanent changes, +you need to change the instantiator that generated the instance -- +retrieve the instantiator with `image-instance-instantiator', and change +its properties with `set-instantiator-property'. + +This applies mostly to widgets. For example, you can set a property on +a widget image instance to change the state of a radio or checkbox button, +set the text currently in an edit field, etc. However, those changes apply +only to the *currently* displayed widgets. If these widgets are in a dialog +box, and you want to change the way the widgets in the dialog box appear +*each* time the dialog box is displayed, you need to change the +instantiator. + +Make sure you understand the difference between instantiators and +instances. An \"instantiator\" is a specification, indicating how to +determine the value of a setting whose value can vary in different +circumstances or \"locales\" (buffers, frames, etc.). An \"instance\" +is the +resulting value in a particular circumstance. For more information, see +`make-specifier'." + (check-argument-type 'image-instance-p image-instance) + (put image-instance prop value)) +@end example + +From: "Stephen J. Turnbull" <stephen@@xemacs.org> +Date: 06 May 2002 16:40:46 +0900 + +>>>>> "Ben" == Ben Wing <ben@@666.com> writes: + + Ben> We have our own "generic function" already in terms of `get', + Ben> `put', etc. which accept various objects. + +I proposed extending the class to stuff like charsets about two years +ago, and I think you were one of the folks who objected. + + Ben> i'm thinking of extending them so they can accept lists + Ben> (either alists or plists) or plist-style vectors, and + Ben> manipulate their properties. what do people think of this? + +I think extending to lists is something we should approach +cautiously. For one thing, if "get" is polymorphic, "put" would have +to be too. But how does it decide when dealing with "nil"? + + Ben> you want the ability to programmatically traipse up and down + Ben> the tree and dynamically modify a part of the tree -- e.g. a + Ben> property on a single widget -- as necessary, and have the + Ben> internal code automatically notice this change and performs + Ben> any necessary updates. + +I like this. + +From: "Stephen J. Turnbull" <stephen@@xemacs.org> +Date: 07 May 2002 11:17:05 +0900 + +>>>>> "Neal" == Neal D Becker <nbecker@@hns.com> writes: + + Neal> I thought that generic polymorphism was inherent in lisp, as + Neal> it is dynamically evaluated. Why would you need anything + Neal> special in the way functions are written to support generic + Neal> programming? + +I think it's basically a technical matter. We have a number of +objects that have property lists besides symbols. Many of them have +special functions (coding-system-get, coding-system-property, +charset-property are examples I find particularly obnoxious). I would +like to make these obsolete by allowing `get' on charsets, coding +systems, etc. + +And currently we have + +(let ((p (symbol-plist symbol))) (plist-get p prop)) + +Ben would like to allow + +(let ((p (symbol-plist symbol))) (get p prop)) + +with `get' determining whether P is a plist or an alist. And where +Michael says "why not use hash tables?", I see `(get hash key)' +(probably to Michael's horror ;-). + +This isn't Lisp any more, though, in some sense. But then we haven't +been that for years. AFAIK all real Lisps restrict `get' to symbols. + +From: sperber@@informatik.uni-tuebingen.de (Michael Sperber [Mr. Preprocessor]) +Date: Tue, 07 May 2002 08:52:53 +0200 + +Indeed. I'll just say "goosebumps." But I don't see why it has to be +GET that accesses the plist. You just build more dispatch into GET +with no immediate benefit to the API. Ad-hoc genericity gets you +something when there's some place in the code you don't know what the +underlying object is. I don't see this being the case here. Why do +you find them "obnoxious?" + +Stephen> This isn't Lisp any more, though, in some sense. But then we haven't +Stephen> been that for years. AFAIK all real Lisps restrict `get' to symbols. + +Actually, Scheme (which admittedly isn't a real Lisp by many +standards) doesn't have get/put at all. And good riddance, I might +add:-) + +From: "Stephen J. Turnbull" <stephen@@xemacs.org> +Date: 07 May 2002 20:04:50 +0900 + +>>>>> "ms" == Michael Sperber <sperber@@informatik.uni-tuebingen.de> writes: + +Stephen> special functions (coding-system-get, coding-system-property, +Stephen> charset-property are examples I find particularly obnoxious). I would +Stephen> like to make these obsolete by allowing `get' on charsets, coding +Stephen> systems, etc. + + ms> But I don't see why it has to be GET that accesses the plist. + ms> You just build more dispatch into GET with no immediate + ms> benefit to the API. Ad-hoc genericity gets you something when + ms> there's some place in the code you don't know what the + ms> underlying object is. I don't see this being the case here. + ms> Why do you find them "obnoxious?" + +Their semantics are basically `get'. Why not use that name? Of +course I agree that it doesn't have to be `get', but why clutter +things up? + +But those are particularly obnoxious because of the object/name +confusion they have built in. Ie, my real problem with them is more +ancient Mule idiom than the *-get or *-property names for the API. + + ms> Actually, Scheme (which admittedly isn't a real Lisp by many + ms> standards) doesn't have get/put at all. + +What does it use instead? (And no, you can't bait _me_ with Lisp +definition trolls, I think of XML as "declarative LISP with fat, +flavored, fuzzy parentheses.") + +From: sperber@@informatik.uni-tuebingen.de (Michael Sperber [Mr. Preprocessor]) +Date: Tue, 07 May 2002 13:26:13 +0200 + +Stephen> Their semantics are basically `get'. Why not use that name? + +Because it doesn't convey as much information in the source code as it +could, and because it provides less type checking than it could. + +Stephen> What does it use instead? + +What for? I've never felt the desire to use them, and it seems to me +that in Lisp, properties are usually used for one of two purposes: + +- As a poor man's replacement for hash tables. + +- To store data which should really be stored inside the object + itself. + +In the former case, I use a hash table. In the latter case, I store +the data in the object itself. + +@node Discussion -- Switching to C++, Discussion -- Windows External Widget, Discussion -- Instantiators and Generic Property Accessors, Future Work Discussion +@section Discussion -- Switching to C++ +@cindex discussion, switching to c++ +@cindex switching to c++, discussion + +From: "Ben Wing" <ben@@666.com> +Date: Fri, 10 May 2002 19:42:53 -0700 + +i know i'm opening up a bag of worms by suggesting this, but what +about moving to C++? I know others advocate this (Jan, Martin), and +the more I read Stroustrup's 3rd edition, the more I realize that +*HUGE* armounts of code in XEmacs, and in particular most of the +really hairy and hard-to-understand stuff -- lots of weird macros, +faux object-oriented stuff implemented in multiple places, each +differently (Lisp objects; methods on consoles/devices/etc; specifier +sub-types; coding-system sub-types; image-instance device methods; +image-instance format methds; etc.), all the GCPROS (which could go +entirely), dynarrs, eistring, etc. etc. -- is simply superseded by +stuff already built into C++ or supplied by the standard libraries. +Just now, I was going through the redisplay code, and noticing the +huge amount of duplication between gtk and X, something that's hard to +fix [except through super ad-hoc ways like using a .c file as a .h +file to "generate" lots of similar but slightly different code] in C, +but is extremely easy in C++ using inheritance [and/or templates]. +for example, instead of having just one layer of device methods, you'd +have + +@example +general -> tty + -> windowing -> mswindows + -> xlike -> x, gtk +@end example + +which would nicely and naturally encapsulate lots of duplicated [and +thus, hard to maintain] code. + +even more of a win would be the GCPRO's. Taking advantage of +constructors and destructors, we could simply do away [COMPLETELY!] +with explicitly gcproing, and still have everything gcpro'd. [in fact, +much more reliably -- none of the dreaded "temporary" problem, and +every reference is always gcpro'd so we have greater flexibility for +GC work -- take note, Michael :-) -- e.g. we could safely garbage +collect when allocating, and we could even implement a relocating +garbage collector. in the few places where performance might be an +issue [i seriously doubt there'd be many of them], we simply use a +separate Lisp_Object_No_GCPRO class (presumably a base class of +Lisp_Object), and manually handle the GCPRO's ourselves. If we needed +to distinguish here between static and dynamic objects, or static +vs. local vs. heap, we could do so easily with bit flags in the object +pointed to -- we have space for lots of them. + +code reliablity and maintainability would likely substantially +increase due to the ability to express most things in a natural C++ +way instead of lots of weird hackish hard-to-understand C stuff +implementing stuff the language wasn't really designed for. +Furthermore, there are even some possibilities for increased speed -- +many operations that can only reasonably be done now using Lisp +objects (and the associated gc overhead and such) could be done using +the high-level built-in facilities of C++, which in their ease of use +approach Lisp; and C++ has `inline' built-in, so we could easily add +various container classes to improve the understandability of the code +without loss of performance. + +finally, making the "switch" is trivial, since martin did the initial +work making XEmacs C++-safe and I've been keeping it that way -- I +regularly build under C++ and fix any problems. All we'd need to do +is switch the compiler and start gradually introducing C++ constructs +as we feel like it. + +for those concerned that dumping might stop working, [a] i don't think +it would, [b] the portable dumper has come of age -- i use it almost +all the time, and it's rock-solid and not obviously slower than +unexec. + +the only major concern that i see is the quality of the C++ +implementations out there, in particular G++, which is the most widely +available. I know that 6 years ago G++ was a bit rocky -- I went to +interview for Netscape, and they mentioned having to rely on various +vendor implementations of C++, whereas they would have preferred G++ +if it was reliable, due to the sameness of environment. But that was +*SIX YEARS* ago! Stroustrup 3rd Edition has been out for 5 years now, +and it defines, as far as I know, ANSI Standard C++ -- so that's at +least 5 years to implement a standard. It's hard to believe that G++ +isn't completely reliable now; but I do not have as much experience as +others. + +What do you think? I would *really* like to make this change, as it +would immensely facilitate lots of code I'm working on and will be +working on, plus of course add all the above benefits once we get +around to converting the code. + +From: "Stephen J. Turnbull" <stephen@@xemacs.org> +Date: 11 May 2002 15:34:08 +0900 + +I don't have a real problem with it, as long as we're very +conservative about it, ie, using C++ as "clean C with classes", and +introducing things slowly. Implement everything ourselves, avoid the +standard class libraries. + +I've been following the Python lists recently, and although the bias +is easy to guess, it's interesting to note that the people who are +most anti-C++ are typically the ones who are world-class C++ +programmers with big projects under their belts. Many of them +actually advocate using C rather than C++. + +I do worry that with Martin currently out of the picture we don't have +an active C++ standards bigot and implementation collector to deal +with compiler-specific issues. We do OK with C, but C++ is a much +more complex, subtle language. Is there anybody else to plausibly +take on that role? + +From: Hrvoje Niksic <hniksic@@arsdigita.com> +Date: Sun, 12 May 2002 20:58:50 +0200 + +I'm strongly opposed to this. Here are some reasons: + +* C++ may fix some problems, but it will introduce others, some of + which may be much harder to fix. XEmacs is already a large program, + hard to understand. C++ will not improve things. + +* XEmacs will suddenly become uncompilable and unusable in + many environments where it used to build perfectly fine -- for + example, those that don't ship with a C++ compiler at all. We could + "make GCC 3 a requirement", but I don't like that idea. + +* People without C++ experience will no longer be able to hack XEmacs. + I'd be the first one to leave. For example, I know quite a few + programmers who don't care for Qt and KDE simply because it's C++. + +* C is the /lingua franca/ of free software development. If we're + switching languages, it should be for a good reason and to something + we agree is an improvement (e.g. Common Lisp). + +* C++ is not the be-all end-all to everything. People who undestand + it well are usually the first ones to warn against it. It's + possible that they were scarred by using C++ at a bad time, but I'd + think twice before discounting their advice or blindly believing + that C++ is now all better. + +If you were writing a new project, I'd say go for it. But at this +point, this seems like a needless tweak. Do we really need *more* +internal reorganizations? Shouldn't we work on user-visible features? +Wasn't that what you yourself advocated when I talked to you? + +From: Didier Verna <didier@@xemacs.org> +Date: Tue, 14 May 2002 11:21:32 +0200 + + Switching to C++ has been suggested for the first time at the M17n'99 +conference in Japan IIRC. Although it was around a table with many empty +bottles of beer on it :-), I've kept some hope from that time. I'm happy to +see Ben in favor of this today. This idea coming from him is likely to have +more impact than when it comes from me or Yan of whoever else. + + There are several points that make me in favor of this change: + +- C++ support is already there thanks to Martin. + +- The amount of OO simulation code written in C in XEmacs is *HUGE*. But more + important, this code simulates *BASIC* OO features that are not any more a + problem for any C++ compiler. I mean, by just using the basic features of + C++ in terms of OO and data abstraction (classes, inheritance, methods (with + inlining), operators overloading), we'll win big time in code size, + readability, maintainability, and correctness. + +- the fact that *basic* OO support is already a major gain is very important + to me. You don't have to go generic programming with templates everywhere to + write an OO XEmacs[1]. Switching to C++ can be completely gradual, and we + can even stop early in the C++ features we use. That will already be a big + gain. That's also the advantage over the idea of using another more modern + language to rewrite the core; something completely unrealistic. + +- there is another important aspect on the design issue: many people + (including from the industry) have worked on abstracting common problems in + an OO philosophy. Some people claim that the concepts that emerged from this + kind of work of just C++ specific hackery, and they're probably right, but + anyway that's obviously not a problem for us. Any C++ writer should have the + "Design Patterns" book in hand. It already has good design solutions for + many problems that we're facing in XEmacs (like, supporting more than one + widget set), because these problems are so *common*. By using C++ we can + directly benefit from the experience of other large applications designers. + + +Footnotes: +[1] We're working on GP in C++ in our lab here and we trigger bugs in gcc 3. + But you should see the code in question, it's pure template and static + programming. Things that XEmacs will never need. + +From: Daniel Pittman <daniel@@rimspace.net> +Date: Sat, 11 May 2002 19:15:04 +1000 + + I've been following the Python lists recently, and although the bias +> is easy to guess, it's interesting to note that the people who are +> most anti-C++ are typically the ones who are world-class C++ +> programmers with big projects under their belts. Many of them +> actually advocate using C rather than C++. + +I wouldn't class myself as "world-class", but I can understand this +perspective based on my experiences with large projects that aim for +portability to vendor compilers, not just gcc. + +The biggest problem, assuming that you are willing to ignore platforms +like Sinix-PC[1] and their poor compiler support[2] is that it's easy to +shoot yourself in the foot with C++. + + +The biggest portability problems are namespaces, the standard C++ +library and template support, in about that order, followed by exception +handling. + +Very few things get namespaces right, even today, with gcc being one of +the worst. Tempting as they are, they are best avoided where possible, +except in compiler and platform specific code.[3] + + +The standard C++ library, which supports RTTI and a few other things +including the [io]stream tools, is less than totally reliable although +it can be used with relative safety most places. + +What you really need to watch out for with that is the extensions that +every vendor in the universe has added to their collections because +there isn't any standard way of doing common things in most of these +areas. + + +The Standard Template Library isn't. Aside from a tendency to expose +limitations of symbol name lengths[4] the library tends to be unreliable +in behavior between compilers and platforms. Not enough to make simple +things fail, though, just enough to make it occasionally do odd things +or show up obscure bugs in your code... - A list of extents is maintained as a double gap array. One gap array -is ordered by start index (the @dfn{display order}) and the other is -ordered by end index (the @dfn{e-order}). Note that positions in an -extent list should logically be conceived of as referring @emph{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). +It's also not very well designed, I think, as libraries go. That's a +personal opinion, though, and not universal. -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: -@enumerate -@item -They are space efficient, as there is no need for next/previous pointers. +C++ exceptions are an interesting issue. They can work extremely well as +a mechanism for managing errors and improve the reliability of the +system. -@item -If the items in them are sorted, locating an item is fast -- @math{O(log N)}. +They can also become an unending nightmare of epic proportions, causing +more pain and suffering than you can imagine. :/ -@item -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. +The main difference between the two situations, so far as I can tell, +comes from two aspects of design that have ... far reaching +implications. + +If you try adding exceptions to code that isn't ready to deal with them, +things tend to go very badly wrong. I /think/ that the existing +exception mechanisms in XEmacs would be similar enough that this isn't +the case, though. + +The other is that you need to base your code very strongly around the +"construction acquires, destruction releases" model of resource +handling. This, of course, implies using exceptions everywhere because +you /can't/ use that model in C++ without them.[5] + +Again, I think that the existing XEmacs model will probably work well +with this, but I am hardly an expert at either; my only real-world +experience is the one project where I gained these impressions and the +knowledge of the suffering they can bring. :) + + +Oh, and finally, watch out for operator overloading -- including casts. +These are very easy to abuse into a position where your code is +impossible for others to understand. + +I would also advocate avoiding multiple inheritance, but that's because +my personal design experience says that it's almost always a sign of bad +design. Views there vary greatly. + +> I do worry that with Martin currently out of the picture we don't have +> an active C++ standards bigot and implementation collector to deal +> with compiler-specific issues. + +You probably have more need of the second than the first. There are not +many things you actually need a standards bigot for; just write good C +and don't use too many things other than classes. + +> We do OK with C, but C++ is a much more complex, subtle language. + +C with classes, or the limited subset of C++ that doesn't include +templates, exceptions or RTTI is not much more complex than standard C. + +If you add exceptions to that you will probably not notice anything but +a syntax change in the core, given their current standing. Er, they +probably don't work right in signal handlers, though, because they don't +know anything about them.[6] + +> Is there anybody else to plausibly take on that role? + +I would be happy to look at things that were publicly discussed on the +topic but I don't think I have the experience or the knowledge of the +XEmacs development process to do anything more than that. + +Not, I imagine, that anyone would ask. :) + + Daniel + +Footnotes: +[1] Archaic Unix ported to i386 from a minicomputer over a decade ago. + +[2] The vendor C++ would segfault on anything that had multiple + inheritance. :) + +[3] I found them invaluable in resolving a few Win9x vn WinNT symbol + conflicts, for example, but that's obviously target-specific. + +[4] The current record for STL-generated name length that I have seen + is a symbol 892 characters long... + +[5] The lack of a return code from a class constructor is the killer + issue here. + +[6] This, I believe, varies from vendor to vendor. :) + + +@node Discussion -- Windows External Widget, Discussion -- Packages, Discussion -- Switching to C++, Future Work Discussion +@section Discussion -- Windows External Widget +@cindex discussion, windows external widget +@cindex windows external widget, discussion + +@example + +Subject: + Re: External Widget Support for Xemacs on nt + Date: + Sat, 08 Jul 2000 01:47:14 -0700 + From: + Ben Wing <ben@@666.com> + To: + Timothy.Fowler@@msdw.com + CC: + xemacs-nt@@xemacs.org + References: + 1 + + + + +Nothing is currently done for external widget support under XEmacs but +it should not be too hard to do and would be a great addition to +XEmacs. What you would probably want to do is create an XEmacs control +that has an interface something like the built-in edit control and +which communicates to an existing XEmacs process using DDE. (Basically +you would modify XEmacs so that it registered itself as a DDE server +accepting external widget requests, and then the external edit control +would simply send a DDE request and the result would be a handle of +some sort used for future communication with that particular XEmacs +process.) + +There are two basic issues in getting the external widget to work, +which are display and input. Although I am not completely sure, I have +a feeling that it is possible for one process to write into the window +of another process, simply by using that window's HWND handle. If so +it should be extremely easy to get the output working (this is exactly +the approach used under Xt). For input, you would probably again want +to do what is done under Xt, which is that the client widget simply +passes all of the appropriate messages to the XEmacs server process +using whatever communication channel was set up, e.g. DDE, and the +XEmacs server processes them normally. Very few modifications would be +needed to the XEmacs source code and all of the necessary +modifications could be done simply by looking for existing external +widget code in XEmacs. + +If you are interested in continuing this, I will certainly give you +any support you need along the way. This would be a great project to +be added to XEmacs. + + + +Timothy Fowler wrote: + +> I am looking into external widget support for xemacs nt similar to that +> existing in xemacs for X +> Have any developement efforts been made in this direction in the past? +> Is there any current effort? +> Any insight into the complexity of achieving this? +> Any comments would be greatly appreciated +> Thanks +> Tim Fowler + +-- +Ben + +In order to save my hands, I am cutting back on my mail. I also write +as succinctly as possible -- please don't be offended. If you send me +mail, you _will_ get a response, but please be patient, especially for +XEmacs-related mail. If you need an immediate response and it is not +apparent in your message, please say so. Thanks for your understanding. + +See also http://www.666.com/ben/chronic-pain/ + + +Subject: + RE: External Widget Support for Xemacs on nt + Date: + Mon, 10 Jul 2000 12:40:01 +0100 + From: + "Alastair J. Houghton" <ajhoughton@@lineone.net> + To: + "Ben Wing" <ben@@666.com>, <xemacs-nt@@xemacs.org> + CC: + <Timothy.Fowler@@msdw.com> + + + + +> -----Original Message----- +> From: owner-xemacs-nt@@xemacs.org [mailto:owner-xemacs-nt@@xemacs.org]On +> Behalf Of Ben Wing +> Sent: 08 July 2000 09:47 +> To: Timothy.Fowler@@msdw.com +> Cc: xemacs-nt@@xemacs.org +> Subject: Re: External Widget Support for Xemacs on nt +> +> Nothing is currently done for external widget support under +> XEmacs but it should +> not be too hard to do and would be a great addition to XEmacs. +> What you would +> probably want to do is create an XEmacs control that has an +> interface something +> like the built-in edit control and which communicates to an +> existing XEmacs +> process using DDE. + +It would be @strong{much} better to use RPC or COM rather than DDE - and +also it would provide a more useful interface to XEmacs (like the +Microsoft rich text edit control that is used by Wordpad). It +would probably also be easier... + +> If you are interested in continuing this, I will certainly give +> you any support +> you need along the way. This would be a great project to be added +> to XEmacs. + +I agree. This would be a *really useful* thing to do... + +Regards, + +Alastair. + +____________________________________________________________ +Alastair Houghton ajhoughton@@lineone.net + +Subject: + Re: External Widget Support for Xemacs on nt + Date: + Mon, 10 Jul 2000 22:56:06 -0700 + From: + Ben Wing <ben@@666.com> + To: + "Alastair J. Houghton" <ajhoughton@@lineone.net> + CC: + xemacs-nt@@xemacs.org, Timothy.Fowler@@msdw.com + References: + 1 + + + + +sounds good. i don't know too much about windows ipc methods, so i suggested +dde just as an example. + +"Alastair J. Houghton" wrote: + +> > -----Original Message----- +> > From: owner-xemacs-nt@@xemacs.org [mailto:owner-xemacs-nt@@xemacs.org]On +> > Behalf Of Ben Wing +> > Sent: 08 July 2000 09:47 +> > To: Timothy.Fowler@@msdw.com +> > Cc: xemacs-nt@@xemacs.org +> > Subject: Re: External Widget Support for Xemacs on nt +> > +> > Nothing is currently done for external widget support under +> > XEmacs but it should +> > not be too hard to do and would be a great addition to XEmacs. +> > What you would +> > probably want to do is create an XEmacs control that has an +> > interface something +> > like the built-in edit control and which communicates to an +> > existing XEmacs +> > process using DDE. +> +> It would be @strong{much} better to use RPC or COM rather than DDE - and +> also it would provide a more useful interface to XEmacs (like the +> Microsoft rich text edit control that is used by Wordpad). It +> would probably also be easier... +> +> > If you are interested in continuing this, I will certainly give +> > you any support +> > you need along the way. This would be a great project to be added +> > to XEmacs. +> +> I agree. This would be a *really useful* thing to do... +> +> Regards, +> +> Alastair. +> +> ____________________________________________________________ +> Alastair Houghton ajhoughton@@lineone.net + +-- +Ben + +In order to save my hands, I am cutting back on my mail. I also write +as succinctly as possible -- please don't be offended. If you send me +mail, you _will_ get a response, but please be patient, especially for +XEmacs-related mail. If you need an immediate response and it is not +apparent in your message, please say so. Thanks for your understanding. + +See also http://www.666.com/ben/chronic-pain/ + +@end example + + +@node Discussion -- Packages, Discussion -- Distribution Layout, Discussion -- Windows External Widget, Future Work Discussion +@section Discussion -- Packages +@cindex discussion, packages +@cindex packages, discussion + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@subheading Important package-related changes + +This file details changes that make the package system no longer an +unmitigated disaster. This way, at the very least, people can +essentially ignore the package system and not get bitten horribly the +way they currently do. +@enumerate @item -Code to manipulate them is relatively simple to write. -@end enumerate - -An alternative would be balanced binary trees, which have guaranteed -@math{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. +A single tarball containing absolutely everything and named +xemacs-21.2.68.tar.gz. This must contain absolutely everything, +including all of the packages, and in the proper directory +structure, so that the paradigm for -@node Zero-Length Extents -@section Zero-Length Extents -@cindex zero-length extents -@cindex extents, zero-length +untar; configure; make; make install - 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 @code{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: +just works. -@enumerate @item -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. +Fixed startup slowdown when all packages are installed so that +there is absolutely no penalty to having them all installed. This +may be hard. @item -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. -@end enumerate - - 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. +All files on the ftp site should be accessible through http. -@node Mathematics of Extent Ordering -@section Mathematics of Extent Ordering -@cindex mathematics of extent ordering -@cindex extent mathematics -@cindex extent ordering +@item +Put symlinks into the distribution directory to the appropriate +files in the package directory. -@cindex display order of extents -@cindex extents, display order - 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 +@item +Eliminate the confusing SUMO name, choosing a much more obvious +name such as all-packages. -@enumerate @item -Locate where an extent would go if inserted into the list. +There should be no separation of mule and non-mule packages. + @item -Insert an extent into the list. +Having 2 packages that conflict with each other should be +completely disallowed. + @item -Remove an extent from the list. +Fix vc and ps-print so that there is only ONE version. + @item -Map over all the extents that overlap a range. +Fix up all of the READMEs on the distribution site to make it +abundantly clear what needs to be obtained, where to get it, and +how to install it, especially with regards to packages. @end enumerate - (4) requires being able to determine the first and last extents -that overlap a range. +@node Discussion -- Distribution Layout, , Discussion -- Packages, Future Work Discussion +@section Discussion -- Distribution Layout +@cindex discussion, distribution layout +@cindex distribution layout, discussion - NOTE: @dfn{overlap} is used as follows: -@itemize @bullet -@item -two ranges overlap if they have at least one point in common. -Whether the endpoints are open or closed makes a difference here. -@item -a point overlaps a range if the point is contained within the -range; this is equivalent to treating a point @math{P} as the range -@math{[P, P]}. -@item -In the case of an @emph{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 @code{map-extents} maps over, since @code{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. -@end itemize +@example +From: + Ben Wing <ben@@666.com> + 10/15/1999 8:50 PM -First, define @math{>}, @math{<}, @math{<=}, etc. as applied to extents -to mean comparison according to the display order. Comparison between -an extent @math{E} and an index @math{I} means comparison between -@math{E} and the range @math{[I, I]}. + Subject: + VOTE: Absolutely necessary changes to file naming in releases + To: + SL Baur <steve@@xemacs.org>, + XEmacs Reviews <xemacs-review@@xemacs.org> -Also define @math{e>}, @math{e<}, @math{e<=}, etc. to mean comparison -according to the e-order. -For any range @math{R}, define @math{R(0)} to be the starting index of -the range and @math{R(1)} to be the ending index of the range. -For any extent @math{E}, define @math{E(next)} to be the extent directly -following @math{E}, and @math{E(prev)} to be the extent directly -preceding @math{E}. Assume @math{E(next)} and @math{E(prev)} can be -determined from @math{E} in constant time. (This is because we store -the extent list as a doubly linked list.) -Similarly, define @math{E(e-next)} and @math{E(e-prev)} to be the -extents directly following and preceding @math{E} in the e-order. +Everybody except Steve seems to agree that we need to provide a single +tar file containing the entire XEmacs tree whenever we release a new +version of XEmacs (beta or not). Therefore I propose the following +simple changes, and ask for a vote. If it is the general will of the +developers, then Steve @strong{WILL} make these changes. This is the +definition of cooperative development -- no one, not even the +maintainer, can assert absolute power over anything. -Now: +I propose (assuming, for example, release 21.2.20): -Let @math{R} be a range. -Let @math{F} be the first extent overlapping @math{R}. -Let @math{L} be the last extent overlapping @math{R}. +1. xemacs-21.2.20.tar.gz -> xemacs-21.2.20-core.tar.gz -Theorem 1: @math{R(1)} lies between @math{L} and @math{L(next)}, -i.e. @math{L <= R(1) < L(next)}. +2. xemacs-sumo.tar.gz -> xemacs-packages.tar.gz - 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. +3. xemacs-mule-sumo.tar.gz -> xemacs-mule-packages.tar.gz - Therefore, we can determine @math{L} just by looking at where we would -insert @math{R(1)} into the list, and if we know @math{F} and are moving -forward over extents, we can easily determine when we've hit @math{L} by -comparing the extent we're at to @math{R(1)}. +4. Symlinks to the files mentioned in #2 and #3 get created in the SAME +directory as xemacs-21.2.20-*.tar.gz. -@example -Theorem 2: @math{F(e-prev) e< [1, R(0)] e<= F}. -@end example +5. MOST IMPORTANTLY, a new file xemacs-21.2.20.tar.gz gets created, +which is the combination of the 5 files xemacs-21.2.20-core.tar.gz, +xemacs-21.2.20-elc.tar.gz, xemacs-21.2.20-info.tar.gz, +xemacs-packages.tar.gz, and xemacs-mule-packages.tar.gz. - This is the analog of Theorem 1, and applies because the e-order -sorts by increasing ending index. - Therefore, @math{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 @math{O(log N)}, -since we are using gap arrays to manage extents. +The directory structure of the new combined file xemacs-21.2.20.tar.gz +would look like this: - Define a @dfn{stack of extents} (or @dfn{SOE}) as the set of extents -(ordered in display order and e-order, just like for normal extent -lists) that overlap an index @math{I}. +xemacs-21.2.20/ +xemacs-packages/ +xemacs-mule-packages/ -Now: -Let @math{I} be an index, let @math{S} be the stack of extents on -@math{I} and let @math{F} be the first extent in @math{S}. +I am sorry to shout, but the current situation is just completely +insane. -Theorem 3: The first extent in @math{S} is the first extent that overlaps -any range @math{[I, J]}. +ben -Proof: Any extent that overlaps @math{[I, J]} but does not include -@math{I} must have a start index @math{> I}, and thus be greater than -any extent in @math{S}. -Therefore, finding the first extent that overlaps a range @math{R} is -the same as finding the first extent that overlaps @math{R(0)}. -Theorem 4: Let @math{I2} be an index such that @math{I2 > I}, and let -@math{F2} be the first extent that overlaps @math{I2}. Then, either -@math{F2} is in @math{S} or @math{F2} is greater than any extent in -@math{S}. -Proof: If @math{F2} does not include @math{I} then its start index is -greater than @math{I} and thus it is greater than any extent in -@math{S}, including @math{F}. Otherwise, @math{F2} includes @math{I} -and thus is in @math{S}, and thus @math{F2 >= F}. -@node Extent Fragments -@section Extent Fragments -@cindex extent fragments -@cindex fragments, extent - Imagine that the buffer is divided up into contiguous, non-overlapping -@dfn{runs} of text such that no extent starts or ends within a run -(extents that abut the run don't count). +From: + Ben Wing <ben@@666.com> + 10/16/1999 3:12 AM - 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 @dfn{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. + Subject: + Re: VOTE: Absolutely necessary changes to file naming in releases + To: + SL Baur <steve@@xemacs.org>, + XEmacs Reviews <xemacs-review@@xemacs.org>, + "Michael Sperber [Mr. Preprocessor]" <sperber@@informatik.uni-tuebingen.de> - 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. -@node Faces, Glyphs, Extents, Top -@chapter Faces -@cindex faces -Not yet documented. -@node Glyphs, Specifiers, Faces, Top -@chapter Glyphs -@cindex glyphs +Something went wrong with my mail program while I was responding, so +Michael's response is not quoted here. -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. +Let me rephrase my proposal, stressing the important points in order of +importance: -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. +1. MOST IMPORTANT: There MUST be a SINGLE tar file containing the complete +XEmacs sources, packages, etc. The name of this tar file must have a +format like this: -@c #### find a place for this discussion -@c The decision to make image specifiers a separate type is debatable. -@c In fact, the design decision to create a separate image specifier -@c type, rather than make glyphs themselves be specifiers, is -@c debatable---the other properties of glyphs are rarely used and could -@c conceivably have been incorporated into the glyph's instantiator. -@c The rarely used glyph types (buffer, pointer, icon) could also have -@c been incorporated into the instantiator. +xemacs-21.2.10.tar.gz -Glyphs are lazily instantiated by calling one of the glyph -functions. This usually occurs within redisplay when -@code{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 @code{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. +The directory layout of the packages within it is not important as long as +it works: The user who downloads the tar file MUST be able to apply the +'configure; make; make install' paradigm at the top-level directory and +have it work properly. -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. +2. All the pieces of XEmacs must be in the @strong{same} subdirectory on the FTP +site. -Any action on a glyph first consults the cache before actually -instantiating a widget. +3. The names need to be obvious and standard. Naming the core files +"xemacs-21.2.20.tar.gz" is non-standard because those are only the core +files. The standard followed by everybody in the world is that a name like +this refers to the entire product, with all ancillary files. Also, "sumo", +although a nice in-joke, is extremely confusing and needs to go. -@section Glyph Instantiation -@cindex glyph instantiation -@cindex instantiation, glyph +Referring to Michael's point about the layout I proposed, I also think that +the package system needs to be modified to accept a layout produced by the +"obvious" way of obtaining and untarring the parts, which leaves you with a +directory consisting of -Glyph instantiation is a hairy topic and requires some explanation. The -guts of glyph instantiation is contained within -@code{image_instantiate}. A glyph contains an image which is a -specifier. When a glyph function - for instance @code{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: +xemacs-21.2.19/ +xemacs-packages/ +mule-packages/ -@itemize @bullet -@item -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 @code{image_validate} and at a simple level validates -keyword value pairs. -@item -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 - -@code{image_copy_instantiator} - which will selectively copy values. -This is controlled by the way that a keyword is defined either using -@code{IIFORMAT_VALID_KEYWORD} or -@code{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. -@item -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 -@code{image_going_to_add} and @code{normalize_image_instantiator}. -@item -Instantiation. When an image instance is actually required for display -it is instantiated using @code{image_instantiate}. This involves calling -instantiate methods that are specific to the type of image being -instantiated. -@end itemize +All at the same level. However, this is an independent issue from the vote +at hand. -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 @dfn{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. +Consider the current insanity. The new XEmacs user or beta tester goes to +the FTP site, looks around, finds the file xemacs-21.2.19.tar.gz, and +downloads it, because it looks like the obvious one to get. But it doesn't +work. Oops ... He looks some more and finds the other two -elc and -info +parts, grabs them, and then tries again. But it still doesn't work. He +manages to overhear something about packages, so he looks for them, but +doesn't find them immediately (they're not even in the beta tree, though +they obviously contain beta-level code, especially in xemacs-base and +mule-base). Eventually he discovers the package/ subdirectory, but what +the hell does he do there? There's no README at all there giving any +clues, so he downloads everything. Along with this, he gets some files +called "sumo", which he doesn't understand, but he notices that some of +them are extremely large. "sumo" ... "large" ... hehe, I get it. Some +silly developer's joke. But then he tries again to compile things, and +just can't figure things out. He still doesn't know: -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 -@dfn{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. +-- "sumo" is not just some large file, but is a tar file of all the +packages. +-- The packages can't be placed is any subdirectory in any obvious relation +to the XEmacs directory ("straight out of the box" if you manage to grok +the significance of the sumo files, you get a layout like -@section Widget-Glyphs -@cindex widget-glyphs +xemacs-21.2.19/ +xemacs-packages/ +mule-packages/ -@section Widget-Glyphs in the MS-Windows Environment -@cindex widget-glyphs in the MS-Windows environment -@cindex MS-Windows environment, widget-glyphs in the +which naturally doesn't work! He needs to put them underneath +xemacs-21.2.19/lib/xemacs/ or something.) -To Do +At this point, he gives up, and (if he was a user of a pre-packagized +XEmacs) wonders in despair how things got so messed up, when all older +XEmacs releases, including all the betas, followed the standard "configure; +make; make install" paradigm). -@section Widget-Glyphs in the X Environment -@cindex widget-glyphs in the X environment -@cindex X environment, widget-glyphs in the -Widget-glyphs under X make heavy use of lwlib (@pxref{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. +Soooooo ......... PLEASE vote on issues #1-3 above, and add any comments +you feel like adding. -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. +ben -This has desirable properties such as lw_modify_all_widgets which is -called from @file{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. +Ben Wing wrote: -@node Specifiers, Menus, Glyphs, Top -@chapter Specifiers -@cindex specifiers +> Everybody except Steve seems to agree that we need to provide a single +> tar file containing the entire XEmacs tree whenever we release a new +> version of XEmacs (beta or not). Therefore I propose the following +> simple changes, and ask for a vote. If it is the general will of the +> developers, then Steve @strong{WILL} make these changes. This is the +> definition of cooperative development -- no one, not even the +> maintainer, can assert absolute power over anything. +> +> I propose (assuming, for example, release 21.2.20): +> +> 1. xemacs-21.2.20.tar.gz -> xemacs-21.2.20-core.tar.gz +> +> 2. xemacs-sumo.tar.gz -> xemacs-packages.tar.gz +> +> 3. xemacs-mule-sumo.tar.gz -> xemacs-mule-packages.tar.gz +> +> 4. Symlinks to the files mentioned in #2 and #3 get created in the SAME +> directory as xemacs-21.2.20-*.tar.gz. +> +> 5. MOST IMPORTANTLY, a new file xemacs-21.2.20.tar.gz gets created, +> which is the combination of the 5 files xemacs-21.2.20-core.tar.gz, +> xemacs-21.2.20-elc.tar.gz, xemacs-21.2.20-info.tar.gz, +> xemacs-packages.tar.gz, and xemacs-mule-packages.tar.gz. +> +> The directory structure of the new combined file xemacs-21.2.20.tar.gz +> would look like this: +> +> xemacs-21.2.20/ +> xemacs-packages/ +> xemacs-mule-packages/ +> +> I am sorry to shout, but the current situation is just completely +> insane. +> +> ben + + + +From: + Ben Wing <ben@@666.com> + 12/6/1999 4:19 AM + + Subject: + Re: Please Vote on Proposals + To: + Kyle Jones <kyle_jones@@wonderworks.com> + CC: + XEmacs Review <xemacs-review@@xemacs.org> + + + + +OK Kyle, how about a different proposal: + +1. The distribution consists of the following three parts (let's assume +v21.2.25): + +-- xemacs-21.2.25-core.tar.gz + The same as would currently in xemacs-21.2.25.tar.gz. You can + run this editor and edit in fundamental mode, but not do anything +else. + +-- xemacs-21.2.25-core-packages.tar.gz + A useful and complete subset of all the possible packages. Selection +of + what goes in and what goes out is based partially on consensus, +partially + on vote, and partially on these criteria: + + -- commonly-used packages go in. + -- unmaintained or out-of-date packages go out. + -- buggy, poorly-written packages go out. + -- really obscure packages that hardly anybody could possibly care + about go out. + -- when there are two or three packages implementing basically the + same functionality, pick only one to go in unless there are two +that + both are really commonly-used. + -- if a package can be loaded implicitly as a result of something in +the + core, it needs to go in, regardless of whether it's been +maintained. + This applies, for example, to the mode files -- @strong{all} mode +packages must + go in (or more properly, every mode must have a corresponding +package + that's in, although if there are two or more packages implementing +a + particular mode, e.g. html, we are free to choose just one). + +-- xemacs-21.2.25-aux-packages.tar.gz + All of the packages not in the previous file. Generally +crappy-quality, + poorly-maintained code. + +Note, we do not make distinctions between Mule and non-Mule in our +packaging scheme -- this is a bug and XEmacs and/or the packages should +be fixed up so that this goes away. + +2. The distribution also contains two combination files: + +-- xemacs-21.2.25.tar.gz + This is the "default" file that a naive user ought to retrieve, and + he'll get a running XEmacs, just like he wants, and comfortable, too, + because all of the common packages are there. This file is a +combination + of xemacs-21.2.25-core.tar.gz and xemacs-21.2.25-core-packages.tar.gz. + +-- xemacs-21.2.25-everything.tar.gz + This file contains absolutely everything, like it advertises -- + including the aux packages and all of their associated crappy-quality, + + unmaintained code. This file is a combination of +xemacs-21.2.25-core.tar.gz, + xemacs-21.2.25-core-packages.tar.gz, and +xemacs-21.2.25-aux-packages.tar.gz. + + +I like this proposal better than the previous one I advocated, because it +follows your good suggestion of separating the wheat from the chaff in +the packages, so to speak. People will grab xemacs-21.2.25.tar.gz by +default, just like they should, +and they'll get something they're quite happy with, and we're happy +because we can exercise quality control over the packages and exclude the +crappy ones most likely to cause grief later on. -Not yet documented. -@node Menus, Subprocesses, Specifiers, Top -@chapter Menus -@cindex menus +What say y'all? + +ben - A menu is set by setting the value of the variable -@code{current-menubar} (which may be buffer-local) and then calling -@code{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 -@code{current-menubar} is described in @file{menubar.c}. - Internally the data in current-menubar is parsed into a tree of -@code{widget_value's} (defined in @file{lwlib.h}); this is accomplished -by the recursive function @code{menu_item_descriptor_to_widget_value()}, -called by @code{compute_menubar_data()}. Such a tree is deallocated -using @code{free_widget_value()}. - @code{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 +Kyle Jones wrote: + +> Ben Wing writes: +> > Disagree. Please let's follow everyone else's convention, and not +> > introduce yet another randomness. +> +> It is not randomness! I think this is a semantic issue and an +> important one. The issue is: What do we consider part of XEmacs +> and what is considered external to XEmacs. If you put all the +> packages in xemacs.tar.gz, then users can reasonably and wrongly +> assume that all this random Lisp code is maintained by us. We +> are trying to stay away from that model because in the past it has +> left us with piles and piles of orphaned code. Even if every one +> of us were paid to maintain XEmacs, it is just not practical for +> us to continue to maintain all that code, let alone any new code. +> So I think the naming distinction Jan is making is worth doing. +> +> Also, I don't consider the current situation broken, except +> perhaps the sumo tarball being out of date. I never, ever, +> though it was a great idea to ship all the stuff that XEacs +> shipped in the old days. Because this pile of code was always +> around in the distribution, an enormous web of undocumented +> dependencies was constructed. Eventually, you HAD to install +> everything because if you left something out or removed something +> you never knew when XEmacs would throw an error. Thus the Cult +> of the Cargo was born. +> +> One of the best things that came out of the package system was +> the month or two we spent running XEmacs without all the assorted +> Lisp installed. Dependencies were removed or documented, some +> stuff got retired, and for the first time we actually had a full +> accounting of what we were shipping. I currently run XEmacs with +> 7 packages and I don't miss the other stuff. +> +> Having come this far, I do not think we should go back to +> advocating that everyone just install everything and not +> think about they are doing. Besides saving space and startup +> time, another reason to not install everything is that you +> won't bloat your XEmacs process nearly as much if you go +> exploring in the Custom menus, because there won't be as much +> Lisp loaded as Custom sets up its groups and whatnot. + +-- +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. +@end example + +@node Old Future Work, Index, Future Work Discussion, Top +@chapter Old Future Work +@cindex old future work +@cindex future work, old + +This chapter includes proposals for future work that were later +implemented. These proposals are included because they may describe to +some extent the actual workings of the implemented code, and because +they may discuss relevant design issues, alternative implementations, or +work still to be done. + +@menu +* Old Future Work -- A Portable Unexec Replacement:: +* Old Future Work -- Indirect Buffers:: +* Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X:: +* Old Future Work -- RTF Clipboard Support:: +* Old Future Work -- xemacs.org Mailing Address Changes:: +* Old Future Work -- Lisp callbacks from critical areas of the C code:: +@end menu + +@node Old Future Work -- A Portable Unexec Replacement, Old Future Work -- Indirect Buffers, Old Future Work, Old Future Work +@section Old Future Work -- A Portable Unexec Replacement +@cindex old future work, a portable unexec replacement +@cindex a portable unexec replacement, old future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +@strong{Abstract:} Currently, during the build stage of XEmacs, a bare +version of the program (called @dfn{temacs}) is run, which loads up a +bunch of Lisp data and then writes out a modified executable file. This +process is very tricky to implement and highly system-dependent. It can +be replaced by a simple, mostly portable, and easy to implement scheme +where the Lisp data is written out to a separate data file. + +The scheme makes only three assumptions about the memory layout of a +running XEmacs process, which, as far as I know, are met by all current +implementations of XEmacs (and they're also requirements of the existing +unexec scheme): @enumerate @item -@code{set-menubar-dirty-flag} was called since the last redisplay. (This -function sets the C variable menubar_has_changed.) + +The initialized data segments of the various XEmacs modules are all laid +out contiguously in memory and are separated from the initialized data +segments of libraries that are linked with XEmacs; likewise for +uninitialized data segments. @item -The buffer displayed in the screen has changed. + +The beginning and end of the XEmacs portion of the combined initialized +data segment can be programmatically determined; likewise for the +uninitialized data segment. @item -The screen has no menubar currently displayed. + +The XEmacs portion of the initialized and uninitialized data segments +are always loaded at the same place in memory. + @end enumerate - @code{set_screen_menubar()} is called for each such screen. This -function calls @code{compute_menubar_data()} to create the tree of -widget_value's, then calls @code{lw_create_widget()}, -@code{lw_modify_all_widgets()}, and/or @code{lw_destroy_all_widgets()} -to create the X-Toolkit widget associated with the menu. +Assumption number three means that this scheme is non-relocatable, which +is a disadvantage as compared to other, relocatable schemes that have +been proposed. However, the advantage of this scheme over them is that +it is much easier to implement and requires minimal changes to the +XEmacs code base. - @code{update_psheets()}, the other external entry point, actually -changes the menus being displayed. It uses the widgets fixed by -@code{update_screen_menubars()} and calls various X functions to ensure -that the menus are displayed properly. +First, let's go over the theory behind the dumping mechanism. The +principles that we would like to follow are: - The menubar widget is set up so that @code{pre_activate_callback()} is -called when the menu is first selected (i.e. mouse button goes down), -and @code{menubar_selection_callback()} is called when an item is -selected. @code{pre_activate_callback()} calls the function in -activate-menubar-hook, which can change the menubar (this is described -in @file{menubar.c}). If the menubar is changed, -@code{set_screen_menubars()} is called. -@code{menubar_selection_callback()} enqueues a menu event, putting in it -a function to call (either @code{eval} or @code{call-interactively}) and -its argument, which is the callback function or form given in the menu's -description. +@enumerate +@item -@node Subprocesses, Interface to the X Window System, Menus, Top -@chapter Subprocesses -@cindex subprocesses +We write out to disk all of the data structures and all of their +sub-structures that we have created ourselves, except for data that is +expected to change from invocation to invocation (in particular, data +that is extracted from the external environment at run time). +@item - The fields of a process are: +We don't write out to disk any data structures created or initialized by +system libraries, by the kernel or by any other code that we didn't +create ourselves, because we can't count on that code working in the way +that we want it to. +@item -@table @code -@item name -A string, the name of the process. +At the beginning of the next invocation of our program, we read in all +those data structures that we have written out to disk, and then +continue as if we had just created and initialized all of that data +ourselves. +@item -@item command -A list containing the command arguments that were used to start this -process. +We make sure that our own data structures don't have any pointers to +system data, or if they do, that we note all of these pointers so that +we can re-create the system data and set up pointers to the data again +in the next invocation. +@item -@item filter -A function used to accept output from the process instead of a buffer, -or @code{nil}. +During the next invocation of our program, we re-create all of our own +data structures that are derived from the external environment. -@item sentinel -A function called whenever the process receives a signal, or @code{nil}. +@end enumerate -@item buffer -The associated buffer of the process. +XEmacs, of course, is already set up to adhere to most of these +principles. -@item pid -An integer, the Unix process @sc{id}. +In fact, the current dumping process that we are replacing does a few of +these principles slightly differently and adds a few extra of its own: -@item childp -A flag, non-@code{nil} if this is really a child process. -It is @code{nil} for a network connection. +@enumerate +@item -@item 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. +All data structures of all sorts, including system data, are written +out. This is the cause of no end of problems, and it is avoidable, +because we can ensure that our own data and the system data are +physically separated in memory. +@item + +Our own data structures that we derive from the external environment are +in fact written out and read in, but then are simply overwritten during +the next invocation with new data. Before dumping, we make sure to free +any such data structure that would cause memory leaks. +@item + +XEmacs carefully arranges things so that all static variables in the +initialized data are never written to after the dumping stage has +completed. This allows for an additional optimization in which we can +make static initialized data segments in pre-dumped invocations of +XEmacs be read-only and shared among all XEmacs processes on a single +machine. -@item kill_without_query -If this is non-@code{nil}, killing XEmacs while this process is still -running does not ask for confirmation about killing the process. +@end enumerate -@item raw_status_low -@itemx raw_status_high -These two fields record 16 bits each of the process status returned by -the @code{wait} system call. +The difficult part in this process is figuring out where our data +structures lie in memory so that we can correctly write them out and +read them back in. The trick that we use to make this problem solvable +is to ensure that the heap that is used for all dynamically allocated +data structures that are created during the dumping process is located +inside the memory of a large, statically declared array. This ensures +that all of our own data structures are contained (at least at the time +that we dump out our data) inside the static initialized and +uninitialized data segments, which are physically separated in memory +from any data treated by system libraries and whose starting and ending +points are known and unchanging (we know that all of these things are +true because we require them to be so, as preconditions of being able to +make use of this method of dumping). + +In order to implement this method of heap allocation, we change the +memory allocation function that we use for our own data. (It's +extremely important that this function not be used to allocate system +data. This means that we must not redefine the @code{malloc} function +using the linker, but instead we need to achieve this using the C +preprocessor, or by simply using a different name, such as +@code{xmalloc}. It's also very important that we use the correct +@code{free} function when freeing dynamically-allocated data, depending +on whether this data was allocated by us or by the + +@node Old Future Work -- Indirect Buffers, Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X, Old Future Work -- A Portable Unexec Replacement, Old Future Work +@section Old Future Work -- Indirect Buffers +@cindex old future work, indirect buffers +@cindex indirect buffers, old future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +An indirect buffer is a buffer that shares its text with some other +buffer, but has its own version of all of the buffer properties, +including markers, extents, buffer local variables, etc. Indirect +buffers are not currently implemented in XEmacs, but they are in GNU +Emacs, and some people have asked for this feature. I consider this +feature somewhat extent-related because much of the work required to +implement this feature involves tracking extents properly. + +In a world with indirect buffers, some buffers are direct, and some +buffers are indirect. This only matters when there is more than one +buffer sharing the same text. In such a case, one of the buffers can be +considered the canonical buffer for the text in question. This buffer +is a direct buffer, and all buffers sharing the text are indirect +buffers. These two kinds of buffers are created differently. One of +them is created simply using the @code{make_buffer()} function (or +perhaps the @code{Fget_buffer_create()} function), and the other kind is +created using the @code{make_indirect_buffer()} function, which takes +another buffer as an argument which specifies the text of the indirect +buffer being created. Every indirect buffer keeps track of the direct +buffer that is its parent, and every direct buffer keeps a list of all +of its indirect buffer children. This list is modified as buffers are +created and deleted. Because buffers are permanent objects, there is no +special garbage collection-related trickery involved in these parent and +children pointers. There should never be an indirect buffer whose +parent is also an indirect buffer. If the user attempts to set up such +a situation using @code{make_indirect_buffer()}, either an error should +be signaled or the parent of the indirect buffer should automatically +become the direct buffer that actually is responsible for the text. +Deleting a direct buffer should perhaps cause all of the indirect buffer +children to be deleted automatically. There should be Lisp functions +for determining whether a buffer is direct or indirect, and other +functions for retrieving the parents, or the children of the buffer, +depending on which is appropriate. (The scheme being described here is +similar to symbolic links. Another possible scheme would be analogous +to hard links, and would make no distinction between direct and indirect +buffers. In that case, the text of the buffer logically exists as an +object separate from the buffer itself and only goes away when the last +buffer pointing to this text is deleted.) + +Other than keeping track of parent and child pointer, the only remaining +thing required to implement indirect buffers is to ensure that changes +to the text of the buffer trigger the same sorts of effect in all the +buffers that share that text. Luckily there are only three functions in +XEmacs that actually make changes to the text of the buffer, and they +are all located in the file @code{insdel.c}. + +These three functions are called @code{buffer_insert_string_1()}, +@code{buffer_delete_range()}, and @code{buffer_replace_char()}. All of +the subfunctions called by these functions are also in @code{insdel.c}. + +The first thing that each of these three functions needs to do is check +to see if its buffer argument is an indirect buffer, and if so, convert +it to the indirect buffer's parent. Once that is done, the functions +need to be modified so that all of the things they do, other than +actually changing the buffers text, such as calling +before-change-functions and after-change-functions, and updating extents +and markers, need to be done over all of the buffers that are indirect +children of the buffers being modified; as well as, of course, for the +buffer itself. Each step in the process needs to be iterated for all of +the buffers in question before proceeding to the next step. For +example, in @code{buffer_insert_string_1()}, +@code{prepare_to_modify_buffer()} needs to be called in turn, for all of +the buffers sharing the text being modified. Then the text itself is +modified, then @code{insert_invalidate_line_number_cache()} is called +for all of the buffers, then @code{record_insert()} is called for all of +the buffers, etc. Essentially, the operation is being done on all of +the buffers in parallel, rather than each buffer being processed in +series. This is necessary because many of the steps can quit or call +Lisp code and each step depends on the previous step, and some steps are +done only once, rather than on each buffer. I imagine it would be +significantly easier to implement this, if a macro were created for +iterating over a buffer, and then all of the indirect children of that +buffer. -@item status -The process status, as @code{process-status} should return it. +@node Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X, Old Future Work -- RTF Clipboard Support, Old Future Work -- Indirect Buffers, Old Future Work +@section Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X +@cindex old future work, improvements in support for non-ascii (european) keysyms under x +@cindex improvements in support for non-ascii (european) keysyms under x, old future work -@item tick -@itemx 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. +Author: @uref{mailto:martin@@xemacs.org,Martin Buchholz} -@item pty_flag -Non-@code{nil} if communication with the subprocess uses a @sc{pty}; -@code{nil} if it uses a pipe. +If a user has a keyboard with known standard non-ASCII character +equivalents, typically for European users, then Emacs' default +binding should be self-insert-command, with the obvious character +inserted. For example, if a user has a keyboard with -@item infd -The file descriptor for input from the process. +xmodmap -e "keycode 54 = scaron" -@item outfd -The file descriptor for output to the process. +then pressing that key on the keyboard will insert the (Latin-2) +character corresponding to "scaron" into the buffer. -@item 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 -@code{-1}.) +Note: Emacs 20.6 does NOTHING when pressing such a key (not even an +error), i.e. even (read-event) ignores this key, which means it can't +even be bound to anything by a user trying to customize it. -@item tty_name -The name of the terminal that the subprocess is using, -or @code{nil} if it is using pipes. -@end table +This is implemented by maintaining a table of translations between all +the known X keysym names and the corresponding (charset, octet) pairs. -@node Interface to the X Window System, Index, Subprocesses, Top -@chapter Interface to the X Window System -@cindex X Window System, interface to the +@quotation + For every key on the keyboard that has a known character correspondence, + we define the ascii-character property of the keysym, and make the + default binding for the key be self-insert-command. + + The following magic is basically intimate knowledge of X11/keysymdef.h. + The keysym mappings defined by X11 are based on the iso8859 standards, + except for Cyrillic and Greek. + + In a non-Mule world, a user can still have a multi-lingual editor, by doing + (set-face-font "...-iso8859-2" (current-buffer)) + for all their Latin-2 buffers, etc. +@end quotation -Mostly undocumented. +@node Old Future Work -- RTF Clipboard Support, Old Future Work -- xemacs.org Mailing Address Changes, Old Future Work -- Improvements in support for non-ASCII (European) keysyms under X, Old Future Work +@section Old Future Work -- RTF Clipboard Support +@cindex old future work, RTF clipboard support +@cindex RTF clipboard support, old future work -@menu -* Lucid Widget Library:: An interface to various widget sets. -@end menu +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} -@node Lucid Widget Library -@section Lucid Widget Library -@cindex Lucid Widget Library -@cindex widget library, Lucid -@cindex library, Lucid Widget +in fact, i merged the windows stuff with the already-existing generic code. -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. +what i'd like to see is something like this: -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). +@enumerate +@item +The current function -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. +@example +(defun own-selection (data &optional type append) +@end example -@menu -* Generic Widget Interface:: The lwlib generic widget interface. -* Scrollbars:: -* Menubars:: -* Checkboxes and Radio Buttons:: -* Progress Bars:: -* Tab Controls:: -@end menu +should become -@node Generic Widget Interface -@subsection Generic Widget Interface -@cindex widget interface, generic +@example +(defun own-selection (data &optional type how-to-add data-type) +@end example -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. +where data-type is the mswindows format, and how-to-add is -For each toolkit widget, lwlib maintains a tree of @code{widget_values} -which mirror the hierarchical state of Xt widgets (including Motif, -Athena, 3D Athena, and Falk's widget sets). Each @code{widget_value} -has @code{contents} member, which points to the head of a linked list of -its children. The linked list of siblings is chained through the -@code{next} member of @code{widget_value}. +@example +'replace-all or nil -- remove data for all formats +'replace-existing -- remove data for DATA-TYPE, but leave other formats alone +'append or t -- append data to existing data in DATA-TYPE, and leave other +formats alone +@end example + +@item +the function @example - +-----------+ - | composite | - +-----------+ - | - | contents - V - +-------+ next +-------+ next +-------+ - | child |----->| child |----->| child | - +-------+ +-------+ +-------+ - | - | contents - V - +-------------+ next +-------------+ - | grand child |----->| grand child | - +-------------+ +-------------+ +(get-selection &optional TYPE DATA-TYPE) +@end example -The @code{widget_value} hierarchy of a composite widget with two simple -children and one composite child. +already has a data-type so you don't need to change it. + +@item +the existing function + +@example +(selection-exists-p &optional SELECTION DEVICE) @end example -The @code{widget_instance} structure maintains the inverse view of the -tree. As for the @code{widget_value}, siblings are chained through the -@code{next} member. However, rather than naming children, the -@code{widget_instance} tree links to parents. +should become @example - +-----------+ - | composite | - +-----------+ - A - | parent - | - +-------+ next +-------+ next +-------+ - | child |----->| child |----->| child | - +-------+ +-------+ +-------+ - A - | parent - | - +-------------+ next +-------------+ - | grand child |----->| grand child | - +-------------+ +-------------+ +(selection-exists-p &optional SELECTION DEVICE DATA-TYPE) +@end example -The @code{widget_value} hierarchy of a composite widget with two simple -children and one composite child. +@item +a new function + +@example +(register-selection-data-type DATA-TYPE) @end example -This permits widgets derived from different toolkits to be updated and -manipulated generically by the lwlib library. For instance -@code{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 @code{widget_value} by walking the -@code{widget_value} tree. This has desirable properties. For example, -@code{lw_modify_all_widgets} is called from @file{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. +like your mswindows-register-clipboard-format. -The @code{widget_instance} structure also contains a pointer to the root -of its tree. Widget instances are further confi +@item +there's already a selection-converter-alist, but that's only for data out. +you should alias it to selection-conversion-out-alist, and create +selection-conversion-in-alist. these alists contain entries for CF_TEXT, which +handles CR/LF conversion, and rtf, which does rtf in/out conversion -- no need +for separate functions to do this. +this may seem daunting, but it's much less hard to add stuff like this than it +seems, and i and others will certainly give you lots of support if you run into +problems. it would be way cool to have a more powerful clipboard mechanism in +XEmacs. +@end enumerate -@node Scrollbars -@subsection Scrollbars -@cindex scrollbars +@node Old Future Work -- xemacs.org Mailing Address Changes, Old Future Work -- Lisp callbacks from critical areas of the C code, Old Future Work -- RTF Clipboard Support, Old Future Work +@section Old Future Work -- xemacs.org Mailing Address Changes +@cindex old future work, xemacs.org mailing address changes +@cindex xemacs.org mailing address changes, old future work -@node Menubars -@subsection Menubars -@cindex menubars +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} -@node Checkboxes and Radio Buttons -@subsection Checkboxes and Radio Buttons -@cindex checkboxes and radio buttons -@cindex radio buttons, checkboxes and -@cindex buttons, checkboxes and radio +@subheading Personal addresses -@node Progress Bars -@subsection Progress Bars -@cindex progress bars -@cindex bars, progress +@enumerate +@item -@node Tab Controls -@subsection Tab Controls -@cindex tab controls +Everyone who is contributing or has ever contributed code to the XEmacs +core, or to any of the packages archived at xemacs.org, even if they +don't actually have an account on any machine at xemacs.org. In fact, +all of these people should have two mailing addresses at xemacs.org, one +of which is their actual login name (or potential login name if they +were ever to have an account), and the other one is in the form of first +name/last name, similar to the way things are done at Sun. For example, +Martin would have two addresses at xemacs.org, @code{martin@@xemacs.org}, +and @code{martin.buchholz@@xemacs.org}, with the latter one simply being +an alias for the former. The idea is that in all cases, if you simply +know the name of any past or present contributor to XEmacs, and you want +to mail them, you will know immediately how to do this without having to +do any complicated searching on the Web or in XEmacs documentation. +@item + +Furthermore, I think that all of the email addresses mentioned anywhere +in the XEmacs source code or documentation should be changed to be the +corresponding ones at xemacs.org, instead of any other email addresses +that any contributors might have. +@item + +All the places in the source code where a contributor's name is +mentioned, but no email addressed is attached, should be found, and the +correct xemacs.org address should be attached. +@item + +The alias file mapping people's addresses at xemacs.org to their actual +addresses elsewhere (in the case, as will be true for the majority of +addresses, where the contributor does not actually have an account at +xemacs.org, but simply a forwarding pointer), should be viewable on the +xemacs.org web site through a CGI script that reads the alias file and +turns it into an HTML table. + +@end enumerate + +@subheading Package addresses + +I also think that for every package archived at xemacs.org, there should +be three corresponding email addresses at xemacs.org. For example, +consider a package such as @code{lazy-shot}. The addresses associated +with this package would be: + +@table @code +@item lazy-shot@@xemacs.org +This is a discussion mailing list about the @code{lazy-shot} package, +and it should be controlled by Majordomo in the standard fashion. +@item lazy-shot-patches@@xemacs.org +This is where patches to the @code{lazy-shot} package are set. This +should go to various people who are interested in such patches. For +example, the maintainer of @code{lazy-shot}, perhaps the maintainer of +XEmacs itself, and probably to other people who have volunteered to do +code review for this package, or for a larger group of packages that +this package is in. Perhaps this list should also be maintained by +Majordomo. +@item lazy-shot-maintainer@@xemacs.org +This address is for mailing the maintainer directly. It is possible +that this will go to more than one person. This would particularly be +the case, for example, if the maintainer is dormant or does not appear +very responsive to patches. In this case, the address would also point +to someone like Steve, who is acting in the maintainer's stead, and who +will himself apply patches or make other changes to the package as +maintained in the CVS archive on xemacs.org. +@end table + +It may take a bit of work to track down the current addresses for the +various package maintainers, and may in general seem like a lot of work +to set up all of these mail addresses, but I think it's very important +to make it as easy as possible for random XEmacs users to be able to +submit patches and report bugs in an orderly fashion. The general idea +that I'm striving for is to create as much momentum as possible in the +XEmacs development community, and I think having the system of mail +addresses set up will make it much easier for this momentum to be built +up and to remain. + +@uref{../../www.666.com/ben/default.htm,Ben Wing} + +@node Old Future Work -- Lisp callbacks from critical areas of the C code, , Old Future Work -- xemacs.org Mailing Address Changes, Old Future Work +@section Old Future Work -- Lisp callbacks from critical areas of the C code +@cindex old future work, lisp callbacks from critical areas of the c code +@cindex lisp callbacks from critical areas of the c code, old future work + +Author: @uref{mailto:ben@@xemacs.org,Ben Wing} + +There are many places in the XEmacs C code where Lisp functions are +called, usually because the Lisp function is acting as a callback, +hook, process filter, or the like. The lisp code is often called in +places where some lisp operations are dangerous. Currently there are +a lot of ad-hoc schemes implemented to try to prevent these dangerous +operations from causing problems. I've added a lot of them myself, +for example, the @code{call*_trapping_errors()} functions. Other places, +such as the pre-gc- and post-gc-hooks, do their own ad hoc processing. +I'm proposing a scheme that would generalize all of this ad hoc code +and allow Lisp code to be called in all sorts of sensitive areas of +the C code, including even within redisplay. + +Basically, we define a set of operations that are disallowable because +they are dangerous. We essentially assign a bit flag to all of these +operations. Whenever any sensitive C code wants to call Lisp code, +instead of using the standard call* functions, it uses a new set of +functions, call*_critical, which takes an extra parameter, which is a +bit mask specifying the set of operations which are disallowed. The +basic operations of these functions is simply to set a global variable +corresponding to the bit mask (more specifically, the functions store +the previous value of this global variable in an unwind_protect, and +use bitwise-or to combine the previous value with the new bit mask +that was passed in). (Actually, we should first implement a slightly +lower level function which is called @code{enter_sensitive_code_section()}, +which simply sets up the global variable and the @code{unwind_protect()}, and +returns a @code{specbind()} value, but doesn't actually call any Lisp code. +There is a corresponding function @code{exit_sensitive_code_section()}, which +takes the specbind value as an argument, and unwinds the +unwind_protect. The call*_sensitive functions are trivially +implemented in terms of these lower level functions.) + +Corresponding to each of these entries is the C name of the bit flag. + +The sets of dangerous operations which can be prohibited are: + +@table @code +@item OPERATION_GC_PROHIBITED +garbage collection. When this flag is set, and the garbage +collection threshold is reached, garbage collection simply doesn't +happen. It will happen at the next opportunity that it is allowed. +Similarly, explicitly calling the Lisp function garbage-collect +simply does nothing. + +@item OPERATION_CATCH_ERRORS +signalling an error. When @code{enter_sensitive_code_section()} is +called, with the bit flag corresponding to this prohibited +operation. When this bit flag is passed to +@code{enter_sensitive_code_section()}, a catch is set up which catches all +errors, signals a warning with @code{warn_when_safe()}, and then simply +continues. This is exactly the same behavior you now get with the +@code{call_*_trapping_errors()} functions. (there should also be some way +of specifying a warning level and class here, similar to the +@code{call_*_trapping_errors()} functions. This is not completely +important, however, because a standard warning level and class +could simply be chosen.) + +@item OPERATION_NO_UNSAFE_OBJECT_DELETION +This flag prohibits deletion of any permanent object (i.e. any +object that does not automatically disappear when created, such as +buffers, frames, devices, windows, etc...) unless they were created +after this bit flag was set. This would be implemented using a +list which stores all of the permanent objects created after this +bit flag was set. This list is reset to its previous value when +the call to @code{exit_sensitive_code_section()} occurs. The motivation +here is to allow Lisp callbacks to create their own temporary +buffers or frames, and later delete them, but not allow any other +permanent objects to be deleted, because C code might be working +with them, and not expect them to change. + +@item OPERATION_NO_BUFFER_MODIFICATION +This flag disallows modifications to the text, extent or any other +properties of any buffers except those created after this flag was +set, just like in the previous entry. + +@item OPERATION_NO_REDISPLAY +This bit flag inhibits any redisplay-related operations from +happening, more specifically, any entry into the redisplay-related +code. This includes, for example, the Lisp functions sit-for, +force-redisplay, force-cursor-redisplay, window-end with certain +arguments to it, and various other functions. When this flag is +set, instead of entering the redisplay code, the calling function +should simply make sure not to enter the redisplay code, (for +example, in the case of window-end), or postpone the redisplay +until such a time when it's safe (for example, with sit-for and +force-redisplay). + +@item OPERATION_NO_REDISPLAY_SETTINGS_CHANGE +This flag prohibits any modifications to faces, glyphs, specifiers, +extents, or any other settings that will affect the way that any +window is displayed. +@end table + +The idea here is that it will finally be safe to call Lisp code from +nearly any part of the C code, simply by setting any combination of +restricted operation bit flags. This even includes from within +redisplay. (in such a case, all of the bit flags need to be set). The +reason that I thought of this is that some coding system translations +might cause Lisp code to be invoked and C code often invokes these +translations in sensitive places. + +@c Indexing guidelines + +@c I assume that all indexes will be combined. +@c Therefore, if a generated findex and permutations +@c cover the ways an index user would look up the entry, +@c then no cindex is added. +@c Concept index (cindex) entries will also be permuted. Therefore, they +@c have no commas and few irrelevant connectives in them. + +@c I tried to include words in a cindex that give the context of the entry, +@c particularly if there is more than one entry for the same concept. +@c For example, "nil in keymap" +@c Similarly for explicit findex and vindex entries, e.g. "print example". + +@c Error codes are given cindex entries, e.g. "end-of-file error". + +@c pindex is used for .el files and Unix programs + +@node Index, , Old Future Work, Top +@unnumbered Index + +@ignore +All variables, functions, keys, programs, files, and concepts are +in this one index. + +All names and concepts are permuted, so they appear several times, one +for each permutation of the parts of the name. For example, +@code{function-name} would appear as @b{function-name} and @b{name, +function-}. Key entries are not permuted, however. +@end ignore + +@c Print the indices -@include index.texi +@printindex fn @c Print the tables of contents @summarycontents diff --text -u 'xemacs-21.5.18/man/lispref/eval.texi' 'xemacs-21.5.19/man/lispref/eval.texi' Index: ./man/lispref/eval.texi --- ./man/lispref/eval.texi Fri Apr 13 03:22:13 2001 +++ ./man/lispref/eval.texi Fri Jan 21 18:43:11 2005 @@ -74,7 +74,7 @@ function @code{car}. Evaluation of a function call ultimately calls the function specified -in it. @xref{Functions}. The execution of the function may itself work +in it. @xref{Functions and Commands}. The execution of the function may itself work by evaluating the function definition; or the function may be a Lisp primitive implemented in C, or it may be a byte-compiled function (@pxref{Byte Compilation}). diff --text -u 'xemacs-21.5.18/man/lispref/functions.texi' 'xemacs-21.5.19/man/lispref/functions.texi' Index: ./man/lispref/functions.texi --- ./man/lispref/functions.texi Fri Apr 13 03:22:14 2001 +++ ./man/lispref/functions.texi Fri Jan 21 18:43:12 2005 @@ -3,8 +3,8 @@ @c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. @c See the file lispref.texi for copying conditions. @setfilename ../../info/functions.info -@node Functions, Macros, Variables, Top -@chapter Functions +@node Functions and Commands, Macros, Variables, Top +@chapter Functions and Commands A Lisp program is composed mainly of Lisp functions. This chapter explains what functions are, how they accept arguments, and how to @@ -45,6 +45,39 @@ specifically to mean a function written in Lisp. Special forms and macros are not functions. +@item command +@cindex command + +A @dfn{command} is a possible definition for a key sequence---we count +mouse events and menu accesses as key sequences for this purpose. More +formally, within XEmacs lisp, a command is something that +@code{command-execute} can invoke. + +Some functions are commands; a function written in Lisp is a command if +it contains an interactive declaration. A trivial interactive +declaration is a line @code{(interactive)} immediately after the +documentation string. For more complex examples, with prompting and +completion, see @xref{Defining Commands}. Such a function can be called +from Lisp expressions like other functions; in this case, the fact that +the function is a command makes no difference. + +Keyboard macros (strings and vectors) are commands also, even though +they are not functions. A symbol is a command if its function +definition is a command; such symbols can be invoked with @kbd{M-x}. +The symbol is a function as well if the definition is a function. + +In the case where you want to call a command in reaction to a +user-generated event, you'll need to bind it to that event. For how to +do this, see @xref{Key Binding Commands}. +@xref{Command Overview}. + +@item keystroke command +@cindex keystroke command +A @dfn{keystroke command} is a command that is bound to a key sequence +(typically one to three keystrokes). The distinction is made here +merely to avoid confusion with the meaning of ``command'' in non-Emacs +editors; for Lisp programs, the distinction is normally unimportant. + @item primitive @cindex primitive @cindex subr @@ -84,28 +117,6 @@ things that special forms can do. @xref{Macros}, for how to define and use macros. -@item command -@cindex command -A @dfn{command} is an object that @code{command-execute} can invoke; it -is a possible definition for a key sequence. Some functions are -commands; a function written in Lisp is a command if it contains an -interactive declaration (@pxref{Defining Commands}). Such a function -can be called from Lisp expressions like other functions; in this case, -the fact that the function is a command makes no difference. - -Keyboard macros (strings and vectors) are commands also, even though -they are not functions. A symbol is a command if its function -definition is a command; such symbols can be invoked with @kbd{M-x}. -The symbol is a function as well if the definition is a function. -@xref{Command Overview}. - -@item keystroke command -@cindex keystroke command -A @dfn{keystroke command} is a command that is bound to a key sequence -(typically one to three keystrokes). The distinction is made here -merely to avoid confusion with the meaning of ``command'' in non-Emacs -editors; for Lisp programs, the distinction is normally unimportant. - @item compiled function A @dfn{compiled function} is a function that has been compiled by the byte compiler. @xref{Compiled-Function Type}. diff --text -u 'xemacs-21.5.18/man/lispref/help.texi' 'xemacs-21.5.19/man/lispref/help.texi' Index: ./man/lispref/help.texi --- ./man/lispref/help.texi Fri Apr 13 03:22:14 2001 +++ ./man/lispref/help.texi Sat Dec 18 03:11:47 2004 @@ -676,7 +676,7 @@ XEmacs Lisp lets you mark a function or variable as @dfn{obsolete}, and indicate what should be used instead. -@deffn Command make-obsolete function new +@deffn Command make-obsolete function new &optional when This function indicates that @var{function} is an obsolete function, and the function @var{new} should be used instead. The byte compiler will issue a warning to this effect when it encounters a usage of the @@ -684,7 +684,9 @@ documentation. @var{new} can also be a string (if there is not a single function with the same functionality any more), and should be a descriptive statement, such as "use @var{foo} or @var{bar} instead" or "this function is -unnecessary". +unnecessary". If provided, @var{when} should be a string indicating when +the function was first made obsolete, for example a date or a release +number. @end deffn @deffn Command make-obsolete-variable variable new diff --text -u 'xemacs-21.5.18/man/lispref/lispref.texi' 'xemacs-21.5.19/man/lispref/lispref.texi' Index: ./man/lispref/lispref.texi --- ./man/lispref/lispref.texi Mon Jul 19 17:24:28 2004 +++ ./man/lispref/lispref.texi Fri Jan 21 18:43:12 2005 @@ -144,8 +144,10 @@ * Evaluation:: How Lisp expressions are evaluated. * Control Structures:: Conditionals, loops, nonlocal exits. * Variables:: Using symbols in programs to stand for values. -* Functions:: A function is a Lisp program - that can be invoked from other functions. + +* Functions and Commands:: A function is a Lisp program that can be + invoked from other functions. + * Macros:: Macros are a way to extend the Lisp language. * Customization:: Writing customization declarations. diff --text -u 'xemacs-21.5.18/man/lispref/macros.texi' 'xemacs-21.5.19/man/lispref/macros.texi' Index: ./man/lispref/macros.texi --- ./man/lispref/macros.texi Fri Apr 13 03:22:17 2001 +++ ./man/lispref/macros.texi Fri Jan 21 18:43:12 2005 @@ -3,7 +3,7 @@ @c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. @c See the file lispref.texi for copying conditions. @setfilename ../../info/macros.info -@node Macros, Loading, Functions, Top +@node Macros, Loading, Functions and Commands, Top @chapter Macros @cindex macros diff --text -u 'xemacs-21.5.18/man/lispref/mule.texi' 'xemacs-21.5.19/man/lispref/mule.texi' Index: ./man/lispref/mule.texi --- ./man/lispref/mule.texi Fri Oct 10 19:18:28 2003 +++ ./man/lispref/mule.texi Fri Nov 5 08:06:07 2004 @@ -1787,13 +1787,13 @@ CCL_BLOCK := STATEMENT | (STATEMENT [STATEMENT ...]) STATEMENT := - SET | IF | BRANCH | LOOP | REPEAT | BREAK | READ | WRITE - | CALL | END + SET | IF | BRANCH | LOOP | REPEAT | BREAK | READ | WRITE | CALL + | TRANSLATE | MAP | END SET := (REG = EXPRESSION) | (REG ASSIGNMENT_OPERATOR EXPRESSION) - | integer + | INT-OR-CHAR EXPRESSION := ARG | (EXPRESSION OPERATOR ARG) @@ -1803,28 +1803,30 @@ BREAK := (break) REPEAT := (repeat) - | (write-repeat [REG | integer | string]) - | (write-read-repeat REG [integer | ARRAY]) + | (write-repeat [REG | INT-OR-CHAR | string]) + | (write-read-repeat REG [INT-OR-CHAR | ARRAY]) READ := (read REG ...) - | (read-if (REG OPERATOR ARG) CCL_BLOCK CCL_BLOCK) + | (read-if (REG OPERATOR ARG) CCL_BLOCK [CCL_BLOCK]) | (read-branch REG CCL_BLOCK [CCL_BLOCK ...]) WRITE := (write REG ...) | (write EXPRESSION) - | (write integer) | (write string) | (write REG ARRAY) + | (write INT-OR-CHAR) | (write string) | (write REG ARRAY) | string CALL := (call ccl-program-name) END := (end) REG := r0 | r1 | r2 | r3 | r4 | r5 | r6 | r7 -ARG := REG | integer +ARG := REG | INT-OR-CHAR OPERATOR := + | - | * | / | % | & | '|' | ^ | << | >> | <8 | >8 | // | < | > | == | <= | >= | != | de-sjis | en-sjis ASSIGNMENT_OPERATOR := += | -= | *= | /= | %= | &= | '|=' | ^= | <<= | >>= -ARRAY := '[' integer ... ']' +ARRAY := '[' INT-OR-CHAR ... ']' +INT-OR-CHAR := integer | character + @end format @node CCL Statements, CCL Expressions, CCL Syntax, CCL @@ -1856,7 +1858,7 @@ The @dfn{write} takes several forms. In the form @samp{(write @var{reg} ...)} it takes one or more registers as arguments and writes each in turn to the output. The integer in a register (interpreted as an -Emchar) is encoded to multibyte form (ie, Bufbytes) and written to the +Ichar) is encoded to multibyte form (ie, Ibytes) and written to the current output buffer. If it is less than 256, it is written as is. The forms @samp{(write @var{expression})} and @samp{(write @var{integer})} are treated analogously. The form @samp{(write diff --text -u 'xemacs-21.5.18/man/lispref/range-tables.texi' 'xemacs-21.5.19/man/lispref/range-tables.texi' Index: ./man/lispref/range-tables.texi --- ./man/lispref/range-tables.texi Fri Apr 13 03:22:19 2001 +++ ./man/lispref/range-tables.texi Mon Dec 6 12:51:41 2004 @@ -13,11 +13,16 @@ Note that range tables have a read syntax, like this: @example -#s(range-table data ((-3 2) foo (5 20) bar)) +#s(range-table type start-closed-end-open data ((-3 2) foo (5 20) bar)) @end example -This maps integers in the range (-3, 2) to @code{foo} and integers -in the range (5, 20) to @code{bar}. +This maps integers in the range [-3, 2) to @code{foo} and integers +in the range [5, 20) to @code{bar}. + +By default, range tables have a @var{type} of +@code{start-closed-end-open}. (@strong{NOTE}: This is a change from +21.4 and earlier, where there was no @var{type} and range tables were always +closed on both ends.) This makes them work like text properties. @defun range-table-p object Return non-@code{nil} if @var{object} is a range table. @@ -32,8 +37,35 @@ @node Introduction to Range Tables @section Introduction to Range Tables -@defun make-range-table +@defun make-range-table &optional type Make a new, empty range table. + +@var{type} is a symbol indicating how ranges are assumed to function +at their ends. It can be one of + +@example +SYMBOL RANGE-START RANGE-END +------ ----------- --------- +`start-closed-end-open' (the default) closed open +`start-closed-end-closed' closed closed +`start-open-end-open' open open +`start-open-end-closed' open closed +@end example + +A @dfn{closed} endpoint of a range means that the number at that end +is included in the range. For an @dfn{open} endpoint, the number +would not be included. + +For example, a closed-open range from 5 to 20 would be indicated as +@samp{[5, 20)} where a bracket indicates a closed end and a +parenthesis an open end, and would mean `all the numbers between 5 and +20', including 5 but not 20. This seems a little strange at first but +is in fact extremely common in the outside world as well as in +computers and makes things work sensibly. For example, if I say +"there are seven days between today and next week today", I'm +including today but not next week today; if I included both, there +would be eight days. Similarly, there are 15 (= 20 - 5) elements in +the range @samp{[5, 20)}, but 16 in the range @samp{[5, 20]}. @end defun @defun copy-range-table range-table @@ -49,11 +81,20 @@ This function finds value for position @var{pos} in @var{range-table}. If there is no corresponding value, return @var{default} (defaults to @code{nil}). + +@strong{NOTE}: If you are working with ranges that are closed at the +start and open at the end (the default), and you put a value for a +range with @var{start} equal to @var{end}, @code{get-range-table} will +@strong{not} return that value! You would need to set @var{end} one +greater than @var{start}. @end defun @defun put-range-table start end value range-table This function sets the value for range (@var{start}, @var{end}) to be @var{value} in @var{range-table}. + +@strong{NOTE}: Unless you are working with ranges that are closed at +both ends, nothing will happen if @var{start} equals @var{end}. @end defun @defun remove-range-table start end range-table diff --text -u 'xemacs-21.5.18/man/lispref/symbols.texi' 'xemacs-21.5.19/man/lispref/symbols.texi' Index: ./man/lispref/symbols.texi --- ./man/lispref/symbols.texi Fri Apr 13 03:22:21 2001 +++ ./man/lispref/symbols.texi Fri Jan 21 18:43:12 2005 @@ -11,8 +11,8 @@ describes symbols, their components, their property lists, and how they are created and interned. Separate chapters describe the use of symbols as variables and as function names; see @ref{Variables}, and -@ref{Functions}. For the precise read syntax for symbols, see -@ref{Symbol Type}. +@ref{Functions and Commands}. For the precise read syntax for symbols, +see @ref{Symbol Type}. You can test whether an arbitrary Lisp object is a symbol with @code{symbolp}: @@ -154,7 +154,7 @@ cell, is derived from the idea that @code{defun} gives the symbol its definition as a function.) @code{defsubst}, @code{define-function} and @code{defalias} are other ways of defining a function. -@xref{Functions}. +@xref{Functions and Commands}. @code{defmacro} defines a symbol as a macro. It creates a macro object and stores it in the function cell of the symbol. Note that a diff --text -u 'xemacs-21.5.18/man/lispref/variables.texi' 'xemacs-21.5.19/man/lispref/variables.texi' Index: ./man/lispref/variables.texi --- ./man/lispref/variables.texi Wed Oct 2 18:30:52 2002 +++ ./man/lispref/variables.texi Fri Jan 21 18:43:12 2005 @@ -3,7 +3,7 @@ @c Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. @c See the file lispref.texi for copying conditions. @setfilename ../../info/variables.info -@node Variables, Functions, Control Structures, Top +@node Variables, Functions and Commands, Control Structures, Top @chapter Variables @cindex variable @@ -225,7 +225,7 @@ @itemize @bullet @item -Function calls (@pxref{Functions}). +Function calls (@pxref{Functions and Commands}). @item Macro calls (@pxref{Macros}). diff --text -u 'xemacs-21.5.18/man/lispref/windows.texi' 'xemacs-21.5.19/man/lispref/windows.texi' Index: ./man/lispref/windows.texi --- ./man/lispref/windows.texi Tue Sep 21 12:00:12 2004 +++ ./man/lispref/windows.texi Thu Oct 28 19:51:17 2004 @@ -48,7 +48,7 @@ In each frame, at any time, one and only one window is designated as @dfn{selected within the frame}. The frame's cursor appears in that -window. At ant time, one frame is the selected frame; and the window +window. At any time, one frame is the selected frame; and the window selected within that frame is @dfn{the selected window}. The selected window's buffer is usually the current buffer (except when @code{set-buffer} has been used). @xref{Current Buffer}. diff --text -u 'xemacs-21.5.18/man/xemacs-faq.texi' 'xemacs-21.5.19/man/xemacs-faq.texi' Index: ./man/xemacs-faq.texi --- ./man/xemacs-faq.texi Mon Jul 5 19:42:30 2004 +++ ./man/xemacs-faq.texi Fri Feb 4 11:51:21 2005 @@ -7,10 +7,10 @@ @finalout @titlepage @title XEmacs FAQ -@subtitle Frequently asked questions about XEmacs @* Last Modified: $Date: 2004/07/05 10:42:30 $ +@subtitle Frequently asked questions about XEmacs @* Last Modified: $Date: 2005/02/04 02:51:21 $ @sp 1 -@author Tony Rossini <rossini@@u.washington.edu> @author Ben Wing <ben@@xemacs.org> +@author Tony Rossini <rossini@@u.washington.edu> @author Chuck Thompson <cthomp@@xemacs.org> @author Steve Baur <steve@@xemacs.org> @author Andreas Kaempf <andreas@@sccon.com> @@ -26,6 +26,108 @@ @end direntry @end ifinfo +@ignore + ***************************************** + ***** To update the menus and nodes ***** + ***************************************** + +First, the first argument to @node (the name itself) needs to be correct. +Use a macro if necessary to update the @node names from the +@unnumberedsubsec commands. Also note that the command we're about to +run will not correctly fix up the part of the menu to the right of a ::. +It will leave existing text in place but not change anything. If you +make a lot of changes and want to update this semi-automatically, use +M-x occur to pick out all @unnumberedsubsec lines then do some editing +magic to coerce them into the right format and cut and paste as necessary: + +1. M-x occur @unnumberedsubsec +2. <select a rectangle including all text before the Q#.#.#> +3. C-x r t *<space> +4. go to the top and use the following macro to get the indentation right. + +(setq last-kbd-macro (read-kbd-macro +"C-s : RET : <right> M-x indent- to- column RET 14 RET <home> <down>")) + +5. Cut and paste the menus into the detailmenu at the top and + individual menus at the top of the appropriate chapters. (#### I + wonder, does texinfo-master-menu generate the detailmenu from the + individual menus or vice-versa or neither?) + +Then, + +6. C-u C-c C-u m (C-u M-x texinfo-master-menu) will update the menus + and nodes. However, it appears that even though it tries to + preserve the existing menu structure as much as possible, it + doesn't do a perfect job. It messes up in at least two ways: The + indentation in the part of the main menu above the detailmenu will + be screwed up, and the #.0 titles will be removed from both the + detailmenu and the individual chapter menus. In addition, + sometimes random things get screwed up in individual parts of the + menus. Therefore: + + 1. Use the Lisp line below to get the spacing correct for the Q#.#.# + menu entries. + +(set (make-local-variable 'texinfo-column-for-description) 14) + + 2. Copy the whole detailmenu beforehand. + 3. Run C-u C-c C-u m to fix up the nodes. + 4. Run `fix-main-menu' and `fix-omitted-menu-lines'. + 5. Check the new detailmenu carefully to see if anything is screwed up + compared to the old detailmenu you copied. + 6. If so, paste back the appropriate sections and fix up the corresponding + part of the chapter-specific menu. + +(defun fix-main-menu () + (interactive) + (save-restriction + (let (p q) + (goto-char (point-min)) + (re-search-forward "^@menu") + (setq p (match-beginning 0)) + (re-search-forward "^$") + (setq q (match-end 0)) + (narrow-to-region p q) + (goto-char p) + (while (search-forward ":: " nil t) + (indent-to-column 26))))) + +(defun fix-omitted-menu-lines () + (interactive) + (save-excursion + (loop for x from 1 to 10 do + (goto-char (point-min)) + (re-search-forward (format "@unnumberedsec \\(%d.0: .*\\)" x)) + (let ((line (match-string 1))) + (re-search-backward "^@menu") + (forward-line 1) + (unless (looking-at "[0-9]+.0:") + (insert line) + (insert "\n")) + (goto-char (point-min)) + (re-search-forward "^@menu") + (search-forward (format "Q%d.0.1:" x)) + (forward-line -1) + (unless (looking-at "[0-9]+.0:") + (insert "\n") + (insert line)))))) + + ***************************************** + ***** Other work ***** + ***************************************** + +When you've rearranged and renumbered a bunch of nodes, you can get +the numbers agreeing again. The macro below assumes that the +unnumberedsubsec number is correct, and fixes up the node to agree. +Only the first part of the node is fixed and the other parts may still +be wrong; but they will be fixed as part of +@code{texinfo-master-menu}. + +(setq last-kbd-macro (read-kbd-macro +"<f1> unnumberedsubsec SPC RET C-s : RET <left> C-x C-x <f3> <home> <up> <C-right> <right> C-s , RET <left> C-x C-x <f4> <home> 2*<down>")) +@end ignore + + @node Top, Introduction, (dir), (dir) @top XEmacs FAQ @@ -77,366 +179,389 @@ @c end ifset points to CANONICAL @menu -* Introduction:: Introduction, Policy, Credits. -* Installation:: Installation and Trouble Shooting. -* Customization:: Customization and Options. -* Subsystems:: Major Subsystems. -* Miscellaneous:: The Miscellaneous Stuff. -* MS Windows:: XEmacs on Microsoft Windows. -* Current Events:: What the Future Holds. -* Legacy Versions:: New information about old XEmacsen. +* Introduction:: Introduction, Policy, Credits. +* Installation:: Installation and Troubleshooting. +* Editing:: Editing Functions. +* Display:: Display Functions. +* External Subsystems:: Interfacing with the OS and External Devices. +* Internet:: Connecting to the Internet. +* Advanced:: Advanced Customization Using XEmacs Lisp. +* Other Packages:: Other External Packages. +* Current Events:: What the Future Holds. +* Legacy Versions:: New information about old XEmacsen. @detailmenu - --- The Detailed Node Listing --- -Introduction, Policy, Credits - -* Q1.0.1:: What is XEmacs? -* Q1.0.2:: What is the current version of XEmacs? -* Q1.0.3:: Where can I find it? -* Q1.0.4:: Why Another Version of Emacs? -* Q1.0.5:: Why Haven't XEmacs and GNU Emacs Merged? -* Q1.0.6:: Where can I get help? -* Q1.0.7:: Where are the mailing lists archived? -* Q1.0.8:: How do you pronounce XEmacs? -* Q1.0.9:: What does XEmacs look like? -* Q1.0.10:: Is there a port of XEmacs to Microsoft ('95 or NT)? -* Q1.0.11:: Is there a port of XEmacs to the Macintosh? -* Q1.0.12:: Is there a port of XEmacs to NextStep? -* Q1.0.13:: Is there a port of XEmacs to OS/2? -* Q1.0.14:: Where can I get a printed copy of the XEmacs users manual? - -Policies: -* Q1.1.1:: What is the FAQ editorial policy? -* Q1.1.2:: How do I become a Beta Tester? -* Q1.1.3:: How do I contribute to XEmacs itself? - -Credits: -* Q1.2.1:: Who wrote XEmacs? -* Q1.2.2:: Who contributed to this version of the FAQ? -* Q1.2.3:: Who contributed to the FAQ in the past? - -Internationalization: -* Q1.3.1:: What is the status of internationalization support aka MULE (including Asian language support? -* Q1.3.2:: How can I help with internationalization? -* Q1.3.3:: How do I type non-ASCII characters? -* Q1.3.4:: Can XEmacs messages come out in a different language? -* Q1.3.5:: Please explain the various input methods in MULE/XEmacs -* Q1.3.6:: How do I portably code for MULE/XEmacs? -* Q1.3.7:: How about Cyrillic Modes? -* Q1.3.8:: Does XEmacs support Unicode? -* Q1.3.9:: How does XEmacs display Unicode? - -Getting Started: -* Q1.4.1:: What is an @file{init.el} or @file{.emacs} and is there a sample one? -* Q1.4.2:: Can I use the same @file{init.el}/@file{.emacs} with the other Emacs? -* Q1.4.3:: Any good XEmacs tutorials around? -* Q1.4.4:: May I see an example of a useful XEmacs Lisp function? -* Q1.4.5:: And how do I bind it to a key? -* Q1.4.6:: What's the difference between a macro and a function? - -Installation and Trouble Shooting - -* Q2.0.1:: Running XEmacs without installing. -* Q2.0.2:: XEmacs is too big. -* Q2.0.3:: Compiling XEmacs with Netaudio. -* Q2.0.4:: Problems with Linux and ncurses. -* Q2.0.5:: Do I need X11 to run XEmacs? -* Q2.0.6:: I'm having strange crashes. What do I do? -* Q2.0.7:: Libraries in non-standard locations. -* Q2.0.8:: can't resolve symbol _h_errno -* Q2.0.9:: Where do I find external libraries? -* Q2.0.10:: After I run configure I find a coredump, is something wrong? -* Q2.0.11:: XEmacs can't resolve host names. -* Q2.0.12:: Why can't I strip XEmacs? -* Q2.0.13:: I don't need no steenkin' packages. Do I? -* Q2.0.14:: How do I figure out which packages to install? -* Q2.0.15:: EFS fails with "500 AUTH not understood" (NEW) -* Q2.0.16:: Cygwin XEmacs won't start: cygXpm-noX4.dll was not found (NEW) - -Trouble Shooting: -* Q2.1.1:: XEmacs just crashed on me! -* Q2.1.2:: Cryptic Minibuffer messages. -* Q2.1.3:: Translation Table Syntax messages at Startup. -* Q2.1.4:: Startup warnings about deducing proper fonts? -* Q2.1.5:: XEmacs cannot connect to my X Terminal. -* Q2.1.6:: XEmacs just locked up my Linux X server. -* Q2.1.7:: HP Alt key as Meta. -* Q2.1.8:: got (wrong-type-argument color-instance-p nil)! -* Q2.1.9:: XEmacs causes my OpenWindows 3.0 server to crash. -* Q2.1.10:: Warnings from incorrect key modifiers. -* Q2.1.11:: Can't instantiate image error... in toolbar -* Q2.1.12:: Regular Expression Problems on DEC OSF1. -* Q2.1.13:: HP/UX 10.10 and @code{create_process} failure -* Q2.1.14:: @kbd{C-g} doesn't work for me. Is it broken? -* Q2.1.15:: How to debug an XEmacs problem with a debugger. -* Q2.1.16:: XEmacs crashes in @code{strcat} on HP/UX 10. -* Q2.1.17:: @samp{Marker does not point anywhere}. -* Q2.1.18:: XEmacs is outputting lots of X errors. -* Q2.1.19:: XEmacs does not follow the local timezone. -* Q2.1.20:: @samp{Symbol's function definition is void: hkey-help-show.} -* Q2.1.21:: [This question intentionally left blank] -* Q2.1.22:: XEmacs seems to take a really long time to do some things. -* Q2.1.23:: Movemail on Linux does not work for XEmacs 19.15 and later. -* Q2.1.24:: XEmacs won't start without network. -* Q2.1.25:: After upgrading, XEmacs won't do `foo' any more! - -Customization and Options - -* Q3.0.1:: What version of Emacs am I running? -* Q3.0.2:: How do I evaluate Elisp expressions? -* Q3.0.3:: @code{(setq tab-width 6)} behaves oddly. -* Q3.0.4:: How can I add directories to the @code{load-path}? -* Q3.0.5:: How to check if a lisp function is defined? -* Q3.0.6:: Can I force the output of @code{(face-list)} to a buffer? -* Q3.0.7:: Font selections don't get saved after @code{Save Options}. -* Q3.0.8:: How do I make a single minibuffer frame? -* Q3.0.9:: What is @code{Customize}? - -X Window System & Resources: -* Q3.1.1:: Where is a list of X resources? -* Q3.1.2:: How can I detect a color display? -* Q3.1.3:: [This question intentionally left blank] -* Q3.1.4:: [This question intentionally left blank] -* Q3.1.5:: How can I get the icon to just say @samp{XEmacs}? -* Q3.1.6:: How can I have the window title area display the full path? -* Q3.1.7:: @samp{xemacs -name junk} doesn't work? -* Q3.1.8:: @samp{-iconic} doesn't work. - -Textual Fonts & Colors: -* Q3.2.1:: How can I set color options from @file{init.el}/@file{.emacs}? -* Q3.2.2:: How do I set the text, menu and modeline fonts? -* Q3.2.3:: How can I set the colors when highlighting a region? -* Q3.2.4:: How can I limit color map usage? -* Q3.2.5:: My tty supports color, but XEmacs doesn't use them. -* Q3.2.6:: Can I have pixmap backgrounds in XEmacs? - -The Modeline: -* Q3.3.1:: How can I make the modeline go away? -* Q3.3.2:: How do you have XEmacs display the line number in the modeline? -* Q3.3.3:: How do I get XEmacs to put the time of day on the modeline? -* Q3.3.4:: How do I turn off current chapter from AUC TeX modeline? -* Q3.3.5:: How can one change the modeline color based on the mode used? - -Multiple Device Support: -* Q3.4.1:: How do I open a frame on another screen of my multi-headed display? -* Q3.4.2:: Can I really connect to a running XEmacs after calling up over a modem? How? - -The Keyboard: -* Q3.5.1:: How can I bind complex functions (or macros) to keys? -* Q3.5.2:: How can I stop down-arrow from adding empty lines to the bottom of my buffers? -* Q3.5.3:: How do I bind C-. and C-; to scroll one line up and down? -* Q3.5.4:: Globally binding @kbd{Delete}? -* Q3.5.5:: Scrolling one line at a time. -* Q3.5.6:: How to map @kbd{Help} key alone on Sun type4 keyboard? -* Q3.5.7:: How can you type in special characters in XEmacs? -* Q3.5.8:: [This question intentionally left blank] -* Q3.5.9:: How do I make the Delete key delete forward? -* Q3.5.10:: Can I turn on @dfn{sticky} modifier keys? -* Q3.5.11:: How do I map the arrow keys? - -The Cursor: -* Q3.6.1:: Is there a way to make the bar cursor thicker? -* Q3.6.2:: Is there a way to get back the old block cursor where the cursor covers the character in front of the point? -* Q3.6.3:: Can I make the cursor blink? - -The Mouse and Highlighting: -* Q3.7.1:: How can I turn off Mouse pasting? -* Q3.7.2:: How do I set control/meta/etc modifiers on mouse buttons? -* Q3.7.3:: Clicking the left button does not do anything in buffer list. -* Q3.7.4:: How can I get a list of buffers when I hit mouse button 3? -* Q3.7.5:: Why does cut-and-paste not work between XEmacs and a cmdtool? -* Q3.7.6:: How I can set XEmacs up so that it pastes where the text cursor is? -* Q3.7.7:: How do I select a rectangular region? -* Q3.7.8:: Why does @kbd{M-w} take so long? - -The Menubar and Toolbar: -* Q3.8.1:: How do I get rid of the menu (or menubar)? -* Q3.8.2:: Can I customize the basic menubar? -* Q3.8.3:: How do I control how many buffers are listed in the menu @code{Buffers} list? -* Q3.8.4:: Resources like @code{Emacs*menubar*font} are not working? -* Q3.8.5:: How can I bind a key to a function to toggle the toolbar? - -Scrollbars: -* Q3.9.1:: How can I disable the scrollbar? -* Q3.9.2:: How can one use resources to change scrollbar colors? -* Q3.9.3:: Moving the scrollbar can move the point; can I disable this? -* Q3.9.4:: How can I turn off automatic horizontal scrolling in specific modes? - -Text Selections: -* Q3.10.1:: How can I turn off or change highlighted selections? -* Q3.10.2:: How do I get that typing on an active region removes it? -* Q3.10.3:: Can I turn off the highlight during isearch? -* Q3.10.4:: How do I turn off highlighting after @kbd{C-x C-p} (mark-page)? -* Q3.10.5:: The region disappears when I hit the end of buffer while scrolling. -* Q3.10.6:: Why is killing so slow? - -Major Subsystems - -* Q4.0.1:: How do I set up VM to retrieve remote mail using POP? -* Q4.0.2:: How do I get VM to filter mail for me? -* Q4.0.3:: How can I get VM to automatically check for new mail? -* Q4.0.4:: [This question intentionally left blank] -* Q4.0.5:: How do I get my outgoing mail archived? -* Q4.0.6:: I have various addresses at which I receive mail. How can I tell VM to ignore them when doing a "reply-all"? -* Q4.0.7:: Is there a mailing list or FAQ for VM? -* Q4.0.8:: Remote mail reading with VM. -* Q4.0.9:: rmail or VM gets an error incorporating new mail. -* Q4.0.10:: How do I make VM stay in a single frame? -* Q4.0.11:: How do I make VM or mh-e display graphical smilies? -* Q4.0.12:: Customization of VM not covered in the manual or here. - -Web browsing with W3: -* Q4.1.1:: What is W3? -* Q4.1.2:: How do I run W3 from behind a firewall? -* Q4.1.3:: Is it true that W3 supports style sheets and tables? - -Reading Netnews and Mail with Gnus: -* Q4.2.1:: GNUS, (ding) Gnus, Gnus 5, September Gnus, Red Gnus, Quassia Gnus, argh! -* Q4.2.2:: [This question intentionally left blank] -* Q4.2.3:: How do I make Gnus stay within a single frame? -* Q4.2.4:: How do I customize the From: line? - -Other Mail & News: -* Q4.3.1:: How can I read and/or compose MIME messages? -* Q4.3.2:: What is TM and where do I get it? -* Q4.3.3:: Why isn't this @code{movemail} program working? -* Q4.3.4:: Movemail is also distributed by Netscape? Can that cause problems? -* Q4.3.5:: Where do I find pstogif (required by tm)? - -Sparcworks, EOS, and WorkShop: -* Q4.4.1:: What is SPARCworks, EOS, and WorkShop -* Q4.4.2:: How do I start the Sun Workshop support in XEmacs 21? - -Energize: -* Q4.5.1:: What is/was Energize? - -Infodock: -* Q4.6.1:: What is Infodock? - -Other Unbundled Packages: -* Q4.7.1:: What is AUC TeX? Where do you get it? -* Q4.7.2:: Are there any Emacs Lisp Spreadsheets? -* Q4.7.3:: [This question intentionally left blank] -* Q4.7.4:: Problems installing AUC TeX -* Q4.7.5:: Is there a reason for an Emacs package not to be included in XEmacs? -* Q4.7.6:: Is there a MatLab mode? -* Q4.7.7:: Can I edit files on other hosts? - -The Miscellaneous Stuff - -* Q5.0.1:: How can I do source code highlighting using font-lock? -* Q5.0.2:: I do not like cc-mode. How do I use the old c-mode? -* Q5.0.3:: How do I get @samp{More} Syntax Highlighting on by default? -* Q5.0.4:: How can I enable auto-indent and/or Filladapt? -* Q5.0.5:: How can I get XEmacs to come up in text/auto-fill mode by default? -* Q5.0.6:: How do I start up a second shell buffer? -* Q5.0.7:: Telnet from shell filters too much. -* Q5.0.8:: Why does edt emulation not work? -* Q5.0.9:: How can I emulate VI and use it as my default mode? -* Q5.0.10:: [This question intentionally left blank] -* Q5.0.11:: [This question intentionally left blank] -* Q5.0.12:: How do I disable gnuserv from opening a new frame? -* Q5.0.13:: How do I start gnuserv so that each subsequent XEmacs is a client? -* Q5.0.14:: Strange things are happening in Shell Mode. -* Q5.0.15:: Where do I get the latest CC Mode? -* Q5.0.16:: I find auto-show-mode disconcerting. How do I turn it off? -* Q5.0.17:: How can I get two instances of info? -* Q5.0.18:: [This question intentionally left blank] -* Q5.0.19:: Is there something better than LaTeX mode? -* Q5.0.20:: Is there a way to start a new XEmacs if there's no gnuserv running, and otherwise use gnuclient? - -Emacs Lisp Programming Techniques: -* Q5.1.1:: The difference in key sequences between XEmacs and GNU Emacs? -* Q5.1.2:: Can I generate "fake" keyboard events? -* Q5.1.3:: Could you explain @code{read-kbd-macro} in more detail? -* Q5.1.4:: What is the performance hit of @code{let}? -* Q5.1.5:: What is the recommended use of @code{setq}? -* Q5.1.6:: What is the typical misuse of @code{setq} ? -* Q5.1.7:: I like the @code{do} form of cl, does it slow things down? -* Q5.1.8:: I like recursion, does it slow things down? -* Q5.1.9:: How do I put a glyph as annotation in a buffer? -* Q5.1.10:: @code{map-extents} won't traverse all of my extents! -* Q5.1.11:: My elisp program is horribly slow. Is there an easy way to find out where it spends time? - -Sound: -* Q5.2.1:: How do I turn off the sound? -* Q5.2.2:: How do I get funky sounds instead of a boring beep? -* Q5.2.3:: What's NAS, how do I get it? -* Q5.2.4:: Sunsite sounds don't play. - -Miscellaneous: -* Q5.3.1:: How do you make XEmacs indent CL if-clauses correctly? -* Q5.3.2:: [This question intentionally left blank] -* Q5.3.3:: How can I print WYSIWYG a font-locked buffer? -* Q5.3.4:: Getting @kbd{M-x lpr} to work with postscript printer. -* Q5.3.5:: How do I specify the paths that XEmacs uses for finding files? -* Q5.3.6:: [This question intentionally left blank] -* Q5.3.7:: Can I have the end of the buffer delimited in some way? -* Q5.3.8:: How do I insert today's date into a buffer? -* Q5.3.9:: Are only certain syntactic character classes available for abbrevs? -* Q5.3.10:: How can I get those oh-so-neat X-Face lines? -* Q5.3.11:: How do I add new Info directories? -* Q5.3.12:: What do I need to change to make printing work? - -Mathematics: -* Q5.4.1:: What are bignums, ratios, and bigfloats in Lisp? -* Q5.4.2:: XEmacs segfaults when I use very big numbers! -* Q5.4.3:: Bignums are really slow! -* Q5.4.4:: Equal bignums don't compare as equal! What's going on? - -XEmacs on MS Windows - -General Info: -* Q6.0.1:: What is the status of the XEmacs port to Windows? -* Q6.0.2:: What flavors of MS Windows are supported? The list name implies NT only. -* Q6.0.3:: Are binaries available? -* Q6.0.4:: Can I build XEmacs on MS Windows with X support? Do I need to? -* Q6.0.5:: I'd like to help out. What do I do? -* Q6.0.6:: What are Cygwin and MinGW, and do I need them to run XEmacs? -* Q6.0.7:: What exactly are all the different ways to build XEmacs under Windows? - -Building XEmacs on MS Windows: -* Q6.1.1:: What compiler/libraries do I need to compile XEmacs? -* Q6.1.2:: How do I compile the native port? -* Q6.1.3:: What do I need for Cygwin? -* Q6.1.4:: How do I compile under Cygwin? -* Q6.1.5:: How do I compile using MinGW (aka @samp{the -mno-cygwin flag to gcc})? -* Q6.1.6:: I decided to run with X. Where do I get an X server? -* Q6.1.7:: How do I compile with X support? - -Customization and User Interface: -* Q6.2.1:: How does the port cope with differences in the Windows user interface? -* Q6.2.2:: How do I change fonts in XEmacs on MS Windows? -* Q6.2.3:: Where do I put my @file{init.el}/@file{.emacs} file? -* Q6.2.4:: How do I get Windows Explorer to associate a file type with XEmacs? -* Q6.2.5:: Is it possible to print from XEmacs? - -Miscellaneous: -* Q6.3.1:: Does XEmacs rename all the @samp{win32-*} symbols to @samp{w32-*}? -* Q6.3.2:: What are the differences between the various MS Windows emacsen? -* Q6.3.3:: XEmacs 21.1 on Windows used to spawn an ugly console window on every startup. Has that been fixed? -* Q6.3.4:: What is the porting team doing at the moment? - -Troubleshooting: -* Q6.4.1:: XEmacs won't start on Windows. -* Q6.4.2:: Why do I get a blank toolbar on Windows 95? -* Q6.4.3:: XEmacs complains "No such file or directory, diff" - -What the Future Holds - -* Q7.0.1:: What new features will be in XEmacs soon? -* Q7.0.2:: What's new in XEmacs 21.4? -* Q7.0.3:: What's new in XEmacs 21.1? -* Q7.0.4:: What's new in XEmacs 20.4? -* Q7.0.5:: What's new in XEmacs 20.3? -* Q7.0.6:: What's new in XEmacs 20.2? - -New information about old XEmacsen. +1 Introduction, Policy, Credits -XEmacs 21.1: -* Q8.0.1:: Gnus 5.10 won't display smileys in XEmacs 21.1. +1.0: What is XEmacs? +* Q1.0.1:: What is XEmacs? +* Q1.0.2:: What is the current version of XEmacs? +* Q1.0.3:: How do you pronounce XEmacs? +* Q1.0.4:: What does XEmacs look like? +* Q1.0.5:: Who wrote XEmacs? +* Q1.0.6:: Who wrote the FAQ? + +1.1: Getting XEmacs +* Q1.1.1:: Where can I find XEmacs? +* Q1.1.2:: Are binaries available? +* Q1.1.3:: How do I get the bleeding-edge sources? +* Q1.1.4:: Where can I obtain a printed copy of the XEmacs User's Manual? + +1.2: Versions for Different Operating Systems +* Q1.2.1:: Do I need X11 to run XEmacs? +* Q1.2.2:: What versions of Unix does XEmacs run on? +* Q1.2.3:: Is there a port of XEmacs to Microsoft Windows? +* Q1.2.4:: Can I build XEmacs on MS Windows with X support? Do I need to? +* Q1.2.5:: What are Cygwin and MinGW, and do I need them to run XEmacs? +* Q1.2.6:: What are the differences between the various MS Windows emacsen? +* Q1.2.7:: How does the port cope with differences in the Windows user interface? +* Q1.2.8:: Is there a port of XEmacs to the Macintosh? +* Q1.2.9:: Is there a port of XEmacs to MS-DOS? +* Q1.2.10:: Is there a port of XEmacs to OS/2? +* Q1.2.11:: Is there a port of XEmacs to NextStep? +* Q1.2.12:: Is there a port of XEmacs to VMS? + +1.3: Getting Started +* Q1.3.1:: What is an @file{init.el} or @file{.emacs} and is there a sample one? +* Q1.3.2:: Where do I put my @file{init.el} file? +* Q1.3.3:: Can I use the same @file{init.el} with the other Emacs? +* Q1.3.4:: Any good XEmacs tutorials around? +* Q1.3.5:: May I see an example of a useful XEmacs Lisp function? +* Q1.3.6:: And how do I bind it to a key? +* Q1.3.7:: What's the difference between a macro and a function? +* Q1.3.8:: What is @code{Custom}? + +1.4: Getting Help +* Q1.4.1:: Where can I get help? +* Q1.4.2:: Which mailing lists are there? +* Q1.4.3:: Where are the mailing lists archived? +* Q1.4.4:: How can I get two instances of info? +* Q1.4.5:: How do I add new Info directories? + +1.5: Contributing to XEmacs +* Q1.5.1:: How do I submit changes to the FAQ? +* Q1.5.2:: How do I become a beta tester? +* Q1.5.3:: How do I contribute to XEmacs itself? +* Q1.5.4:: How do I get started developing XEmacs? +* Q1.5.5:: What's the basic layout of the code? + +1.6: Politics (XEmacs vs. GNU Emacs) +* Q1.6.1:: What is GNU Emacs? +* Q1.6.2:: How does XEmacs differ from GNU Emacs? +* Q1.6.3:: How much does XEmacs differ? +* Q1.6.4:: Is XEmacs "GNU"? +* Q1.6.5:: What is the correct way to refer to XEmacs and GNU Emacs? +* Q1.6.6:: Why haven't XEmacs and GNU Emacs merged? + +1.7: External Packages +* Q1.7.1:: What is the package system? +* Q1.7.2:: Which external packages are there? +* Q1.7.3:: Do I need to have the packages to run XEmacs? +* Q1.7.4:: Is there a way to find which package has particular functionality? + +1.8: Internationalization +* Q1.8.1:: What is the status of internationalization support aka MULE (including Asian language support)? +* Q1.8.2:: How can I help with internationalization? +* Q1.8.3:: How do I type non-ASCII characters? +* Q1.8.4:: Can XEmacs messages come out in a different language? +* Q1.8.5:: Please explain the various input methods in MULE/XEmacs +* Q1.8.6:: How do I portably code for MULE/XEmacs? +* Q1.8.7:: How about Cyrillic modes? +* Q1.8.8:: Does XEmacs support Unicode? +* Q1.8.9:: How does XEmacs display Unicode? + +2 Installation and Troubleshooting + +2.0: Installation (General) +* Q2.0.1:: How do I build and install XEmacs? +* Q2.0.2:: Where do I find external libraries? +* Q2.0.3:: How do I specify the paths that XEmacs uses for finding files? +* Q2.0.4:: Running XEmacs without installing +* Q2.0.5:: XEmacs is too big + +2.1: Package Installation +* Q2.1.1:: How do I install the packages? +* Q2.1.2:: Can I install the packages individually? +* Q2.1.3:: Can I install the packages automatically? +* Q2.1.4:: Can I upgrade or remove packages? +* Q2.1.5:: Which packages to install? +* Q2.1.6:: Can you describe the package location process in more detail? +* Q2.1.7:: EFS fails with "500 AUTH not understood" + +2.2: Unix/Mac OS X Installation (Also Relevant to Cygwin, MinGW) +* Q2.2.1:: Libraries in non-standard locations +* Q2.2.2:: Why can't I strip XEmacs? + +2.3: Windows Installation (Windows, Cygwin, MinGW) +* Q2.3.1:: What exactly are all the different ways to build XEmacs under Windows? +* Q2.3.2:: What compiler/libraries do I need to compile XEmacs? +* Q2.3.3:: How do I compile the native port? +* Q2.3.4:: What do I need for Cygwin? +* Q2.3.5:: How do I compile under Cygwin? +* Q2.3.6:: How do I compile using MinGW (aka @samp{the -mno-cygwin flag to gcc})? +* Q2.3.7:: How do I compile with X support? +* Q2.3.8:: Cygwin XEmacs won't start -- cygXpm-noX4.dll was not found (NEW) + +2.4: General Troubleshooting +* Q2.4.1:: How do I deal with bugs or with problems building, installing, or running? +* Q2.4.2:: Help! XEmacs just crashed on me! +* Q2.4.3:: XEmacs crashes and I compiled it myself. +* Q2.4.4:: How to debug an XEmacs problem with a debugger +* Q2.4.5:: I get a cryptic error message when trying to do something. +* Q2.4.6:: XEmacs hangs when I try to do something. +* Q2.4.7:: I get an error message when XEmacs is running in batch mode. +* Q2.4.8:: The keyboard or mouse is not working properly, or I have some other event-related problem. +* Q2.4.9:: @kbd{C-g} doesn't work for me. Is it broken? +* Q2.4.10:: How do I debug process-related problems? +* Q2.4.11:: XEmacs is outputting lots of X errors. +* Q2.4.12:: After upgrading, XEmacs won't do `foo' any more! + +2.5: Startup-Related Problems +* Q2.5.1:: XEmacs cannot connect to my X Terminal! +* Q2.5.2:: Startup problems related to paths or package locations. +* Q2.5.3:: XEmacs won't start without network. +* Q2.5.4:: Startup warnings about deducing proper fonts? +* Q2.5.5:: Warnings from incorrect key modifiers. +* Q2.5.6:: XEmacs 21.1 on Windows used to spawn an ugly console window on every startup. Has that been fixed? + +3 Editing Functions + +3.0: The Keyboard +* Q3.0.1:: How can I customize the keyboard? +* Q3.0.2:: How can I bind complex functions (or macros) to keys? +* Q3.0.3:: How do I bind C-. and C-; to scroll one line up and down? +* Q3.0.4:: Globally binding @kbd{Delete}? +* Q3.0.5:: How to map @kbd{Help} key alone on Sun type4 keyboard? +* Q3.0.6:: How can you type in special characters in XEmacs? +* Q3.0.7:: Can I turn on @dfn{sticky} modifier keys? +* Q3.0.8:: How do I map the arrow keys? +* Q3.0.9:: HP Alt key as Meta. +* Q3.0.10:: Why does edt emulation not work? +* Q3.0.11:: How can I emulate VI and use it as my default mode? + +3.1: The Mouse +* Q3.1.1:: How can I turn off Mouse pasting? +* Q3.1.2:: How do I set control/meta/etc modifiers on mouse buttons? +* Q3.1.3:: Clicking the left button does not do anything in buffer list. +* Q3.1.4:: How can I get a list of buffers when I hit mouse button 3? +* Q3.1.5:: How can I set XEmacs up so that it pastes where the text cursor is? + +3.2: Buffers, Text Editing +* Q3.2.1:: Can I have the end of the buffer delimited in some way? +* Q3.2.2:: How do I insert today's date into a buffer? +* Q3.2.3:: How do I get a single minibuffer frame? +* Q3.2.4:: How can I enable auto-indent and/or Filladapt? +* Q3.2.5:: How can I get XEmacs to come up in text/auto-fill mode by default? + +3.3: Text Selections +* Q3.3.1:: How do I select a rectangular region? +* Q3.3.2:: How can I turn off or change highlighted selections? +* Q3.3.3:: How do I cause typing on an active region to remove it? +* Q3.3.4:: Can I turn off the highlight during isearch? +* Q3.3.5:: Why is killing so slow? +* Q3.3.6:: Why does @kbd{M-w} take so long? + +3.4: Editing Source Code +* Q3.4.1:: I do not like cc-mode. How do I use the old c-mode? +* Q3.4.2:: How do you make XEmacs indent CL if-clauses correctly? + +4 Display Functions + +4.0: Textual Fonts and Colors +* Q4.0.1:: How do I specify a font? +* Q4.0.2:: How do I set the text, menu and modeline fonts? +* Q4.0.3:: How can I set color options from @file{init.el}? +* Q4.0.4:: How can I set the colors when highlighting a region? +* Q4.0.5:: How can I limit color map usage? +* Q4.0.6:: My tty supports color, but XEmacs doesn't use them. +* Q4.0.7:: Can I have pixmap backgrounds in XEmacs? +* Q4.0.8:: How do I display non-ASCII characters? +* Q4.0.9:: Font selections in don't get saved after @code{Save Options}. + +4.1: Syntax Highlighting (Font Lock) +* Q4.1.1:: How can I do source code highlighting using font-lock? +* Q4.1.2:: How do I get @samp{More} Syntax Highlighting on by default? + +4.2: The Modeline +* Q4.2.1:: How can I make the modeline go away? +* Q4.2.2:: How do you have XEmacs display the line number in the modeline? +* Q4.2.3:: How do I get XEmacs to put the time of day on the modeline? +* Q4.2.4:: How can I change the modeline color based on the mode used? + +4.3: The Cursor +* Q4.3.1:: Is there a way to make the bar cursor thicker? +* Q4.3.2:: Is there a way to get back the block cursor? +* Q4.3.3:: Can I make the cursor blink? + +4.4: The Menubar +* Q4.4.1:: How do I get rid of the menubar? +* Q4.4.2:: How can I customize the menubar? +* Q4.4.3:: How do I enable use of the keyboard (@kbd{Alt}) to access menu items? +* Q4.4.4:: How do I control how many buffers are listed in the menu @code{Buffers List}? +* Q4.4.5:: Resources like @code{Emacs*menubar*font} are not working? + +4.5: The Toolbar +* Q4.5.1:: How do I get rid of the toolbar? +* Q4.5.2:: How can I customize the toolbar? +* Q4.5.3:: How can I bind a key to a function to toggle the toolbar? +* Q4.5.4:: @samp{Can't instantiate image error...} in toolbar + +4.6: Scrollbars and Scrolling +* Q4.6.1:: How can I disable the scrollbar? +* Q4.6.2:: How can I change the scrollbar width? +* Q4.6.3:: How can I use resources to change scrollbar colors? +* Q4.6.4:: Moving the scrollbar can move the point; can I disable this? +* Q4.6.5:: Scrolling one line at a time. +* Q4.6.6:: How can I turn off automatic horizontal scrolling in specific modes? +* Q4.6.7:: I find auto-show-mode disconcerting. How do I turn it off? + +4.7: The Gutter Tabs, The Progress Bar, Widgets +* Q4.7.1:: How can I disable the gutter tabs? +* Q4.7.2:: How can I disable the progress bar? +* Q4.7.3:: There are bugs in the gutter or widgets. +* Q4.7.4:: How can I customize the gutter or gutter tabs? + +5 Interfacing with the Operating System and External Devices + +5.0: X Window System and Resources +* Q5.0.1:: Where is a list of X resources? +* Q5.0.2:: How can I detect a color display? +* Q5.0.3:: How can I get the icon to just say @samp{XEmacs}? +* Q5.0.4:: How can I have the window title area display the full path? +* Q5.0.5:: @samp{xemacs -name junk} doesn't work? +* Q5.0.6:: @samp{-iconic} doesn't work. + +5.1: Microsoft Windows +* Q5.1.1:: Does XEmacs rename all the @samp{win32-*} symbols to @samp{w32-*}? +* Q5.1.2:: How do I get Windows Explorer to associate a file type with XEmacs? + +5.2: Printing +* Q5.2.1:: What do I need to change to make printing work? +* Q5.2.2:: How can I print WYSIWYG a font-locked buffer? +* Q5.2.3:: Getting @kbd{M-x lpr} to work with postscript printer. +* Q5.2.4:: Can you print under MS Windows? + +5.3: Sound +* Q5.3.1:: How do I turn off the sound? +* Q5.3.2:: How do I get funky sounds instead of a boring beep? +* Q5.3.3:: What are NAS and ESD (EsounD)? +* Q5.3.4:: Sunsite sounds don't play. + +5.4: Running an Interior Shell, Invoking Subprocesses +* Q5.4.1:: What is an interior shell? +* Q5.4.2:: How do I start up a second shell buffer? +* Q5.4.3:: Telnet from shell filters too much +* Q5.4.4:: Strange things are happening in Shell Mode. +* Q5.4.5:: XEmacs complains "No such file or directory, diff" + +5.5: Multiple Device Support +* Q5.5.1:: How do I open a frame on another screen of my multi-headed display? +* Q5.5.2:: Can I really connect to a running XEmacs after calling up over a modem? How? +* Q5.5.3:: How do I disable gnuserv from opening a new frame? +* Q5.5.4:: How do I start gnuserv so that each subsequent XEmacs is a client? +* Q5.5.5:: Is there a way to start a new XEmacs if there's no gnuserv running, and otherwise use gnuclient? + +6 Connecting to the Internet + +6.0: General Mail and News +* Q6.0.1:: What are the various packages for reading mail? +* Q6.0.2:: How can I send mail? +* Q6.0.3:: How do I get my outgoing mail archived? +* Q6.0.4:: How can I read and/or compose MIME messages? +* Q6.0.5:: How do I customize the From line? +* Q6.0.6:: How do I get my MUA to filter mail for me? +* Q6.0.7:: Remote mail reading with an MUA. +* Q6.0.8:: An MUA gets an error incorporating new mail. +* Q6.0.9:: Why isn't @file{movemail} working? +* Q6.0.10:: How do I make my MUA display graphical smilies? +* Q6.0.11:: How can I get those oh-so-neat X-Face lines? + +6.1: Reading Mail with VM +* Q6.1.1:: How do I set up VM to retrieve mail from a remote site using POP? +* Q6.1.2:: How can I get VM to automatically check for new mail? +* Q6.1.3:: I have various addresses at which I receive mail. How can I tell VM to ignore them when doing a "reply-all"? +* Q6.1.4:: Is there a mailing list or FAQ for VM? +* Q6.1.5:: How do I make VM stay in a single frame? +* Q6.1.6:: Customization of VM not covered in the manual, or here. + +6.2: Reading Netnews and Mail with Gnus +* Q6.2.1:: GNUS, (ding) Gnus, Gnus 5, September Gnus, Red Gnus, Quassia Gnus, argh! +* Q6.2.2:: How do I make Gnus stay within a single frame? + +6.3: FTP Access +* Q6.3.1:: Can I edit files on other hosts? +* Q6.3.2:: What is EFS? + +6.4: Web Browsing with W3 +* Q6.4.1:: What is W3? +* Q6.4.2:: How do I run W3 from behind a firewall? +* Q6.4.3:: Is it true that W3 supports style sheets and tables? + +7 Advanced Customization Using XEmacs Lisp + +7.0: Emacs Lisp and @file{init.el} +* Q7.0.1:: What version of Emacs am I running? +* Q7.0.2:: How can I evaluate Emacs-Lisp expressions? +* Q7.0.3:: @code{(setq tab-width 6)} behaves oddly. +* Q7.0.4:: How can I add directories to the @code{load-path}? +* Q7.0.5:: How to check if a lisp function is defined? +* Q7.0.6:: Can I force the output of @code{(face-list)} to a buffer? + +7.1: Emacs Lisp Programming Techniques +* Q7.1.1:: What is the difference in key sequences between XEmacs and GNU Emacs? +* Q7.1.2:: Can I generate "fake" keyboard events? +* Q7.1.3:: Could you explain @code{read-kbd-macro} in more detail? +* Q7.1.4:: What is the performance hit of @code{let}? +* Q7.1.5:: What is the recommended use of @code{setq}? +* Q7.1.6:: What is the typical misuse of @code{setq}? +* Q7.1.7:: I like the @code{do} form of cl, does it slow things down? +* Q7.1.8:: I like recursion, does it slow things down? +* Q7.1.9:: How do I put a glyph as annotation in a buffer? +* Q7.1.10:: @code{map-extents} won't traverse all of my extents! +* Q7.1.11:: My elisp program is horribly slow. Is there an easy way to find out where it spends time? + +7.2: Mathematics +* Q7.2.1:: What are bignums, ratios, and bigfloats in Lisp? +* Q7.2.2:: XEmacs segfaults when I use very big numbers! +* Q7.2.3:: Bignums are really slow! +* Q7.2.4:: Equal bignums don't compare as equal! What gives? + +8 Other External Packages + +8.0: TeX +* Q8.0.1:: Is there something better than LaTeX mode? +* Q8.0.2:: What is AUCTeX? Where do you get it? +* Q8.0.3:: Problems installing AUCTeX. +* Q8.0.4:: How do I turn off current chapter from AUCTeX modeline? + +8.1: Other Unbundled Packages +* Q8.1.1:: Is there a reason for an Emacs package not to be included in XEmacs? +* Q8.1.2:: Are there any Emacs Lisp Spreadsheets? +* Q8.1.3:: Is there a MatLab mode? + +8.2: Environments Built Around XEmacs +* Q8.2.1:: What are SPARCworks, EOS, and WorkShop? +* Q8.2.2:: How do I start the Sun Workshop support in XEmacs 21? +* Q8.2.3:: What is/was Energize? +* Q8.2.4:: What is Infodock? + +9 What the Future Holds + +9.0: Changes +* Q9.0.1:: What new features will be in XEmacs soon? +* Q9.0.2:: What's new in XEmacs 21.4? +* Q9.0.3:: What's new in XEmacs 21.1? +* Q9.0.4:: What's new in XEmacs 20.4? +* Q9.0.5:: What's new in XEmacs 20.3? +* Q9.0.6:: What's new in XEmacs 20.2? + +10 New information about old XEmacsen + +10.0: XEmacs 21.1 +* Q10.0.1:: Gnus 5.10 won't display smileys in XEmacs 21.1. +* Q10.0.2:: XEmacs won't start on Windows in XEmacs 21.1. @end detailmenu @end menu @@ -451,437 +576,386 @@ wondering what to do next. It is also useful as a reference to available resources. -The previous maintainer of the FAQ was @email{rossini@@biostat.washington.edu, -Anthony Rossini}, who started it, after getting tired of hearing JWZ -complain about repeatedly having to answer questions. -@email{ben@@xemacs.org, Ben Wing} and @email{cthomp@@xemacs.org, Chuck -Thompson}, the principal authors of XEmacs, then took over and Ben did -a massive update reorganizing the whole thing. At which point Anthony -took back over, but then had to give it up again. Some of the other -contributors to this FAQ are listed later in this document. +The previous maintainer of the FAQ was +@email{rossini@@biostat.washington.edu, Anthony Rossini}, who started +it, after getting tired of hearing JWZ complain about repeatedly +having to answer questions. @email{ben@@xemacs.org, Ben Wing} then +took over and did a massive update reorganizing the whole thing. At +this point Anthony took back over, but then had to give it up again. +Some of the other contributors to this FAQ are listed later in this +document. The previous version was converted to hypertext format, and edited by @email{steve@@xemacs.org, Steven L. Baur}. It was converted back to texinfo by @email{hniksic@@xemacs.org, Hrvoje Niksic}. The FAQ was then maintained by @email{andreas@@sccon.com, Andreas Kaempf}, who passed it -on to ChristianNyb@o{}. +on to ChristianNyb@o{}, and then to @email{wambold@@xemacs.org,Sandra Wambold}. + +The current version of the FAQ has been heavily redone by +@email{ben@@xemacs.org, Ben Wing}. If you notice any errors or items which should be added or amended to -this FAQ please send email to @email{faq@@xemacs.org, Sandra -Wambold}. Include @samp{XEmacs FAQ} on the Subject: line. +this FAQ please send email to @email{xemacs-beta@@xemacs.org}. +Include @samp{XEmacs FAQ} on the Subject: line. @menu -Introduction: -* Q1.0.1:: What is XEmacs? -* Q1.0.2:: What is the current version of XEmacs? -* Q1.0.3:: Where can I find it? -* Q1.0.4:: Why Another Version of Emacs? -* Q1.0.5:: Why Haven't XEmacs and GNU Emacs Merged? -* Q1.0.6:: Where can I get help? -* Q1.0.7:: Where are the mailing lists archived? -* Q1.0.8:: How do you pronounce XEmacs? -* Q1.0.9:: What does XEmacs look like? -* Q1.0.10:: Is there a port of XEmacs to Microsoft ('95 or NT)? -* Q1.0.11:: Is there a port of XEmacs to the Macintosh? -* Q1.0.12:: Is there a port of XEmacs to NextStep? -* Q1.0.13:: Is there a port of XEmacs to OS/2? -* Q1.0.14:: Where can I get a printed copy of the XEmacs users manual? - -Policies: -* Q1.1.1:: What is the FAQ editorial policy? -* Q1.1.2:: How do I become a Beta Tester? -* Q1.1.3:: How do I contribute to XEmacs itself? - -Credits: -* Q1.2.1:: Who wrote XEmacs? -* Q1.2.2:: Who contributed to this version of the FAQ? -* Q1.2.3:: Who contributed to the FAQ in the past? - -Internationalization: -* Q1.3.1:: What is the status of internationalization support aka MULE (including Asian language support? -* Q1.3.2:: How can I help with internationalization? -* Q1.3.3:: How do I type non-ASCII characters? -* Q1.3.4:: Can XEmacs messages come out in a different language? -* Q1.3.5:: Please explain the various input methods in MULE/XEmacs -* Q1.3.6:: How do I portably code for MULE/XEmacs? -* Q1.3.7:: How about Cyrillic Modes? -* Q1.3.8:: Does XEmacs support Unicode? -* Q1.3.9:: How does XEmacs display Unicode? - -Getting Started: -* Q1.4.1:: What is an @file{init.el} or @file{.emacs} and is there a sample one? -* Q1.4.2:: Can I use the same @file{init.el}/@file{.emacs} with the other Emacs? -* Q1.4.3:: Any good XEmacs tutorials around? -* Q1.4.4:: May I see an example of a useful XEmacs Lisp function? -* Q1.4.5:: And how do I bind it to a key? -* Q1.4.6:: What's the difference between a macro and a function? +1.0: What is XEmacs? +* Q1.0.1:: What is XEmacs? +* Q1.0.2:: What is the current version of XEmacs? +* Q1.0.3:: How do you pronounce XEmacs? +* Q1.0.4:: What does XEmacs look like? +* Q1.0.5:: Who wrote XEmacs? +* Q1.0.6:: Who wrote the FAQ? + +1.1: Getting XEmacs +* Q1.1.1:: Where can I find XEmacs? +* Q1.1.2:: Are binaries available? +* Q1.1.3:: How do I get the bleeding-edge sources? +* Q1.1.4:: Where can I obtain a printed copy of the XEmacs User's Manual? + +1.2: Versions for Different Operating Systems +* Q1.2.1:: Do I need X11 to run XEmacs? +* Q1.2.2:: What versions of Unix does XEmacs run on? +* Q1.2.3:: Is there a port of XEmacs to Microsoft Windows? +* Q1.2.4:: Can I build XEmacs on MS Windows with X support? Do I need to? +* Q1.2.5:: What are Cygwin and MinGW, and do I need them to run XEmacs? +* Q1.2.6:: What are the differences between the various MS Windows emacsen? +* Q1.2.7:: How does the port cope with differences in the Windows user interface? +* Q1.2.8:: Is there a port of XEmacs to the Macintosh? +* Q1.2.9:: Is there a port of XEmacs to MS-DOS? +* Q1.2.10:: Is there a port of XEmacs to OS/2? +* Q1.2.11:: Is there a port of XEmacs to NextStep? +* Q1.2.12:: Is there a port of XEmacs to VMS? + +1.3: Getting Started +* Q1.3.1:: What is an @file{init.el} or @file{.emacs} and is there a sample one? +* Q1.3.2:: Where do I put my @file{init.el} file? +* Q1.3.3:: Can I use the same @file{init.el} with the other Emacs? +* Q1.3.4:: Any good XEmacs tutorials around? +* Q1.3.5:: May I see an example of a useful XEmacs Lisp function? +* Q1.3.6:: And how do I bind it to a key? +* Q1.3.7:: What's the difference between a macro and a function? +* Q1.3.8:: What is @code{Custom}? + +1.4: Getting Help +* Q1.4.1:: Where can I get help? +* Q1.4.2:: Which mailing lists are there? +* Q1.4.3:: Where are the mailing lists archived? +* Q1.4.4:: How can I get two instances of info? +* Q1.4.5:: How do I add new Info directories? + +1.5: Contributing to XEmacs +* Q1.5.1:: How do I submit changes to the FAQ? +* Q1.5.2:: How do I become a beta tester? +* Q1.5.3:: How do I contribute to XEmacs itself? +* Q1.5.4:: How do I get started developing XEmacs? +* Q1.5.5:: What's the basic layout of the code? + +1.6: Politics (XEmacs vs. GNU Emacs) +* Q1.6.1:: What is GNU Emacs? +* Q1.6.2:: How does XEmacs differ from GNU Emacs? +* Q1.6.3:: How much does XEmacs differ? +* Q1.6.4:: Is XEmacs "GNU"? +* Q1.6.5:: What is the correct way to refer to XEmacs and GNU Emacs? +* Q1.6.6:: Why haven't XEmacs and GNU Emacs merged? + +1.7: External Packages +* Q1.7.1:: What is the package system? +* Q1.7.2:: Which external packages are there? +* Q1.7.3:: Do I need to have the packages to run XEmacs? +* Q1.7.4:: Is there a way to find which package has particular functionality? + +1.8: Internationalization +* Q1.8.1:: What is the status of internationalization support aka MULE (including Asian language support)? +* Q1.8.2:: How can I help with internationalization? +* Q1.8.3:: How do I type non-ASCII characters? +* Q1.8.4:: Can XEmacs messages come out in a different language? +* Q1.8.5:: Please explain the various input methods in MULE/XEmacs +* Q1.8.6:: How do I portably code for MULE/XEmacs? +* Q1.8.7:: How about Cyrillic modes? +* Q1.8.8:: Does XEmacs support Unicode? +* Q1.8.9:: How does XEmacs display Unicode? @end menu +@unnumberedsec 1.0: What is XEmacs? + @node Q1.0.1, Q1.0.2, Introduction, Introduction -@unnumberedsec 1.0: Introduction @unnumberedsubsec Q1.0.1: What is XEmacs? - XEmacs is a powerful, highly customizable open source text editor and -application development system, with full GUI support. It is protected -under the GNU Public License and related to other versions of Emacs, in -particular GNU Emacs. Its emphasis is on modern graphical user -interface support and an open software development model, similar to -Linux. XEmacs has an active development community numbering in the -hundreds (and thousands of active beta testers on top of this), and runs -on all versions of MS Windows, on Linux, and on nearly every other -version of Unix in existence. Support for XEmacs has been supplied by -Sun Microsystems, University of Illinois, Lucid, ETL/Electrotechnical -Laboratory, Amdahl Corporation, BeOpen, and others, as well as the -unpaid time of a great number of individual developers. +application development system, with full GUI support. It is +protected under the GNU Public License and related to other versions +of Emacs, in particular GNU Emacs. Its emphasis is on modern +graphical user interface support and an open software development +model, similar to Linux. XEmacs has an active development community +numbering in the hundreds (and thousands of active beta testers on top +of this), and runs on all versions of MS Windows, on Mac OS X, on +Linux, and on nearly every other version of Unix in existence. +Support for XEmacs has been supplied by Sun Microsystems, University +of Illinois, Lucid, ETL/Electrotechnical Laboratory, Amdahl +Corporation, BeOpen, and others, as well as the unpaid time of a great +number of individual developers. @node Q1.0.2, Q1.0.3, Q1.0.1, Introduction @unnumberedsubsec Q1.0.2: What is the current version of XEmacs? -XEmacs versions 21.1.* are releases made from the current stable -sources. XEmacs versions 21.2.* are releases made from the development -sources. Check at @uref{http://www.xemacs.org} for the current minor -version. +XEmacs versions 21.4.* are releases made from the current stable +sources. XEmacs versions 21.5.* (which will be released as 22.0) are +releases made from the development sources. Check at +@uref{http://www.xemacs.org} for the current minor version. XEmacs +versions 21.1.* were the previous stable releases, now retired. -XEmacs 19.16 was the last release of v19, released in November, 1997, -which was also the last version without international language support. +XEmacs 20.4, released in February 1998, was the last release of v20. -@node Q1.0.3, Q1.0.4, Q1.0.2, Introduction -@unnumberedsubsec Q1.0.3: Where can I find it? +XEmacs 19.16, released in November, 1997. was the last release of v19, +and was also the last version without international language support. -The canonical source and binaries can be found via anonymous FTP at: +@node Q1.0.3, Q1.0.4, Q1.0.2, Introduction +@unnumberedsubsec Q1.0.3: How do you pronounce XEmacs? -@example -@uref{ftp://ftp.xemacs.org/pub/xemacs/} -@end example +The most common pronounciation is @samp{Eks eemax}. @node Q1.0.4, Q1.0.5, Q1.0.3, Introduction -@unnumberedsubsec Q1.0.4: Why Another Version of Emacs? +@unnumberedsubsec Q1.0.4: What does XEmacs look like? -For a detailed description of the differences between GNU Emacs and -XEmacs and a detailed history of XEmacs, check out the -@example -@uref{http://www.xemacs.org/About/XEmacsVsGNUemacs.html, NEWS file} -@end example +Screen snapshots are available at +@uref{http://www.xemacs.org/About/Screenshots/index.html} +as part of the XEmacs website. -However, here is a list of some of the reasons why we think you might -consider using it: +@node Q1.0.5, Q1.0.6, Q1.0.4, Introduction +@unnumberedsubsec Q1.0.5: Who wrote XEmacs? -@itemize @bullet -@item -It looks nicer. +XEmacs is the result of the time and effort of many people, and the +active developers have changed over time. There are two major +components of the XEmacs effort -- writing the code itself and providing +all the support work (testing the code, releasing beta and final +versions, handling patches, reading bug reports, maintaining the web +site, managing the mailing lists, etc. etc.). Neither component would +work without the other. + +@subheading CODING + +The primary code contributor over the years has been Ben Wing (active +since late 1992). Between 1991 and 1995, large amounts of coding was +contributed by Jamie Zawinski and Chuck Thompson. Many other people +have authored major subsystems or otherwise contributed large amounts of +code, including Andy Piper, Hrvoje Niksic, Jerry James, Jonathan Harris, +Kyle Jones, Martin Buchholz, Michael Sperber, Olivier Galibert, Richard +Mlynarik, Stig, William Perry and plenty of others. -@item -The XEmacs maintainers are generally more receptive to suggestions than -the GNU Emacs maintainers. +Primary XEmacs-specific subsystems and their authors: +@table @asis +@item Objects +@itemize @minus @item -Many more bundled packages than GNU Emacs. - +Conversion from 26-bit to 28-bit pointers and integers, lrecords, lcrecords: Richard Mlynarik, 1994 @item -Binaries are available for many common operating systems. - +Conversion to 32-bit pointers and 31-bit integers: Kyle Jones, Martin Buchholz @item -Face support on TTY's. - +Portable dumper, object descriptions: Olivier Galibert @item -A built-in toolbar. - +KKCC (new garbage collector), ephemerons, weak boxes: Michael Sperber and students @item -Better Motif compliance. - +Random object work (object equal and hash methods, weak lists, lcrecord lists, bit vectors, dynarr, blocktype, opaque, string resizing): Ben Wing @item -Some internationalization support (including full MULE support, if -compiled with it). - +Profiling: Ben Wing @item -Variable-width fonts. - +Some byte-compilation and hash-table improvements: Martin Buchholz @item -Variable-height lines. +Bignum: Jerry James +@end itemize +@item Internationalization/Mule +@itemize @minus @item -Marginal annotations. +mostly Ben Wing; many ideas for future work, Stephen Turnbull +@end itemize +@item I/O +@itemize @minus @item -ToolTalk support. - +Basic event/event-stream implementation: Jamie Zawinski @item -XEmacs can be used as an Xt widget, and can be embedded within another -application. - +Most event work since 1994: Ben Wing @item -Horizontal and vertical scrollbars (using real toolkit scrollbars). - +Asynchronous stuff (async timeouts, signals, quit-checking): Ben Wing @item -Better APIs (and performance) for attaching fonts, colors, and other -properties to text. - +Process method abstraction, Windows process work: Kirill Katsnelson @item -The ability to embed arbitrary graphics in a buffer. - +Misc-user events, async timeouts, most quit-checking and signal code, most other work since 1994: Ben Wing @item -Completely compatible (at the C level) with the Xt-based toolkits. - +Lstreams: Ben Wing @end itemize -@node Q1.0.5, Q1.0.6, Q1.0.4, Introduction -@unnumberedsubsec Q1.0.5: Why Haven't XEmacs and GNU Emacs Merged? - -There are currently irreconcilable differences in the views about -technical, programming, design and organizational matters between RMS -and the XEmacs development team which provide little hope for a merge to -take place in the short-term future. - -If you have a comment to add regarding the merge, it is a good idea to -avoid posting to the newsgroups, because of the very heated flamewars -that often result. Mail your questions to @email{xemacs-beta@@xemacs.org} and -@email{bug-gnu-emacs@@prep.ai.mit.edu}. - -@node Q1.0.6, Q1.0.7, Q1.0.5, Introduction -@unnumberedsubsec Q1.0.6: Where can I get help? - -Probably the easiest way, if everything is installed, is to use Info, by -pressing @kbd{C-h i}, or looking for an Info item on the -Help Menu. @kbd{M-x apropos} can be used to look for particular commands. - -For items not found in the manual, try reading this FAQ -@comment , examining the regular GNU Emacs FAQ (which can be -@comment found with the Emacs 19 distribution) as well as at -@comment @uref{http://www.eecs.nwu.edu/emacs/faq/} -and reading the Usenet group comp.emacs.xemacs. - -If you choose to post to a newsgroup, @strong{please use -comp.emacs.xemacs}. Please do not post XEmacs related questions to -gnu.emacs.help. - -If you cannot post or read Usenet news, there is a corresponding mailing -list @email{xemacs-news@@xemacs.org} which is available. It can be -subscribed to via the Mailman Web interface or by sending mail to to -@email{xemacs-news-request@@xemacs.org} with @samp{subscribe} in the -body of the message. See also -@uref{http://www.xemacs.org/Lists/#xemacs-news}. To cancel a -subscription, you may use the @email{xemacs-news-request@@xemacs.org} -address or the Web interface. Send a message with a subject of -@samp{unsubscribe} to be removed. - -@node Q1.0.7, Q1.0.8, Q1.0.6, Introduction -@unnumberedsubsec Q1.0.7: Where are the mailing lists archived? - -The archives can be found at @uref{http://list-archive.xemacs.org} - -@node Q1.0.8, Q1.0.9, Q1.0.7, Introduction -@unnumberedsubsec Q1.0.8: How do you pronounce XEmacs? - -The most common pronounciation is @samp{Eks eemax}. - -@node Q1.0.9, Q1.0.10, Q1.0.8, Introduction -@unnumberedsubsec Q1.0.9: What does XEmacs look like? - -Screen snapshots are available at -@uref{http://www.xemacs.org/About/Screenshots/index.html} -as part of the XEmacs website. - -@node Q1.0.10, Q1.0.11, Q1.0.9, Introduction -@unnumberedsubsec Q1.0.10: Is there a port of XEmacs to Microsoft ('95 or NT)? - -Yes. XEmacs can be built under MS Windows and is fully-featured and -actively developed. See @ref{MS Windows}. - -@node Q1.0.11, Q1.0.12, Q1.0.10, Introduction -@unnumberedsubsec Q1.0.11: Is there a port of XEmacs to the Macintosh? -@c changed - -@c There has been a port to the MachTen environment of XEmacs 19.13, but no -@c patches have been submitted to the maintainers to get this in the -@c mainstream distribution. -@c -@c For the MacOS, there is a port of -@c @uref{ftp://ftp.cs.cornell.edu/pub/parmet/, Emacs 18.59}. - -Yes. - -XEmacs 21.5 (perhaps 21.4 also?) works on MacOS X, although it certainly -will not feel very much like a Mac application as it has no Mac-specific -code in it. - -There is also a port of XEmacs 19.14 that works on all recent versions -of MacOS, from 8.1 through MacOS X, by @email{pjarvis@@ispchannel.com, -Pitts Jarvis}. It runs in an equivalent of TTY mode only (one single -Macintosh window, 25 colors), but has a large number of Mac-specific -additions. It's available at -@uref{http://homepage.mac.com/pjarvis/xemacs.html}. - -@node Q1.0.12, Q1.0.13, Q1.0.11, Introduction -@unnumberedsubsec Q1.0.12: Is there a port of XEmacs to NextStep? - -Carl Edman, apparently no longer at @email{cedman@@princeton.edu}, did -the port of GNU Emacs to NeXTstep and expressed interest in doing the -XEmacs port, but never went any farther. - -@node Q1.0.13, Q1.0.14, Q1.0.12, Introduction -@unnumberedsubsec Q1.0.13: Is there a port of XEmacs to OS/2? - -No, but Alexander Nikolaev <avn_1251@@mail.ru> is working on it. - -@node Q1.0.14, Q1.1.1, Q1.0.13, Introduction -@unnumberedsubsec Q1.0.14: Where can I obtain a printed copy of the XEmacs User's Manual? - -Pre-printed manuals are not available. If you are familiar with -TeX, you can generate your own manual from the XEmacs sources. - -HTML and Postscript versions of XEmacs manuals are available from the -XEmacs web site at -@uref{http://www.xemacs.org/Documentation/index.html}. - -@node Q1.1.1, Q1.1.2, Q1.0.14, Introduction -@unnumberedsec 1.1: Policies -@unnumberedsubsec Q1.1.1: What is the FAQ editorial policy? +@item Display +@itemize @minus +@item +Redisplay mechanism: implementation, Chuck Thompson; additional work, lots of people +@item +Glyphs: mostly Ben Wing +@item +Specifiers: Ben Wing +@item +Extents: initial implementation, someone at Lucid; rewrite, 1994, Ben Wing +@item +Widgets: Andy Piper +@item +JPEG/PNG/TIFF image converters: Ben Wing, William Perry, Jareth Hein, others (see comment in @file{glyphs-eimage.c}) +@item +Menus: Jamie Zawinski, someone at Lucid (Lucid menus) +@item +Scrollbars: Chuck Thompson, ??? (Lucid scrollbar) +@item +Multi-device/device-independence work (console/device/etc methods): Ben Wing, prototype by chuck thompson +@item +Faces: first implementation, Jamie Zawinski; second, chuck; third, Ben Wing +@item +Fonts/colors: first implementation, Jamie Zawinski; further work, Ben Wing +@item +Toolbars: implementation, chuck, much interface work, Ben Wing +@item +Gutters, tabs: andy piper +@end itemize -The FAQ is actively maintained and modified regularly. All links should -be up to date. Unfortunately, some of the information is out of date -- -a situation which the FAQ maintainer is working on. All submissions are -welcome, please e-mail submissions to @email{faq@@xemacs.org, XEmacs FAQ -maintainers}. +@item Device subsystems +@itemize @minus +@item +X Windows: Jamie Zawinksi, Ben Wing, others +@item +GTK: William Perry, Malcolm Purvis +@item +MS Windows: initial implementation, Jonathan Harris; some more work, Andy Piper, Ben Wing +@item +TTY: Chuck Thompson, Ben Wing +@item +Cygwin: Andy Piper +@end itemize -Please make sure that @samp{XEmacs FAQ} appears on the Subject: line. -If you think you have a better way of answering a question, or think a -question should be included, we'd like to hear about it. Questions and -answers included into the FAQ will be edited for spelling and grammar -and will be attributed. Answers appearing without attribution are -either from versions of the FAQ dated before May 1996 or are from -previous FAQ maintainers. Answers quoted from Usenet news articles will -always be attributed, regardless of the author. +@item Misc +@itemize @minus +@item +Configure: initial porting from fsf, Chuck Thompson; conversion to autoconf 2, much rewriting, Martin Buchholz +@item +Most initialization-related code: Ben Wing +@item +Internals manual, much of Lisp manual: Ben Wing +@item +FSF synching: initial sync with FSF 19, Richard Mlynarik, further work, Ben Wing +@end itemize +@end table -@node Q1.1.2, Q1.1.3, Q1.1.1, Introduction -@unnumberedsubsec Q1.1.2: How do I become a Beta Tester? +@subheading SUPPORT -Send an email message to @email{xemacs-beta-request@@xemacs.org} with -the line @samp{subscribe} in the body of the message. +Currently, support duties are handled by many different people. -Be prepared to get your hands dirty, as beta testers are expected to -identify problems as best they can. +Release managers have been -@node Q1.1.3, Q1.2.1, Q1.1.2, Introduction -@unnumberedsubsec Q1.1.3: How do I contribute to XEmacs itself? +@itemize @minus +@item +Stephen Turnbull (April 2001 - January 2003, March 2004 - present, 21.2.47 - 21.4.12, 21.5.2 - 21.5.7, 21.5.17 - present) +@item +Vin Shelton (May 2003 - present, 21.4.13 - present) +@item +Steve Youngs (July 2002 - September 2003, 21.5.8 - 21.5.16) +@item +Martin Buchholz (December 1998, November 1999 - May 2001, 21.2.7 - 21.2.8, 21.2.21 - 21.2.46, 21.5.0 - 21.5.1) +@item +Steve Baur (early 1997 - December 1998, February 1999 - November 1999, 19.15 - 21.2.5, 21.2.9 - 21.2.20) +@item +Andy Piper (December 1998, 21.2.6) +@item +Chuck Thompson (June 1994 - September 1996, 19.11 - 19.14) +@item +Jamie Zawinski (April 1991 - June 1994, 19.0 - 19.10) +@end itemize -Ben Wing @email{ben@@xemacs.org} writes: +The recent overlapping dates are intentional, since two or three trees +are maintained simultaneously at any point. -@quotation -BTW if you have a wish list of things that you want added, you have to -speak up about it! More specifically, you can do the following if you -want a feature added (in increasing order of usefulness): +Other major support work: -@itemize @bullet +@itemize @minus @item -Make a posting about a feature you want added. - +Adrian Aichner wrote and maintains the web site. @item -Become a beta tester and make more postings about those same features. - +Stephen Turnbull has produced many of the beta and semi-stable releases +and has attempted to be the "face" of XEmacs on the newsgroups and +mailing lists. @item -Convince us that you're going to use the features in some cool and -useful way. - +Steve Youngs currently produces the beta releases (???). @item -Come up with a clear and well-thought-out API concerning the features. - +Steve Youngs, Ville Skytta, and now Norbert Koch have taken turns +maintaining the packages. @item -Write the code to implement a feature and send us a patch. +Vin Shelton maintains the stable releases. +@item +Testing - #### Norbert, Adrian, ??? @end itemize -(not that we're necessarily requiring you to write the code, but we can -always hope :) -@end quotation - -@node Q1.2.1, Q1.2.2, Q1.1.3, Introduction -@unnumberedsec 1.2: Credits -@unnumberedsubsec Q1.2.1: Who wrote XEmacs? - -XEmacs is the result of the time and effort of many people. The -developers responsible for recent releases are: +Portraits and email of some of the major developers: @itemize @bullet -@item @email{martin@@xemacs.org, Martin Buchholz} +@item @email{andy@@xemacs.org, Andy Piper} @html -<br><img src="mrb.jpeg" alt="Portrait of Martin Buchholz"><br> +<br><img src="piper.png" alt="Portrait of Andy Piper"><br> @end html - -@item @email{stephen@@xemacs.org, Stephen Turnbull} - - @item @email{ben@@xemacs.org, Ben Wing} @html -<br><img src="wing.gif" alt="Portrait of Ben Wing"><br> +<br><img src="ben.png" alt="Portrait of Ben Wing"><br> @end html - -@item @email{hniksic@@xemacs.org, Hrvoje Niksic} - +@item @email{cthomp@@xemacs.org, Chuck Thompson} @html -<br><img src="hniksic.jpeg" alt="Portrait of Hrvoje Niksic"><br> +<br><img src="cthomp.png" alt="Portrait of Chuck Thompson"><br> @end html -@end itemize - -The developers responsible for older releases were: - -@itemize @bullet -@item @email{steve@@xemacs.org, Steve Baur} +@item @email{hniksic@@xemacs.org, Hrvoje Niksic} @html -<br><img src="steve.gif" alt="Portrait of Steve Baur"><br> +<br><img src="hniksic.png" alt="Portrait of Hrvoje Niksic"><br> @end html -@item @email{cthomp@@xemacs.org, Chuck Thompson} +@item @email{jwz@@jwz.org, Jamie Zawinski} @html -<br><img src="cthomp.jpeg" alt="Portrait of Chuck Thompson"><br> +<br><img src="jwz.png" alt="Portrait of Jamie Zawinski"><br> @end html -@item @email{jwz@@jwz.org, Jamie Zawinski} +@item @email{martin@@xemacs.org, Martin Buchholz} @html -<br><img src="jwz.gif" alt="Portrait of Jamie Zawinski"><br> +<br><img src="martin.png" alt="Portrait of Martin Buchholz"><br> @end html @item @email{mly@@adoc.xerox.com, Richard Mlynarik} +@html +<br><img src="mly.png" alt="Portrait of Richard Mlynarik"><br> +@end html -Steve Baur was the primary maintainer for 19.15 through 21.0. - -Chuck Thompson and Ben Wing were the maintainers for 19.11 through 19.14 -and heavy code contributors for 19.8 through 19.10. - -Jamie Zawinski was the maintainer for 19.0 through 19.10 (the entire -history of Lucid Emacs). Richard Mlynarik was a heavy code contributor -to 19.6 through 19.8. +@item @email{stephen@@xemacs.org, Stephen Turnbull} +@item @email{steve@@xemacs.org, Steve Baur} +@html +<br><img src="slb.png" alt="Portrait of Steve Baur"><br> +@end html @end itemize -Along with many other contributors, partially enumerated in the -@samp{About XEmacs} option in the Help menu. +Many other people have contributed to XEmacs; this is partially +enumerated in the @samp{About XEmacs} option in the Help menu. -@node Q1.2.2, Q1.2.3, Q1.2.1, Introduction -@unnumberedsubsec Q1.2.2: Who contributed to this version of the FAQ? +@node Q1.0.6, Q1.1.1, Q1.0.5, Introduction +@unnumberedsubsec Q1.0.6: Who wrote the FAQ? -The following people contributed valuable suggestions to building this -version of the FAQ (listed in alphabetical order): +The current version of this FAQ was created by @email{ben@@xemacs.org, +Ben Wing}. + +Previous contributors to the FAQ include @itemize @bullet @item @email{steve@@xemacs.org, SL Baur} @item @email{hniksic@@xemacs.org, Hrvoje Niksic} -@item @email{Aki.Vehtari@@hut.fi, Aki Vehtari} - -@end itemize - -@node Q1.2.3, Q1.3.1, Q1.2.2, Introduction -@unnumberedsubsec Q1.2.3: Who contributed to the FAQ in the past? - -This is only a partial list, as many names were lost in a hard disk -crash some time ago. - -@itemize @bullet @item @email{binge@@aloft.att.com, Curtis.N.Bingham} @item @email{bruncott@@dormeur.inria.fr, Georges Brun-Cottan} @@ -921,308 +995,390 @@ @item @email{Aki.Vehtari@@hut.fi, Aki Vehtari} @end itemize -@node Q1.3.1, Q1.3.2, Q1.2.3, Introduction -@unnumberedsec 1.3: Internationalization -@unnumberedsubsec Q1.3.1: What is the status of internationalization support aka MULE (including Asian language support? - -Both the stable and development versions of XEmacs include -internationalization support (aka MULE). MULE currently (21.4) works on -UNIX and Linux systems. It is possible to build with MULE on Windows -systems, but if you really need MULE on Windows, it is recommended that -you build and use the development (21.5) version, and deal with the -instability of the development tree. Binaries compiled without MULE -support run faster than MULE capable XEmacsen. +@unnumberedsec 1.1: Getting XEmacs -@node Q1.3.2, Q1.3.3, Q1.3.1, Introduction -@unnumberedsubsec Q1.3.2: How can I help with internationalization? +@node Q1.1.1, Q1.1.2, Q1.0.6, Introduction +@unnumberedsubsec Q1.1.1: Where can I find XEmacs? -If you would like to help, you may want to join the -@email{xemacs-mule@@xemacs.org} mailing list. Especially needed are -people who speak/write languages other than English, who are willing to -use XEmacs/MULE regularly, and have some experience with Elisp. +To download XEmacs, visit the XEmacs WWW page at +@uref{http://www.xemacs.org/Download/}. The most up-to-date list of +distribution sites can always be found there. Try to pick a site that +is networkologically close to you. If you know of other mirrors of +the XEmacs archives, please send e-mail to +@uref{mailto:webmaster@@xemacs.org} and we will list them here as well. + +The canonical distribution point is ftp.xemacs.org, available either +through HTTP (@uref{http://ftp.xemacs.org/}) or anonymous FTP +(@uref{ftp://ftp.xemacs.org/pub/xemacs/}). -Translations of the TUTORIAL and man page are welcome, and XEmacs does -support multilingual menus, but we have few current translations. +@node Q1.1.2, Q1.1.3, Q1.1.1, Introduction +@unnumberedsubsec Q1.1.2: Are binaries available? -@xref{Q1.1.2}. +MS Windows binaries are available at +@uref{http://www.xemacs.org/Download/win32/} for the native versions +of 21.4 and 21.1. Cygwin binaries are now available as part of the +standard Cygwin installation process. XEmacs also comes pre-built as +part of many Linux distributions, such as Red Hat and SuSE. + +Otherwise, you will need to build XEmacs yourself or get your system +administrator to do it. Generally, this is not a difficult process +under Unix and Mac OS X, as XEmacs has been tested under all of the +common Unix versions and under Mac OS X and comes with an extensive +configure script that is able to automatically detect most aspects of +the configuration of your particular system. + +@node Q1.1.3, Q1.1.4, Q1.1.2, Introduction +@unnumberedsubsec Q1.1.3: How do I get the bleeding-edge sources? + +If you are interested in developing XEmacs, or getting the absolutely most +recent, up-to-the-moment, bleeding-edge source code, you can directly +access the master CVS source tree (read-only, of course, until you ask for +and are granted permission to directly modify portions of the source tree) +at cvs.xemacs.org. Directions on how to access the source tree are located +at @uref{http://www.xemacs.org/Develop/cvsaccess.html}. -@node Q1.3.3, Q1.3.4, Q1.3.2, Introduction -@unnumberedsubsec Q1.3.3: How do I type non-ASCII characters? +Nightly CVS snapshots are available at +@uref{http://www.dk.xemacs.org/Download/CVS-snapshots/}. -See question 3.5.7 (@pxref{Q3.5.7}) in part 3 of this FAQ for some -simple methods that also work in non-MULE builds of XEmacs (but only for -one-octet coded character sets, and mostly for ISO 8859/1). Many of the -methods available for Cyrillic (@pxref{Q1.3.7}) work without MULE. -MULE has more general capabilities. @xref{Q1.3.5}. +@node Q1.1.4, Q1.2.1, Q1.1.3, Introduction +@unnumberedsubsec Q1.1.4: Where can I obtain a printed copy of the XEmacs User's Manual? -@xref{Q3.2.7}, which covers display of non-ASCII characters. +Pre-printed manuals are not available. If you are familiar with +TeX, you can generate your own manual from the XEmacs sources. -@node Q1.3.4, Q1.3.5, Q1.3.3, Introduction -@unnumberedsubsec Q1.3.4: Can XEmacs messages come out in a different language? +HTML and Postscript versions of XEmacs manuals are available from the +XEmacs web site at +@uref{http://www.xemacs.org/Documentation/index.html}. -The message-catalog support was written but is badly bit-rotted. XEmacs -20 and 21 did @emph{not} support it, and early releases of XEmacs 22 -will not either. +@unnumberedsec 1.2: Versions for Different Operating Systems -However, menubar localization @emph{does} work. To enable it, add to -your @file{Emacs} file entries like this: +@node Q1.2.1, Q1.2.2, Q1.1.4, Introduction +@unnumberedsubsec Q1.2.1: Do I need X11 to run XEmacs? + +No. The name @dfn{XEmacs} is unfortunate in the sense that it is +@strong{not} an X Window System-only version of Emacs. XEmacs has +full color support on a color-capable character terminal. + +@node Q1.2.2, Q1.2.3, Q1.2.1, Introduction +@unnumberedsubsec Q1.2.2: What versions of Unix does XEmacs run on? + +XEmacs is regularly tested on Linux, Solaris, SunOS, HP/UX, FreeBSD, +OpenBSD, BSD/OS aka BSDI, Tru64 aka DEC/OSF, SCO5, and probably +others. It should work on all versions of Unix created in the last 10 +years or so, perhaps with a bit of work on more obscure platforms to +correct bit-rot. It uses a sophisticated configuration system to +auto-detect zillions of features that are implemented differently in +different versions of Unix, so it will probably work on your vendor's +version, possibly with a bit of tweaking, even if we've never heard of +it. + +For problems with particular machines and versions of Unix, see the +@file{PROBLEMS} file. + +Much effort has gone into making XEmacs work on as many different +machines, configurations, and compilers as possible. + +Much effort has gone into making XEmacs 64-bit clean. + +Much effort has gone into removing system-specific code, and replacing +such code with autodetection at configure time. + +The XEmacs core should build "out of the box" on most Unix-like systems. + +XEmacs 21.2 was tested and @samp{make check} succeeded on these Unix +configurations as of 2001-02-10: @example -Emacs*XlwMenu.resourceLabels: True -Emacs*XlwMenu.file.labelString: Fichier -Emacs*XlwMenu.openInOtherWindow.labelString: In anderem Fenster oeffnen +alphaev56-dec-osf4.0e (both Compaq C and gcc) +i386-unknown-freebsd4.2 +i386-unknown-netbsdelf1.5 +i586-sco-sysv5uw7.0.1 (both SCO's cc and gcc) +i686-pc-linux-gnu +hppa2.0-hp-hpux10.20 (both HP's ANSI cc and gcc) +mips-sgi-irix6.5 (both MIPSpro cc and gcc) +rs6000-ibm-aix4.3.0.0 (both IBM's xlc and gcc) +sparc-sun-solaris2.6 (both Sun's Forte C and gcc) +sparc-sun-solaris2.7 (both Sun's Forte C and gcc) +sparc-sun-sunos4.1.4 (gcc) @end example -The name of the resource is derived from the non-localized entry by -removing punctuation and capitalizing as above. +Some systems have a dual mode 32-bit/64-bit compiler. On most of +these, XEmacs requires the @samp{--pdump} configure option to build +correctly with the 64-bit version of the compiler. -@node Q1.3.5, Q1.3.6, Q1.3.4, Introduction -@unnumberedsubsec Q1.3.5: Please explain the various input methods in MULE/XEmacs +@example +mips-sgi-irix6.5, CC="gcc -mabi=64" +mips-sgi-irix6.5, CC="cc -64" +rs6000-ibm-aix4.3.0.0, CC="cc -q64" +@end example -Mule supports a wide variety of input methods. There are three basic -classes: Lisp implementations, generic platform support, and library -interfaces. +On most of these systems, XEmacs also builds with a C++ compiler, +but not "out of the box". This feature is only for use by the +maintainers. -@emph{Lisp implementations} include Quail, which provides table-driven input -methods for almost all the character sets that Mule supports (including -all of the ISO 8859 family, the Indic languages, Thai, and so on), and -SKK, for Japanese. (SKK also supports an interface to an external -"dictionary server" process.) Quail supports both typical "dead-key" -methods (eg, in the "latin-1-prefix" method, @kbd{" a} produces ä, LATIN -SMALL LETTER A WITH DIAERESIS), and the complex dictionary-based phonetic -methods used for Asian ideographic languages like Chinese. - -Lisp implementations can be less powerful (but they are not perceptibly -inefficient), and of course are not portable to non-Emacs applications. -The incompatibility can be very annoying. On the other hand, they -require no special platform support or external libraries, so if you can -display the characters, Mule can input them for you and you can edit, -anywhere. +XEmacs 21.2 is known @emph{not} to work on any machines with m680x0 +processors. Sorry, all you sun3 and Unix PC nostalgia buffs out there. -@emph{Generic platform support} is currently limited to the X Input -Method (XIM) framework, although support for MSIME (for MS Windows) is -planned, and IIIMF (Sun's Internet-Intranet Input Method Framework) -support is extremely desirable. XIM is enabled at build time by use of -the @samp{--with-xim} flag to @code{configure}. For use of XIM, see -your platform documentation. However, normally the input method you use -is specified via the @samp{LANG} and @samp{XMODIFIERS} environment -variables. +VMS has never been supported by XEmacs. In fact, all the old VMS code +inherited from Emacs has been removed. Sorry, all you VMS fans out there. -Of course, input skills are portable across most applications. However, -especially in modern GUI systems the habit of using bucky bits has -fallen into sad disuse, and many XIM systems are poorly configured for -use with Emacs. For example, the kinput2 input manager (a separate -process providing an interface between Japanese dictionary servers such -as Canna and Wnn, and the application) tends to gobble up keystrokes -generating Meta characters. This means that to edit while using an XIM -input method, you must toggle the input method off every time you want -to use @kbd{M-f}. Your mileage may vary. +@node Q1.2.3, Q1.2.4, Q1.2.2, Introduction +@unnumberedsubsec Q1.2.3: Is there a port of XEmacs to Microsoft Windows? -@emph{Library interfaces} are most common for Japanese, although Wnn -supports Chinese (traditional and simplified) and Korean. There are -Chinese and Korean input servers available, but we do not know of any -patches for XEmacs to use them directly. You can use them via -IM-enabled terminals, by manipulating the terminal coding systems. We -describe only the Japanese-oriented systems here. The advantage of -these systems is that they are very powerful, and on platforms where -they are available there is typically a wide range of applications that -support them. Thus your input skills are portable across applications. +Yes. Beginning with release 21.0, XEmacs has worked under MS Windows +and is fully-featured and actively developed. A group of dedicated +developers actively maintains and improves the Windows-specific +portions of the code. Some of the core developers, in fact, use +Windows as their only development environment, and some features, such +as printing, actually work better on Windows than native Unix and Mac +OS X. The mailing list at @email{xemacs-winnt@@xemacs.org} is dedicated +to that effort (please use the -request address to +subscribe). (Despite its name, XEmacs actually works on all versions +of Windows.) -Mule provides built-in interfaces to the following input methods: Wnn4, -Wnn6, Canna, and SJ3. These can be configured at build time. There are -patches available (no URL, sorry) to support the SKK server, as well. -Wnn and SJ3 use the @code{egg} user interface. The interface for Canna -is specialized to Canna. +The list name is misleading, as XEmacs supports and has been compiled on +Windows 95, Windows 98, Windows NT, Windows 2000, Windows ME, Windows +XP, and all newer versions of Windows. The MS Windows-specific code is +based on Microsoft Win32 API, and will not work on MS Windows 3.x or on +MS-DOS. -Wnn supports Japanese, Chinese and Korean. It is made by OMRON and Kyôto -University. It is a powerful and complex system. Wnn4 is free and Wnn6 -is not. Wnn uses grammatical hints and probability of word association, -so in principle Wnn can be cleverer than other methods. +XEmacs also supports the Cygwin and MinGW development and runtime +environments, where it also uses native Windows code for graphical +features. In addition, under Cygwin it is possible to compile XEmacs +to use an X server (and XFree86 is available as part of the standard +Cygwin installation). -Canna, made by NEC, supports only Japanese. It is a simple and powerful -system. Canna uses only grammar, but its grammar and dictionary are -quite sophisticated. So for standard modern Japanese, Canna seems -cleverer than Wnn4. In addition, the UNIX version of Canna is free (now -there is a Microsoft Windows version). +@node Q1.2.4, Q1.2.5, Q1.2.3, Introduction +@unnumberedsubsec Q1.2.4: Can I build XEmacs on MS Windows with X support? Do I need to? -SJ3, by Sony, supports only Japanese. +Yes, you can, but no you do not need to. In fact, we recommend that you +use a native-GUI version unless you have a specific need for an X +version. -Egg consists of following parts: +@node Q1.2.5, Q1.2.6, Q1.2.4, Introduction +@unnumberedsubsec Q1.2.5: What are Cygwin and MinGW, and do I need them to run XEmacs? -@enumerate -@item -Input character Translation System (ITS) layer. -It translates ASCII inputs to Kana/PinYin/Hangul characters. +To answer the second part of the question: No, you, you don't need +Cygwin or MinGW to build or to run XEmacs. But if you have them and +want to use them, XEmacs supports these environments. -@item -Kana/PinYin/Hangul to Kanji transfer layer. -The interface layer to network Kana-Kanji server (Wnn and Sj3). -@end enumerate +(One important reason to support Cygwin is that it lets the MS Windows +developers test out their code in a Unix environment without actually +having to have a Unix machine around. For this reason alone, Cygwin +support is likely to remain supported for a long time in XEmacs. Same +goes for the X support under Cygwin, for the same reasons. MinGW +support, on the other hand, depends on volunteers to keep it up to date; +but this is generally not hard.) -These input methods are modal. They have a raw (alphabet) mode, a -phonetic input mode, and Kana-Kanji transfer mode. However there are -mode-less input methods for Egg and Canna. @samp{boiled-egg} is a -mode-less input method running on Egg. For Canna, @samp{canna.el} has a -tiny boiled-egg-like command, @code{(canna-boil)}, and there are some -boiled-egg-like utilities. +Cygwin is a set of tools providing Unix-like API on top of Win32. +It makes it easy to port large Unix programs without significant +changes to their source code. It is a development environment as well +as a runtime environment. -Much of this information was provided by @email{morioka@@jaist.ac.jp, -MORIOKA Tomohiko}. +When built with Cygwin, XEmacs supports all display types -- TTY, X & +Win32 GUI, and can be built with support for all three simultaneously. +If you build with Win32 GUI support then the Cygwin version uses the +majority of the Windows-specific code, which is mostly related to +display. If you want to build with X support you need X libraries (and +an X server to display XEmacs on); see @ref{Q2.3.7}. TTY and Win32 GUI +require no additional libraries beyond what comes standard with Cygwin. -@node Q1.3.6, Q1.3.7, Q1.3.5, Introduction -@unnumberedsubsec Q1.3.6: How do I portably code for MULE/XEmacs? +The advantages of the Cygwin version are that it integrates well with +the Cygwin environment for existing Cygwin users; uses configure so +building with different features is very easy; and actively supports X & +TTY. Furthermore, the entire Cygwin environment and compiler are free, +whereas Visual C++ costs money. -MULE has evolved rapidly over the last few years, and the original third -party patch (for GNU Emacs 19), GNU Emacs 20+, and XEmacs 20+ have quite -different implementations. The APIs also vary although recent versions -of XEmacs have tended to converge to the GNU Emacs standard. +The disadvantage is that it requires the whole Cygwin environment, +whereas the native port requires only a suitable MS Windows compiler. +Also, it follows the Unix filesystem and process model very closely +(some will undoubtedly view this as an advantage). -MULE implementations are going to continue to evolve. Both GNU Emacs -and XEmacs are working hard on Unicode support, which will involve new -APIs and probably variations on old ones. For XEmacs 22, the old ISO -2022-based system for recognizing encodings will be replaced by a much -more flexible system, which should improve accuracy of automatic coding -detections, but will also involve new APIs. +See @uref{http://www.cygwin.com/} for more information on +Cygwin. -@email{morioka@@jaist.ac.jp, MORIOKA Tomohiko} writes: +MinGW is a collection of header files and import libraries that allow +one to use GCC under the Cygwin environment to compile and produce +exactly the same native Win32 programs that you can using Visual C++. +Programs compiled with MinGW make use of the standard Microsoft runtime +library @file{MSVCRT.DLL}, present on all Windows systems, and look, +feel, and act like a standard Visual-C-produced application. (The only +difference is the compiler.) This means that, unlike a +standardly-compiled Cygwin application, no extra runtime support +(e.g. Cygwin's @file{cygwin1.dll}) is required. This, along with the +fact that GCC is free (and works in a nice Unix-y way in a nice Unix-y +environment, for those die-hard Unix hackers out there), is the main +advantage of MinGW. It is also potentially faster than Cygwin because +it has less overhead when calling Windows, but you lose the POSIX +emulation layer, which makes Unix programs harder to port. (But this is +irrelevant for XEmacs since it's already ported to Win32.) -@quotation -The application implementor must write separate code for these mule -variants. [Please don't hesitate to report these variants to us; they -are not, strictly speaking, bugs, but they give third-party developers -the same kind of creepy-crawly feeling. We'll do what we can. -- Ed.] +See @uref{http://www.mingw.org/} for more information on MinGW. -MULE and the next version of Emacs are similar but the symbols are very -different---requiring separate code as well. +@node Q1.2.6, Q1.2.7, Q1.2.5, Introduction +@unnumberedsubsec Q1.2.6: What are the differences between the various MS Windows emacsen? -Namely we must support 3 kinds of mule variants and 4 or 5 or 6 kinds of -emacs variants... (;_;) I'm shocked, so I wrote a wrapper package called -@code{emu} to provide a common interface. [There is an XEmacs package -of APEL which provides much more comprehensive coverage. Be careful, -however; APEL has problems of its own. -- Ed.] +XEmacs, Win-Emacs, DOS Emacs, NT Emacs, this is all very confusing. +Could you briefly explain the differences between them? -I have the following suggestions about dealing with mule variants: +Here is a recount of various Emacs versions running on MS Windows: @itemize @bullet + @item -@code{(featurep 'mule)} @code{t} on all mule variants +XEmacs + +@itemize @minus @item -@code{(boundp 'MULE)} is @code{t} on only MULE. Maybe the next version -of Emacs will not have this symbol. +Beginning with XEmacs 19.12, XEmacs' architecture was redesigned +in such a way to allow clean support of multiple window systems. At +this time the TTY support was added, making X and TTY the first two +"window systems" supported by XEmacs. The 19.12 design is the basis for +the current native MS Windows code. @item -MULE has a variable @code{mule-version}. Perhaps the next version of -Emacs will have this variable as well. +Some time during 1997, David Hobley (soon joined by Marc Paquette) +imported some of the NT-specific portions of GNU Emacs, making XEmacs +with X support compile under Windows NT, and creating the "X" port. + +@item +Several months later, Jonathan Harris sent out initial patches to use +the Win32 API, thus creating the native port. Since then, various +people have contributed, including Kirill M. Katsnelson (contributed +support for menubars, subprocesses and network, as well as loads of +other code), Andy Piper (ported XEmacs to Cygwin environment, +contributed Windows unexec, Windows-specific glyphs and toolbars code, +and more), Ben Wing (loads of improvements; primary MS Windows developer +since 2000), Jeff Sparkes (contributed scrollbars support) and many +others. @end itemize -Following is a sample to distinguish mule variants: +@item +NT Emacs -@lisp -(if (featurep 'mule) - (cond ((boundp 'MULE) - ;; for original Mule - ) - ((string-match "XEmacs" emacs-version) - ;; for XEmacs with Mule - ) - (t - ;; for next version of Emacs - )) - ;; for old emacs variants - ) -@end lisp -@end quotation +@itemize @minus -@node Q1.3.7, Q1.3.8, Q1.3.6, Introduction -@unnumberedsubsec Q1.3.7: How about Cyrillic Modes? +@item +NT Emacs was an early version of GNU Emacs 19 modified to compile and +run under MS Windows 95 and NT using the native Win32 API. It was +written by Geoff Voelker, and has long since been incorporated into +the mainline GNU Emacs distribution. +@end itemize -@email{ilya@@math.ohio-state.edu, Ilya Zakharevich} writes: +@item +Win-Emacs -@quotation -There is a cyrillic mode in the file @file{mysetup.zip} in -@iftex -@* -@end iftex -@uref{ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs/}. This is a -modification to @email{ava@@math.jhu.ed, Valery Alexeev's} @file{russian.el} -which can be obtained from -@end quotation +@itemize @minus -@uref{http://www.math.uga.edu/~valery/russian.el}. +@item +Win-Emacs was a port of Lucid Emacs 19.6 to MS Windows using X +compatibility libraries. Win-Emacs was written by Ben Wing. The MS +Windows code never made it back to Lucid Emacs, and its creator (Pearl +Software) has long since gone out of business. +@end itemize -@email{d.barsky@@ee.surrey.ac.uk, Dima Barsky} writes: +@item +GNU Emacs for DOS -@quotation -There is another cyrillic mode for both GNU Emacs and XEmacs by -@email{manin@@camelot.mssm.edu, Dmitrii -(Mitya) Manin} at -@iftex +@itemize @minus + +@item +GNU Emacs features support for MS-DOS and DJGPP (D.J. Delorie's DOS +port of GCC). Such an Emacs is heavily underfeatured, because it does +not support long file names, lacks proper subprocesses support, and +is far too big compared with typical DOS editors. +@end itemize + +@item +GNU Emacs compiled with Win32 + +@itemize @minus + +@item +Starting with GNU Emacs 19.30, it has been possible to compile GNU Emacs +under MS Windows using the DJGPP compiler and X libraries. The result +is very similar to GNU Emacs compiled under MS DOS, only it works +somewhat better because it runs in 32-bit mode, makes use of all the +system memory, supports long file names, etc. +@end itemize + +@end itemize + +@node Q1.2.7, Q1.2.8, Q1.2.6, Introduction +@unnumberedsubsec Q1.2.7: How does the port cope with differences in the Windows user interface? + +The XEmacs (and Emacs in general) user interface is pretty different +from what is expected of a typical MS Windows program. How does the MS +Windows port cope with it? -@end iftex -@uref{http://kulichki-lat.rambler.ru/centrolit/manin/cyr.el}. -@c Link above, <URL:http://camelot.mssm.edu/~manin/cyr.el> was dead. -@c Changed to russian host instead -@end quotation +As a general rule, we follow native MS Windows conventions as much as +possible. 21.4 is a fairly complete Windows application, supporting +native printing, system file dialog boxes, tool tips, etc. In cases +where there's a clear UI conflict, we currently use normal Unix XEmacs +behavior by default, but make sure the MS Windows "look and feel" (mark +via shift-arrow, self-inserting deletes region, Alt selects menu items, +etc.) is easily configurable (respectively: using the variable +@code{shifted-motion-keys-select-region} in 21.4 and above [it's in fact +the default in these versions], or the @file{pc-select} package; using +the @file{pending-del} package; and setting the variable +@code{menu-accelerator-enabled} to @code{menu-force} in 21.4 and above). +In fact, if you use the sample @file{init.el} file as your init file, +you will get all these behaviors automatically turned on. -@email{rebecca.ore@@op.net, Rebecca Ore} writes: +In future versions, some of these features might be turned on by +default in the MS Windows environment. -@quotation -The fullest resource I found on Russian language use (in and out of -XEmacs) is @uref{http://www.ibiblio.org/sergei/Software/Software.html} -@end quotation +@node Q1.2.8, Q1.2.9, Q1.2.7, Introduction +@unnumberedsubsec Q1.2.8: Is there a port of XEmacs to the Macintosh? -@node Q1.3.8, Q1.3.9, Q1.3.7, Introduction -@unnumberedsubsec Q1.3.8: Does XEmacs support Unicode? +Yes. -Partially, as an external encoding for files, processes, and terminals. -It does not yet support Unicode fonts @ref{Q1.3.9, Does XEmacs support -Unicode Fonts?} +XEmacs 21.5 (perhaps 21.4 also?) works on MacOS X, although it certainly +will not feel very much like a Mac application as it has no Mac-specific +code in it. -To get Unicode support, you need a Mule-enabled XEmacs. Install -Mule-UCS from packages in the usual way. Put +There is also a port of XEmacs 19.14 that works on all recent versions +of MacOS, from 8.1 through MacOS X, by @email{pjarvis@@ispchannel.com, +Pitts Jarvis} (recently deceased). It runs in an equivalent of TTY +mode only (one single Macintosh window, 25 colors), but has a large +number of Mac-specific additions. It's available at +@uref{http://homepage.mac.com/pjarvis/xemacs.html}. -@example -(require 'un-define) -(set-coding-priority-list '(utf-8)) -(set-coding-category-system 'utf-8 'utf-8) -@end example +@node Q1.2.9, Q1.2.10, Q1.2.8, Introduction +@unnumberedsubsec Q1.2.9: Is there a port of XEmacs to MS-DOS? -in your init file to enable the UTF-8 coding system. You may wish to -view the documentation of @code{set-coding-priority-list} if you find -that files that are not UTF-8 are being mis-recognized as UTF-8. +No. We have never supported running on MS-DOS or Windows 3.1, and in +fact have long since deleted all MS-DOS-related code. We're not +particularly interested in patches for these platforms, as they would +introduce huge amounts of code clutter due to the woefully +underfeatured nature of these systems. (See GNU Emacs for a port to +MS-DOS.) -Install standard national fonts (not Unicode fonts) for all -character sets you use. See @ref{Q1.3.9}. +@node Q1.2.10, Q1.2.11, Q1.2.9, Introduction +@unnumberedsubsec Q1.2.10: Is there a port of XEmacs to OS/2? -Mule-UCS also supports 16-bit forms of Unicode (UTF-16). It does not -support 31-bit forms of Unicode (UTF-32 or UCS-4). +No, but Alexander Nikolaev <avn_1251@@mail.ru> was at one point +working on it. -@node Q1.3.9, Q1.4.1, Q1.3.8, Introduction -@unnumberedsubsec Q1.3.9: How does XEmacs display Unicode? +@node Q1.2.11, Q1.2.12, Q1.2.10, Introduction +@unnumberedsubsec Q1.2.11: Is there a port of XEmacs to NextStep? -Mule doesn't have a Unicode charset internally, so there's nothing to -bind a Unicode registry to. It would not be straightforward to create, -either, because Unicode is not ISO 2022-compatible. You'd have to -translate it to multiple 96x96 pages. +Carl Edman, apparently no longer at @email{cedman@@princeton.edu}, did +the port of GNU Emacs to NeXTstep and expressed interest in doing the +XEmacs port, but never went any farther. -This means that Mule-UCS uses ordinary national fonts for display. This -is not really a problem, except for those languages that use the Unified -Han characters. The problem here is that Mule-UCS maps from Unicode -code points to national character sets in a deterministic way. By -default, this means that Japanese fonts are tried first, then Chinese, -then Korean. To change the priority ordering, use the command -`un-define-change-charset-order'. +@node Q1.2.12, Q1.3.1, Q1.2.11, Introduction +@unnumberedsubsec Q1.2.12: Is there a port of XEmacs to VMS? -It also means you can't use Unicode fonts directly, at least not without -extreme hackery. You can run -nw with (set-terminal-coding-system -'utf-8) if you really want a Unicode font for some reason. +VMS has never been supported by XEmacs. In fact, all the old VMS code +inherited from GNU Emacs has been removed. Sorry, all you VMS fans +out there. -Real Unicode support will be introduced in XEmacs 22.0. +@unnumberedsec 1.3: Getting Started -@node Q1.4.1, Q1.4.2, Q1.3.9, Introduction -@unnumberedsec 1.4: Getting Started, Backing up & Recovery -@unnumberedsubsec Q1.4.1: What is an @file{init.el} or @file{.emacs} and is there a sample one? +@node Q1.3.1, Q1.3.2, Q1.2.12, Introduction +@unnumberedsubsec Q1.3.1: What is an @file{init.el} or @file{.emacs} and is there a sample one? The @file{init.el} or @file{.emacs} file is used to customize XEmacs to your tastes. Starting in 21.4, the preferred location for the init file @@ -1250,18 +1406,32 @@ determine the location of the @file{etc/} directory type the command @kbd{C-h v data-directory @key{RET}}. -@node Q1.4.2, Q1.4.3, Q1.4.1, Introduction -@unnumberedsubsec Q1.4.2: Can I use the same @file{init.el}/@file{.emacs} with the other Emacs? +@node Q1.3.2, Q1.3.3, Q1.3.1, Introduction +@unnumberedsubsec Q1.3.2: Where do I put my @file{init.el} file? + +@file{init.el} is the name of the init file starting with 21.4, and is +located in the subdirectory @file{.xemacs/} of your home directory. In +prior versions, the init file is called @file{.emacs} and is located in +your home directory. + +Your home directory under Windows is determined by the @samp{HOME} +environment variable. If this is not set, it defaults to @samp{C:\}. +To set this variable, modify @file{AUTOEXEC.BAT} under Windows 95/98, or +select @samp{Control Panel->System->Advanced->Environment Variables...} +under Windows NT/2000. + +@node Q1.3.3, Q1.3.4, Q1.3.2, Introduction +@unnumberedsubsec Q1.3.3: Can I use the same @file{init.el} with the other Emacs? -Yes. The sample @file{init.el}/@file{.emacs} included in the XEmacs +Yes. The sample @file{init.el} included in the XEmacs distribution will show you how to handle different versions and flavors of Emacs. -@node Q1.4.3, Q1.4.4, Q1.4.2, Introduction -@unnumberedsubsec Q1.4.3: Any good tutorials around? +@node Q1.3.4, Q1.3.5, Q1.3.3, Introduction +@unnumberedsubsec Q1.3.4: Any good XEmacs tutorials around? There's the XEmacs tutorial available from the Help Menu under -@samp{Basics->Tutorials}, or by typing @kbd{C-h t}. To check whether +@samp{Help->Tutorials}, or by typing @kbd{C-h t}. To check whether it's available in a non-english language, type @kbd{C-u C-h t TAB}, type the first letters of your preferred language, then type @key{RET}. @@ -1278,8 +1448,8 @@ @comment @end iftex @comment @uref{http://petaxp.rug.ac.be/~erik/xemacs/}. -@node Q1.4.4, Q1.4.5, Q1.4.3, Introduction -@unnumberedsubsec Q1.4.4: May I see an example of a useful XEmacs Lisp function? +@node Q1.3.5, Q1.3.6, Q1.3.4, Introduction +@unnumberedsubsec Q1.3.5: May I see an example of a useful XEmacs Lisp function? The following function does a little bit of everything useful. It does something with the prefix argument, it examines the text around the @@ -1313,8 +1483,8 @@ @code{p} converts the prefix argument to a number, and @code{interactive} allows you to execute the command with @kbd{M-x}. -@node Q1.4.5, Q1.4.6, Q1.4.4, Introduction -@unnumberedsubsec Q1.4.5: And how do I bind it to a key? +@node Q1.3.6, Q1.3.7, Q1.3.5, Introduction +@unnumberedsubsec Q1.3.6: And how do I bind it to a key? To bind to a key do: @@ -1324,8 +1494,8 @@ Or interactively, @kbd{M-x global-set-key} and follow the prompts. -@node Q1.4.6, , Q1.4.5, Introduction -@unnumberedsubsec Q1.4.6: What's the difference between a macro and a function? +@node Q1.3.7, Q1.3.8, Q1.3.6, Introduction +@unnumberedsubsec Q1.3.7: What's the difference between a macro and a function? Quoting from the Lisp Reference (a.k.a @dfn{Lispref}) Manual: @@ -1344,4479 +1514,4899 @@ another matter, entirely. A keyboard macro is a key bound to several other keys. Refer to manual for details. -@node Installation, Customization, Introduction, Top -@unnumbered 2 Installation and Trouble Shooting - -This is part 2 of the XEmacs Frequently Asked Questions list. This -section is devoted to Installation, Maintenance and Trouble Shooting. +@node Q1.3.8, Q1.4.1, Q1.3.7, Introduction +@unnumberedsubsec Q1.3.8: What is @code{Custom}? -@menu -Installation: -* Q2.0.1:: Running XEmacs without installing. -* Q2.0.2:: XEmacs is too big. -* Q2.0.3:: Compiling XEmacs with Netaudio. -* Q2.0.4:: Problems with Linux and ncurses. -* Q2.0.5:: Do I need X11 to run XEmacs? -* Q2.0.6:: I'm having strange crashes. What do I do? -* Q2.0.7:: Libraries in non-standard locations. -* Q2.0.8:: can't resolve symbol _h_errno -* Q2.0.9:: Where do I find external libraries? -* Q2.0.10:: After I run configure I find a coredump, is something wrong? -* Q2.0.11:: XEmacs can't resolve host names. -* Q2.0.12:: Why can't I strip XEmacs? -* Q2.0.13:: I don't need no steenkin' packages. Do I? -* Q2.0.14:: I don't want to install a million .els one at a time! -* Q2.0.15:: EFS fails with "500 AUTH not understood" (NEW) -* Q2.0.16:: Cygwin XEmacs won't start: cygXpm-noX4.dll was not found (NEW) - -Trouble Shooting: -* Q2.1.1:: XEmacs just crashed on me! -* Q2.1.2:: Cryptic Minibuffer messages. -* Q2.1.3:: Translation Table Syntax messages at Startup. -* Q2.1.4:: Startup warnings about deducing proper fonts? -* Q2.1.5:: XEmacs cannot connect to my X Terminal. -* Q2.1.6:: XEmacs just locked up my Linux X server. -* Q2.1.7:: HP Alt key as Meta. -* Q2.1.8:: got (wrong-type-argument color-instance-p nil)! -* Q2.1.9:: XEmacs causes my OpenWindows 3.0 server to crash. -* Q2.1.10:: Warnings from incorrect key modifiers. -* Q2.1.11:: Can't instantiate image error... in toolbar -* Q2.1.12:: Regular Expression Problems on DEC OSF1. -* Q2.1.13:: HP/UX 10.10 and @code{create_process} failure -* Q2.1.14:: @kbd{C-g} doesn't work for me. Is it broken? -* Q2.1.15:: How to debug an XEmacs problem with a debugger. -* Q2.1.16:: XEmacs crashes in @code{strcat} on HP/UX 10. -* Q2.1.17:: @samp{Marker does not point anywhere}. -* Q2.1.18:: XEmacs is outputting lots of X errors. -* Q2.1.19:: XEmacs does not follow the local timezone. -* Q2.1.20:: @samp{Symbol's function definition is void: hkey-help-show.} -* Q2.1.21:: [This question intentionally left blank] -* Q2.1.22:: XEmacs seems to take a really long time to do some things. -* Q2.1.23:: Movemail on Linux does not work for XEmacs 19.15 and later. -* Q2.1.24:: XEmacs won't start without network. -* Q2.1.25:: After upgrading, XEmacs won't do `foo' any more! -@end menu +@code{Custom} is a system for customizing XEmacs options. -@node Q2.0.1, Q2.0.2, Installation, Installation -@unnumberedsec 2.0: Installation -@unnumberedsubsec Q2.0.1: Running XEmacs without installing +You can access @code{Advanced (Customize)} from the @code{Options} menu +or invoking one of customize commands by typing eg. +@kbd{M-x customize}, @kbd{M-x customize-face}, +@kbd{M-x customize-variable} or @kbd{M-x customize-apropos}. -How can I just try XEmacs without installing it? +There is also new @samp{browser} mode for Customize. +Try it out with @kbd{M-x customize-browse} -XEmacs will run in place without requiring installation and copying of -the Lisp directories, and without having to specify a special build-time -flag. It's the copying of the Lisp directories that requires so much -space. XEmacs is largely written in Lisp. +@unnumberedsec 1.4: Getting Help -A good method is to make a shell alias for xemacs: +@node Q1.4.1, Q1.4.2, Q1.3.8, Introduction +@unnumberedsubsec Q1.4.1: Where can I get help? -@example -alias xemacs=/i/xemacs-20.2/src/xemacs -@end example +Probably the easiest way, if everything is installed, is to use Info, by +pressing @kbd{C-h i}, or looking for an Info item on the +Help Menu. @kbd{M-x apropos} can be used to look for particular commands. -(You will obviously use whatever directory you downloaded the source -tree to instead of @file{/i/xemacs-20.2}). +For items not found in the manual, try reading this FAQ +and reading the Usenet group comp.emacs.xemacs. -This will let you run XEmacs without massive copying. +If you choose to post to a newsgroup, @strong{please use +comp.emacs.xemacs}. Please do not post XEmacs related questions to +gnu.emacs.help. -@node Q2.0.2, Q2.0.3, Q2.0.1, Installation -@unnumberedsubsec Q2.0.2: XEmacs is too big +If you cannot post or read Usenet news, there is a corresponding mailing +list @email{xemacs-news@@xemacs.org} which is available. It can be +subscribed to via the Mailman Web interface or by sending mail to to +@email{xemacs-news-request@@xemacs.org} with @samp{subscribe} in the +body of the message. See also +@uref{http://www.xemacs.org/Lists/#xemacs-news}. To cancel a +subscription, you may use the @email{xemacs-news-request@@xemacs.org} +address or the Web interface. Send a message with a subject of +@samp{unsubscribe} to be removed. -The space required by the installation directories can be -reduced dramatically if desired. Gzip all the .el files. Remove all -the packages you'll never want to use. Remove the TexInfo manuals. -Remove the Info (and use just hardcopy versions of the manual). Remove -most of the stuff in etc. Remove or gzip all the source code. Gzip or -remove the C source code. Configure it so that copies are not made of -the support lisp. +@node Q1.4.2, Q1.4.3, Q1.4.1, Introduction +@unnumberedsubsec Q1.4.2: Which mailing lists are there? -These are all Emacs Lisp source code and bytecompiled object code. You -may safely gzip everything named *.el here. You may remove any package -you don't use. @emph{Nothing bad will happen if you delete a package -that you do not use}. You must be sure you do not use it though, so be -conservative at first. +For complete, up-to-date info on the lists and how to subscribe, see +@uref{http://www.xemacs.org/Lists/}. -Any package with the possible exceptions of xemacs-base, and EFS are -candidates for removal. Ask yourself, @emph{Do I ever want to use this -package?} If the answer is no, then it is a candidate for removal. +@table @samp -First, gzip all the .el files. Then go about package by package and -start gzipping the .elc files. Then run XEmacs and do whatever it is -you normally do. If nothing bad happens, then remove the package. You -can remove a package via the PUI interface -(@code{M-x pui-list-packages}, then press @kbd{d} to mark the packages -you wish to delete, and then @kbd{x} to delete them. +@item comp.emacs.xemacs +is a Usenet newsgroup +for XEmacs users to discuss problems and issues that arise +for them. It's not generally an appropriate place to ask +about apparent bugs (use @samp{xemacs-beta}), or future plans +(use @samp{xemacs-design}). + +@item xemacs-announce +is a read-only, low +volume list for announcements concerning the XEmacs project +and new releases of the XEmacs software. + +@item xemacs-beta +is an open list for bug reports about beta versions of XEmacs. This +includes the bug reports themselves, by both users and developers, as +well as queries, follow-ups, and discussions further determining their +nature and status. This is the primary channel for this kind of +discussion; related code changes will usually not be applied until +they have been discussed here. When such discussions touch on +significant changes to the code (in particular, structural changes), +or on changes to API's or external functionality, they should be moved +to @samp{xemacs-design}. Requests and proposals for non-bug-related +changes do not belong on @samp{xemacs-beta}, and should be sent to +@samp{xemacs-design} instead. + +@item xemacs-beta-ja +is an open list for bug +reports and design discussion related to Mule features, +including Japanese handling, in beta versions of XEmacs. +Japanese is the preferred language of discussion. For most +timely presentation to reviewers, please consider sending +appropriate discussion to @samp{xemacs-mule} or +@samp{xemacs-design} in English when convenient for +the participants in discussion. When possible, bug reports +not related to Mule (including Japanese) should be reported on +@samp{xemacs-beta} in English. + +@item xemacs-buildreports +is an open list for +submission of build-reports on beta versions of XEmacs. For +information on what the build-reports should contain, please +see the `etc/BETA' file which is included in each beta +distribution. -Another method is to do @code{M-x package-get-delete-package}. +@item xemacs-cvs +is a read-only list for notices +and information on what has been committed to the XEmacs CVS +trees, by whom, and for what. + +@item xemacs-design +is an open list for +discussing the design of XEmacs. This includes discussion +about planned and ongoing changes to functionality and API +changes and additions as well as requests for them. This is +the primary channel for this kind of discussion; related code +changes will usually not be applied until they have been +discussed here. This does not include bug reports, which go +to @samp{xemacs-beta}. + +@item xemacs-mule +is an open mailing list for +discussion of International extensions to XEmacs including +Mule, XIM, I18n issues, etc, and is not confined to +developmental issues. This list is not restricted to +English, postings in all languages are welcome. + +@item xemacs-news +is an open list for discussion +and bug reporting for XEmacs. This mailing list is +bi-directionally gatewayed with the USENET newsgroup +comp.emacs.xemacs. + +@item xemacs-nt +is a developers-only mailing +list and is intended for people who wish to work actively on +the porting of XEmacs to Microsoft Windows NT and Microsoft +Windows '95. + +@item xemacs-patches +is an open, moderated +list for submission of patches to the XEmacs distribution +and its packages. Anyone may subscribe or submit to +xemacs-patches, but all submissions are reviewed by the list +moderator before they are distributed to the +list. Discussion is not appropriate on xemacs-patches. + +@item xemacs-users-ja +is an open list for +discussion and bug reporting for XEmacs. Japanese is the +preferred language of discussion. It is not gated to +comp.emacs.xemacs or the @samp{xemacs} list. For +fastest response, bugs not specifically related to Japanese +or Mule features should be reported on +@samp{xemacs-beta} (in English). + +@item xemacs-users-ru +is an open list for +discussion and bug reporting for XEmacs. Russian is the +preferred language of discussion. It is not gated to +comp.emacs.xemacs or the @samp{xemacs} list. For +fastest response, bugs not specifically related to Russian +or Mule features should be reported on +@samp{xemacs-beta} (in English). +@end table -@node Q2.0.3, Q2.0.4, Q2.0.2, Installation -@unnumberedsubsec Q2.0.3: Compiling XEmacs with Netaudio. +@node Q1.4.3, Q1.4.4, Q1.4.2, Introduction +@unnumberedsubsec Q1.4.3: Where are the mailing lists archived? -What is the best way to compile XEmacs with the netaudio system, since I -have got the netaudio system compiled but installed at a weird place, I -am not root. Also in the READMEs it does not say anything about -compiling with the audioserver? - -You should only need to add some stuff to the configure command line. -To tell it to compile in netaudio support: @samp{--with-sound=both}, or -@samp{--with-sound=nas} if you don't want native sound support for some -reason.) To tell it where to find the netaudio includes and libraries: +The archives can be found at @uref{http://list-archive.xemacs.org} -@example ---site-libraries=WHATEVER ---site-includes=WHATEVER -@end example +@node Q1.4.4, Q1.4.5, Q1.4.3, Introduction +@unnumberedsubsec Q1.4.4: How can I get two instances of info? -Then (fingers crossed) it should compile and it will use netaudio if you -have a server running corresponding to the X server. The netaudio server -has to be there when XEmacs starts. If the netaudio server goes away and -another is run, XEmacs should cope (fingers crossed, error handling in -netaudio isn't perfect). - -BTW, netaudio has been renamed as it has a name clash with something -else, so if you see references to NAS or Network Audio System, it's the -same thing. It also might be found at -@uref{ftp://ftp.x.org/contrib/audio/nas/}. +Before 21.4, you can't. The @code{info} package does not provide for +multiple info buffers. In 21.4, this should be fixed. #### how? -@node Q2.0.4, Q2.0.5, Q2.0.3, Installation -@unnumberedsubsec Q2.0.4: Problems with Linux and ncurses. +@node Q1.4.5, Q1.5.1, Q1.4.4, Introduction +@unnumberedsubsec Q1.4.5: How do I add new Info directories? -On Linux 1.3.98 with termcap 2.0.8 and the ncurses that came with libc -5.2.18, XEmacs 20.0b20 is unable to open a tty device: +You use something like: -@example -src/xemacs -nw -q -Initialization error: -@iftex -@* -@end iftex -Terminal type `xterm' undefined (or can't access database?) -@end example +@lisp +(setq Info-directory-list (cons + (expand-file-name "~/info") + Info-default-directory-list)) +@end lisp -@email{ben@@xemacs.org, Ben Wing} writes: +@email{davidm@@prism.kla.com, David Masterson} writes: @quotation -Your ncurses configuration is messed up. Your /usr/lib/terminfo is a -bad pointer, perhaps to a CD-ROM that is not inserted. +Emacs Info and XEmacs Info do many things differently. If you're trying to +support a number of versions of Emacs, here are some notes to remember: + +@enumerate +@item +Emacs Info scans @code{Info-directory-list} from right-to-left while +XEmacs Info reads it from left-to-right, so append to the @emph{correct} +end of the list. + +@item +Use @code{Info-default-directory-list} to initialize +@code{Info-directory-list} @emph{if} it is available at startup, but not +all Emacsen define it. + +@item +Emacs Info looks for a standard @file{dir} file in each of the +directories scanned from #1 and magically concatenates them together. + +@item +XEmacs Info looks for a @file{localdir} file (which consists of just the +menu entries from a @file{dir} file) in each of the directories scanned +from #1 (except the first), does a simple concatenation of them, and +magically attaches the resulting list to the end of the menu in the +@file{dir} file in the first directory. +@end enumerate + +Another alternative is to convert the documentation to HTML with +texi2html and read it from a web browser like Lynx or W3. @end quotation -@node Q2.0.5, Q2.0.6, Q2.0.4, Installation -@unnumberedsubsec Q2.0.5: Do I need X11 to run XEmacs? +@unnumberedsec 1.5: Contributing to XEmacs -No. The name @dfn{XEmacs} is unfortunate in the sense that it is -@strong{not} an X Window System-only version of Emacs. XEmacs has -full color support on a color-capable character terminal. +@node Q1.5.1, Q1.5.2, Q1.4.5, Introduction +@unnumberedsubsec Q1.5.1: How do I submit changes to the FAQ? + +The FAQ is actively maintained and modified regularly. All links should +be up to date. Unfortunately, some of the information is out of date -- +a situation which the FAQ maintainer is working on. All submissions are +welcome, please e-mail submissions to @email{faq@@xemacs.org, XEmacs FAQ +maintainers}. + +Please make sure that @samp{XEmacs FAQ} appears on the Subject: line. +If you think you have a better way of answering a question, or think a +question should be included, we'd like to hear about it. Questions and +answers included into the FAQ will be edited for spelling and grammar +and will be attributed. Answers appearing without attribution are +either from versions of the FAQ dated before May 1996 or are from +previous FAQ maintainers. Answers quoted from Usenet news articles will +always be attributed, regardless of the author. + +@node Q1.5.2, Q1.5.3, Q1.5.1, Introduction +@unnumberedsubsec Q1.5.2: How do I become a beta tester? + +Send an email message to @email{xemacs-beta-request@@xemacs.org} with +the line @samp{subscribe} in the body of the message. + +Be prepared to get your hands dirty, as beta testers are expected to +identify problems as best they can. + +@node Q1.5.3, Q1.5.4, Q1.5.2, Introduction +@unnumberedsubsec Q1.5.3: How do I contribute to XEmacs itself? + +It depends on the knowledge and time you possess. If you are able, by +all means become a beta tester (@pxref{Q1.5.2}). If you are a +programmer, try to build XEmacs and see if you can improve it. + +Otherwise, you can still help by using XEmacs as your everyday editor +(for pre-built binary versions, @pxref{Q1.1.2}) and reporting bugs you +find to the mailing list. + +Another area where we need help is the documentation: We need good +documentation for building XEmacs and for using it. This FAQ is a +small step in that direction. + +Ben Wing @email{ben@@xemacs.org} writes: + +@quotation +BTW if you have a wish list of things that you want added, you have to +speak up about it! More specifically, you can do the following if you +want a feature added (in increasing order of usefulness): + +@itemize @bullet +@item +Make a posting about a feature you want added. + +@item +Become a beta tester and make more postings about those same features. + +@item +Convince us that you're going to use the features in some cool and +useful way. + +@item +Come up with a clear and well-thought-out API concerning the features. + +@item +Write the code to implement a feature and send us a patch. +@end itemize + +(not that we're necessarily requiring you to write the code, but we can +always hope :) +@end quotation -@node Q2.0.6, Q2.0.7, Q2.0.5, Installation -@unnumberedsubsec Q2.0.6: I'm having strange crashes. What do I do? +@node Q1.5.4, Q1.5.5, Q1.5.3, Introduction +@unnumberedsubsec Q1.5.4: How do I get started developing XEmacs? -There have been a variety of reports of crashes due to compilers with -buggy optimizers. Please see the @file{PROBLEMS} file that comes with -XEmacs to read what it says about your platform. +First, get yourself set up under CVS so that you can access the CVS +repositories containing the XEmacs sources and the XEmacs packages. -If you compiled XEmacs using @samp{--use-union-type} (or the option -@samp{USE_UNION_TYPE} in @file{config.inc} under Windows), try -recompiling again without it. The union type has been known to trigger -compiler errors in a number of cases. +Next, set up your layout. This is important, as a good layout will +facilitate getting things done efficiently, while a bad layout will could +lead to disaster, as you can't figure out which code is the most recent, +which can be thrown away, etc. We suggest the following layout: (feel free +to make changes) -@node Q2.0.7, Q2.0.8, Q2.0.6, Installation -@unnumberedsubsec Q2.0.7: Libraries in non-standard locations +@itemize @bullet +@item +Everything goes under @file{/src/xemacs} (use a different directory if +you want). From now, instead of saying @file{/src/xemacs}, we use +@file{<xsrc-top>}, to make it easier in case someone picked a +different directory. -I have x-faces, jpeg, xpm etc. all in different places. I've tried -space-separated, comma-separated, several --site-libraries, all to no -avail. +@item +Package source is in @file{<xsrc-top>/package-src}. -@example ---site-libraries='/path/one /path/two /path/etc' -@end example +@item +Installed packages go under @file{<xsrc-top>/xemacs-packages}, and +@file{<xsrc-top>/mule-packages}. -@node Q2.0.8, Q2.0.9, Q2.0.7, Installation -@unnumberedsubsec Q2.0.8: can't resolve symbol _h_errno +@item +A "workspace" is a complete copy of the sources, in which you do work of +a particular kind. Workspaces can be differentiated by which branch of +the source tree they extend off of -- usually either the stable or +experimental, unless other branches have been created (for example, Ben +created a branch for his Mule work because (1) the project was long-term +and involved an enormous number of changes, (2) people wanted to be able +to look at what his work in progress, and (3) he wanted to be able to +check things in and in general use source-code control, since it was a +long-term project). Workspaces are also differentiated in what their +purpose is -- general working workspace, workspace for particular +projects, workspace keeping the latest copy of the code in one of the +branches without mods, etc. -You are using the Linux/ELF distribution of XEmacs 19.14, and your ELF -libraries are out of date. You have the following options: +@item +Various workspaces are subdirectories under @file{<xsrc-top>}, e.g.: -@enumerate +@itemize @bullet @item -Upgrade your libc to at least 5.2.16 (better is 5.2.18, 5.3.12, or -5.4.10). +@file{<xsrc-top>/working} (the workspace you're actively working on, +periodically synched up with the latest trunk) @item -Patch the XEmacs binary by replacing all occurrences of -@samp{_h_errno^@@} with -@iftex -@* -@end iftex -@samp{h_errno^@@^@@}. Any version of Emacs will -suffice. If you don't understand how to do this, don't do it. +@file{<xsrc-top>/stable} (for making changes to the stable version of +XEmacs, which sits on a branch) @item -Rebuild XEmacs yourself---any working ELF version of libc should be -O.K. -@end enumerate +@file{<xsrc-top>/unsigned-removal} (a workspace for a specific, difficult +task that's going to affect lots of source and take a long time, and +so best done in its own workspace without the interference of other +work you're doing. Also, you can commit just this one large change, +separate from all the other changes). -@email{hniksic@@xemacs.org, Hrvoje Niksic} writes: +@item +@file{<xsrc-top>/latest} (a copy of the latest sources on the trunk, +i.e. the experimental version of XEmacs, with no patches in it; +either update it periodically, by hand, or set up a cron job to do it +automatically). Set it up so it can be built, and build it so you +have a working XEmacs. (Building it might also go into the cron job.) -@quotation -Why not use a Perl one-liner for No. 2? +This workspace serves a number of purposes: +@enumerate +@item +You always have a recent version of XEmacs you can compare +against when something you're working on breaks. It's true +that you can do this with cvs diff, but when you need to do +some serious investigation, this method just fails. +@item +You (almost) always have a working, up-to-date executable that +can be used when your executable is crashing and you need to +keep developing it, or when you need an `xemacs' to build +packages, etc. +@item +When creating new workspaces, you can just copy the `latest' +workspace using GNU @code{cp -a}. You have all the .elc's built, +everything else probably configured, any spare files in place +(e.g. some annoying xpm.dll under Windows, etc.). +@end enumerate -@example -perl -pi -e 's/_h_errno\0/h_errno\0\0/g' \ -/usr/local/bin/xemacs-19.14 -@end example +@item +@file{<xsrc-top>/latest-stable/} (equivalent to @file{<xsrc-top>/latest/}, but +for the Stable branch of XEmacs, rather than the Experimental branch +of XEmacs). This may or may not be necessary depending on how much +development you do of the stable branch. +@end itemize -NB: You @emph{must} patch @file{/usr/local/bin/xemacs-19.14}, and not -@file{xemacs} because @file{xemacs} is a link to @file{xemacs-19.14}; -the Perl @samp{-i} option will cause unwanted side-effects if applied to -a symbolic link. -@end quotation +@item +@file{<xsrc-top>/xemacsweb} is a workspace for working on the XEmacs +web site. -@email{steve@@xemacs.org, SL Baur} writes: +@item +@file{<xsrc-top>/in-patches} for patches received from email and saved +to files. -@quotation -If you build against a recent libc-5.4 (late enough to have caused -problems earlier in the beta cycle) and then run with an earlier version -of libc, you get a +@item +@file{<xsrc-top>/out-patches} for locally-generated patches to be sent +to @email{xemacs-patches@@xemacs.org}. Less useful now that the +patcher util has been developed. + +@item +@file{<xsrc-top>/build}, for build trees when compiling and testing XEmacs with +various configuration options turned off and on. The scripts in +xemacs-builds/ben (see below) can be used to automate building XEmacs +workspaces with many different configuration options and automatically +filtering out the normal output so that you see only the abnormal +output. + +@item +@file{<xsrc-top>/xemacs-builds}, for the xemacs-builds module, which you need +to check out separately in CVS. This contains scripts used for building +XEmacs, automating and simplifying using CVS, etc. Under various +people's directories are their own build and other scripts. The +currently most-maintained scripts are under ben/, where there are easily +configurable scripts that can be used to easily build any workspace +(esp. if you've more or less followed the layout presented above) +unattended, with one or more configuration states (there's a +pre-determined list of the most useful, but it's easy to change). The +output is filtered and split up in various ways so that you can identify +which output came from where, and you can see the output either full or +with all "normal" output except occasional status messages filtered so +that you only see the abnormal ones. +@end itemize -@example -$ xemacs -xemacs: can't resolve symbol '__malloc_hook' -zsh: 7942 segmentation fault (core dumped) xemacs -@end example +@node Q1.5.5, Q1.6.1, Q1.5.4, Introduction +@unnumberedsubsec Q1.5.5: What's the basic layout of the code? -(Example binary compiled against libc-5.4.23 and run with libc-5.4.16). +The file @file{configure} is a shell script to acclimate XEmacs to the +oddities of your processor and operating system. It will create a +file named @file{Makefile} (a script for the @file{make} program), which helps +automate the process of building and installing emacs. See INSTALL +for more detailed information. + +The file @file{configure.in} is the input used by the autoconf program to +construct the @file{configure} script. Since XEmacs has configuration +requirements that autoconf can't meet, @file{configure.in} uses an unholy +marriage of custom-baked configuration code and autoconf macros; it +may be wise to avoid rebuilding @file{configure} from @file{configure.in} when +possible. -The solution is to upgrade to at least libc-5.4.23. Sigh. Drat. -@end quotation +The file @file{Makefile.in} is a template used by @file{configure} to create +@file{Makefile}. -@node Q2.0.9, Q2.0.10, Q2.0.8, Installation -@unnumberedsubsec Q2.0.9: Where do I find external libraries? +There are several subdirectories: -All external libraries used by XEmacs can be found at the XEmacs FTP -site -@iftex -@* -@end iftex -@uref{ftp://ftp.xemacs.org/pub/xemacs/aux/}. -[These tarballs and this FAQ are wa-a-ay out of date. Sorry, I'm not -currently network-capable, and I will probably forgot to update this -before submitting the patch. -- Ed.] - -@c Changed June Link above, <URL:ftp://ftp.xemacs.org/pub/aux/> was dead. -@c This list is a pain in the you-know-what to keep in synch with the -@c world. -The canonical locations (at the time of this writing) are as follows: +@enumerate +@item +@file{src} holds the C code for XEmacs (the XEmacs Lisp interpreter and its +primitives, the redisplay code, and some basic editing functions). +@item +@file{lisp} holds the XEmacs Lisp code for XEmacs (most everything else). +@item +@file{lib-src} holds the source code for some utility programs for use by +or with XEmacs, like movemail and etags. +@item +@file{etc} holds miscellaneous architecture-independent data files +XEmacs uses, like the tutorial text. The contents of the @file{lisp}, +@file{info} and @file{man} subdirectories are architecture-independent too. +@item +@file{lwlib} holds the C code for the X toolkit objects used by XEmacs. +@item +@file{info} holds the Info documentation tree for XEmacs. +@item +@file{man} holds the source code for the XEmacs online documentation. +@item +@file{nt} holds files used compiling XEmacs under Microsoft Windows. +@end enumerate -@table @asis -@item JPEG -@uref{ftp://ftp.uu.net/graphics/jpeg/}. Version 6a is current. -@c Check from host with legal IP address -@item XPM -@uref{ftp://ftp.x.org/contrib/libraries/}. Version 3.4j is current. -Older versions of this package are known to cause XEmacs crashes. - -@item TIFF -@uref{ftp://ftp.sgi.com/graphics/tiff/}. v3.4 is current. The latest -beta is v3.4b035. There is a HOWTO here. - -@item PNG -@uref{ftp://ftp.uu.net/graphics/png/}. 0.89c is current. XEmacs -requires a fairly recent version to avoid using temporary files. -@c Check from host with legal IP address - -@uref{ftp://swrinde.nde.swri.edu/pub/png/src/} - -@item Compface -@uref{ftp://ftp.cs.indiana.edu/pub/faces/compface/}. This library has -been frozen for about 6 years, and is distributed without version -numbers. @emph{It should be compiled with the same options that X11 was -compiled with on your system}. The version of this library at -XEmacs.org includes the @file{xbm2xface.pl} script, written by -@email{stig@@hackvan.com}, which may be useful when generating your own xface. - -@item NAS -@uref{ftp://ftp.x.org/contrib/audio/nas/}. -Version 1.2p5 is current. There is a FAQ here. -@end table +@unnumberedsec 1.6: Politics (XEmacs vs. GNU Emacs) -@node Q2.0.10, Q2.0.11, Q2.0.9, Installation -@unnumberedsubsec Q2.0.10: After I run configure I find a core dump, is something wrong? +@node Q1.6.1, Q1.6.2, Q1.5.5, Introduction +@unnumberedsubsec Q1.6.1: What is GNU Emacs? -Not necessarily. If you have GNU sed 3.0 you should downgrade it to -2.05. From the @file{README} at prep.ai.mit.edu: +GNU Emacs and XEmacs are related open-source text editors. Both +derive from GNU Emacs version 18; the split between the two happened +in 1991 (for comparison, the oldest versions of GNU Emacs date from +1984). For information on GNU Emacs, see +@uref{http://www.gnu.org/software/emacs/emacs.html}. -@quotation -sed 3.0 has been withdrawn from distribution. It has major revisions, -which mostly seem to be improvements; but it turns out to have bugs too -which cause trouble in some common cases. - -Tom Lord won't be able to work fixing the bugs until May. So in the -mean time, we've decided to withdraw sed 3.0 from distribution and make -version 2.05 once again the recommended version. -@end quotation +@node Q1.6.2, Q1.6.3, Q1.6.1, Introduction +@unnumberedsubsec Q1.6.2: How does XEmacs differ from GNU Emacs? -It has also been observed that the vfork test on Solaris will leave a -core dump. +For a detailed description of the differences between GNU Emacs and +XEmacs and a detailed history of XEmacs, check out the +@example +@uref{http://www.xemacs.org/About/XEmacsVsGNUemacs.html, NEWS file} +@end example -@node Q2.0.11, Q2.0.12, Q2.0.10, Installation -@unnumberedsubsec Q2.0.11: XEmacs doesn't resolve hostnames. +@table @strong +@item User-Visible Editing Features +XEmacs in general tries hard to conform to exist user-interface +standards, and to work "out-of-the-box" without the need for obscure +customization changes. GNU Emacs, particularly version 21, has gotten +better about this (in many cases by copying the XEmacs behavior!), but +still has some weirdnesses. For example, the standard method of +selecting text using the Shift key works out-of-the-box in XEmacs. + +XEmacs has a built-in toolbar. Four toolbars can actually be configured +simultaneously: top, bottom, left, and right toolbars. + +XEmacs has vertical and horizontal scrollbars. Unlike in GNU Emacs 19 +(which provides a primitive form of vertical scrollbar), these are true +toolkit scrollbars. A look-alike Motif scrollbar is provided for those +who don't have Motif. (Even for those who do, the look-alike may be +preferable as it is faster.) + +XEmacs has buffer tabs along the top of the frame (although the +position can be changed) that make it very easy to switch buffers. + +The menubar under XEmacs is better-designed, with more thought put into +it. + +XEmacs can ask questions using popup dialog boxes. Any command executed +from a menu will ask yes/no questions with dialog boxes, while commands +executed via the keyboard will use the minibuffer. + +XEmacs under MS Windows provides uses the standard file-dialog box for +opening and saving files. Standard menu-accelerator behavior can easily +be enabled using the Options menu, and integrates well into the existing +keymap. + +XEmacs has (still experimental) support for widgets of various sorts -- +buttons, text boxes, sliders, progress bars, etc. A progress bar is +used in font lock to show the progress. + +Experimental support for drag-and-drop protocols is provided from +XEmacs 21. + +@item General Platform Support +If you're running on a machine with audio hardware, you can specify +sound files for XEmacs to play instead of the default X beep. See the +documentation of the function load-sound-file and the variable +sound-alist. XEmacs also supports the network sound protocols NAS and +EsounD. + +XEmacs 21 supports database protocols with LISP bindings, currently +including Berkeley DB, LDAP, and PostgreSQL (21.2 only). + +XEmacs 20 and 21 support the Canna, Wnn, and SJ3 Japanese input method +servers directly, as well as through the X Input Method (XIM) +protocol. GNU Emacs 20 supports only the XIM protocol. Both Emacsen +support the Quail family of input methods (implemented in LISP) for many +languages. + +XEmacs provides support for ToolTalk on systems that have +it. + +@item Packaged LISP Libraries +Many more packages are provided standard with XEmacs than with GNU Emacs +19 or 20. + +XEmacs 21 supports an integrated package management system which uses +EFS to download, then automatically install prebuilt LISP +libraries. This allows XEmacs users much more straightforward access to +the "latest and greatest" version of any given library. + +We are working on a standard method for enabling, disabling and +otherwise controlling packages, which should make them very easy to use. + +@item LISP Programming +From XEmacs 20 on, characters are a separate type. Characters can be +converted to integers (and many integers can be converted to +characters), but characters are not integers. GNU Emacs 19, XEmacs 19, +Mule 2.3 (an extensive patch to GNU Emacs 18.55 and 19.x), and GNU Emacs +20 (incorporating Mule 3 and later Mule 4) represent them as integers. + +From XEmacs 20 on, the buffer is treated as an array of characters, and +the representation of buffer text is not exposed to LISP. The GNU Emacs +20 functions like buffer-as-multibyte are not supported. + +In XEmacs, events are first-class objects. GNU Emacs 19 represents them +as integers, which obscures the differences between a key gesture and +the ancient ASCII code used to represent a particular overlapping subset +of them. + +In XEmacs, keymaps are first-class opaque objects. GNU Emacs 19 +represents them as complicated combinations of association lists and +vectors. If you use the advertised functional interface to manipulation +of keymaps, the same code will work in XEmacs, GNU Emacs 18, and GNU +Emacs 19; if your code depends on the underlying implementation of +keymaps, it will not. + +XEmacs uses "extents" to represent all non-textual aspects of buffers; +GNU Emacs 19 uses two distinct objects, "text properties" and +"overlays", which divide up the functionality between them. Extents are +a superset of the union of the functionality of the two GNU Emacs data +types. The full GNU Emacs 19 interface to text properties and overlays +is supported in XEmacs (with extents being the underlying +representation). + +Extents can be made to be copied into strings, and then restored, by +kill and yank. Thus, one can specify this behavior on either "extents" +or "text properties", whereas in GNU Emacs 19 text properties always +have this behavior and overlays never do. + +@item Window System Programming Interface +XEmacs uses the MIT "Xt" toolkit instead of raw Xlib calls, which makes +it be a more well-behaved X citizen (and also improves portability). A +result of this is that it is possible to include other Xt "Widgets" in +the XEmacs window. Also, XEmacs understands the standard Xt command-line +arguments. + +XEmacs supports Motif applications, generic Xt (e.g. Athena) +applications, and raw Xlib applications. An XEmacs variant which +supports GTK+ is available (integration as an option in the XEmacs +mainline is planned for XEmacs 22), although code to take advantage of +the support is as yet scarce. + +An XEmacs frame can be placed within an "external client widget" managed +by another application. This allows an application to use an XEmacs +frame as its text pane rather than the standard Text widget that is +provided with Motif or Athena. + +@item Community Participation +Joining the XEmacs development team is simple. Mail to +@email{xemacs-beta@@xemacs.org, XEmacs Developers}, and you're in! (If +you want to be, of course. You're also welcome to just post +development-related questions and bug reports.) The GNU Emacs +development team and internal mailing lists are still by invitation +only. + +The "bleeding edge" of mainline XEmacs development is available by +anonymous CVS as are some subsidiary branches (check out the xemacs-gtk +module for the latest in GUI features!) + +Development and maintenance of Lisp libraries is separated from the core +editor development at a fairly low level. This provides better +modularization and a better division of responsibility between external +library maintainers and the XEmacs core development team. Even for +packages the size of Gnus, XEmacs users normally have access to a +pre-built version within a few weeks of a major release, and minor +updates often within days. + +CVS commit authority is broadly dispersed. Recognized maintainers of +LISP libraries who are willing to maintain XEmacs packaged versions +automatically qualify for CVS accounts for their packages. +@end table -This is the result of a long-standing problem with SunOS and the fact -that stock SunOS systems do not ship with DNS resolver code in libc. +@node Q1.6.3, Q1.6.4, Q1.6.2, Introduction +@unnumberedsubsec Q1.6.3: How much does XEmacs differ? -@email{ckd@@loiosh.kei.com, Christopher Davis} writes: +RMS has asserted at times that XEmacs is merely a "patch" on top of +GNU Emacs (@pxref{Q1.6.4}). In fact, probably not more than 5% of the +code, if that, remains unchanged, and nearly 14 years of work has gone +into XEmacs at this point. (GNU Emacs itself is only than 20 years +old, and thus XEmacs has existed as a separate product for over 2/3 of +the lifespan of GNU Emacs.) As a point of comparison, XEmacs 21.5 has +perhaps 65,000 more lines of C code than GNU Emacs 21.2. + +However, the XEmacs developers strive to keep their code compatible with +GNU Emacs, especially on the Lisp level. Much effort goes into +"synching" the XEmacs Elisp code with recent GNU Emacs releases so as to +benefit from GNU Emacs development work. (In contrast, almost no code +from XEmacs has made it into GNU Emacs, and in fact the GNU Emacs +developers are instructed by RMS not to even look at XEmacs source code! +This stems from self-imposed licensing restrictions on the part of GNU +Emacs -- and almost certainly out of hostility, as well.) + +@node Q1.6.4, Q1.6.5, Q1.6.3, Introduction +@unnumberedsubsec Q1.6.4: Is XEmacs "GNU"? + +RMS insists on the term "GNU XEmacs" and maintains that + +@quotation +XEmacs is GNU software because it's a modified version of a +GNU program. And it is GNU software because the FSF is the copyright +holder for most of it, and therefore the legal responsibility for +protecting its free status falls on us whether we want it or not. This +is why the term "GNU XEmacs" is legitimate. +@end quotation + +In fact, FSF is @emph{not} the copyright holder for most of the code, +as very little unmodified FSF code remains (@pxref{Q1.6.3}). + +Furthermore, RMS's assertion that XEmacs is "GNU" seems rather bizarre +to the XEmacs developers given RMS's hostility and general lack of +interest in cooperation. "GNU" software in general is part of the GNU +Project, is distributed by it on their FTP site, and receives support +(or at least cooperation), as well as implicit endorsement, from it. +The GNU Project, however, has never supported XEmacs and never +distributed XEmacs, and RMS's hostility is the farthest thing possible +from an endorsement. In fact, the GNU Project distributes a number of +non-GNU software projects on the FSF web site, but again XEmacs is not +one of them. + +@node Q1.6.5, Q1.6.6, Q1.6.4, Introduction +@unnumberedsubsec Q1.6.5: What is the correct way to refer to XEmacs and GNU Emacs? + +Unfortunately even the naming of these two applications has become +politicized. Much of this stems from RMS, who has a history of +politicizing similar issues. (Compare the controversy over "Lignux" +and "GNU/Linux".) We would prefer that the terms "XEmacs" and "GNU +Emacs" be used, which are neutral and acceptable to most people. RMS, +however, is not willing to accept these terms. He insists that, if +his product is called "GNU Emacs", then ours must be called "GNU +XEmacs". (For our opinion of this term, @xref{Q1.6.4}.) On the other +hand, if our product is to be called "XEmacs", as we prefer, then his +product must simply be called "Emacs". The intent of this seems +clear: RMS wants to make sure the names reflect his view that his +version is the "real" Emacs and ours is merely a derivative, +second-class product (@pxref{Q1.6.3}). + +The XEmacs developers hope that you will use the neutral terms +"XEmacs" and "GNU Emacs" for these two specific products. "Emacs", on +the other hand, is a generic term for a class of programmable text +editors with a similar look-and-feel, and usually a Lisp-based +extension language. These trace themselves back to early editors such +as EINE, ZWEI, ZMACS and Multics Emacs. @xref{A History of Emacs,,, +internals, XEmacs Internals Manual}. + +We also call upon RMS, in the spirit of furthering cooperation, to +stop politicizing this issue and use the neutral terms "XEmacs" and +"GNU Emacs". We have already acceded to RMS' wishes in this respect, +and we expect him to do the same. (In the past, the XEmacs developers +often used the terms "FSF Emacs" or "FSFmacs" or "RMSmacs" in +reference to GNU Emacs; these terms were apparently modeled after RMS' +own usage of "Gosmacs" and "Gosling Emacs" in reference to Unipress +Emacs, produced by James Gosling. RMS, however, considers such terms +to be insulting, so we refrain from using them as much as possible in +preference to GNU Emacs.) -@quotation -That's correct [The SunOS 4.1.3 precompiled binaries don't do name -lookup]. Since Sun figured that everyone used NIS to do name lookups -(that DNS thing was apparently only a passing fad, right?), the stock -SunOS 4.x systems don't have DNS-based name lookups in libc. - -This is also why Netscape ships two binaries for SunOS 4.1.x. - -The best solution is to compile it yourself; the configure script will -check to see if you've put DNS in the shared libc and will then proceed -to link against the DNS resolver library code. -@end quotation +@node Q1.6.6, Q1.7.1, Q1.6.5, Introduction +@unnumberedsubsec Q1.6.6: Why haven't XEmacs and GNU Emacs merged? -@node Q2.0.12, Q2.0.13, Q2.0.11, Installation -@unnumberedsubsec Q2.0.12: Why can't I strip XEmacs? +There are currently irreconcilable differences in the views about +technical, programming, design, organizational and legal matters +between Richard Stallman (RMS), the author and leader of the GNU Emacs +project, and the XEmacs development team which provide little hope for +a merge to take place in the short-term future. There have been +repeated attempts at merging by all of the major XEmacs developers, +starting from the early days of Lucid Emacs (in 1991), but they have +all failed. RMS has very strong views about how GNU Emacs should be +structured and how his project should be run, and during the repeated +merge efforts has never demonstrated any realistic interest in +sufficiently compromising or ceding control to allow a middle ground +to be found. The basic problem seems to be the very different goals +of RMS and the XEmacs project. The primary goals of the XEmacs +project are technical and organizational -- we want to create the best +editor possible, and to make it as easy as possible for people around +the world to contribute. The primary goals of RMS, on the other hand, +are political, and GNU Emacs, and any potential merge efforts with +XEmacs, are strictly subservient to these goals. In fact, in many +ways RMS sees GNU Emacs as the "poster child" of his aims, the one +program in the GNU project that above all others must set an example +to the world. (This has to do with the fact that GNU Emacs was the +first program in the GNU project, and the only one that he is still +personally involved with on a day-to-day basis.) Given his goals, his +position is completely reasonable -- but unfortunately, makes any +merge impossible. -@email{cognot@@fronsac.ensg.u-nancy.fr, Richard Cognot} writes: +From the XEmacs perspective, the most intractable issues appear to be +legal and organizational, specifically: -@quotation -Because of the way XEmacs (and every other Emacsen, AFAIK) is built. The -link gives you a bare-boned emacs (called temacs). temacs is then run, -preloading some of the lisp files. The result is then dumped into a new -executable, named xemacs, which will contain all of the preloaded lisp -functions and data. +@itemize @bullet +@item +RMS requires "legal papers" to be signed for all contributions of code +to GNU Emacs over 10 lines or so, transferring the copyright and all +legal rights to the code to the Free Software Foundation. XEmacs does +not and has never required this, since it has the practical effect of +discouraging individual and in particular corporate contributions -- +corporations will almost never sign away their legal rights to code +since it makes it impossible to reuse the code in any product that +whose license is not compatible with the GNU General Public License. +Since RMS has shown no inclination to compromise on this issue, a +merge would require that most of the existing XEmacs code would need +to be thrown away and rewritten -- something the XEmacs developers are +understandably reluctant to do. + +@item +A repeated stumbling block in the merge talks has been the issue of +organizational control over the resulting product. RMS has made it +clear that he intends to have final say over design issues in a merged +Emacs. Unfortunately, RMS and the XEmacs developers have repeatedly +clashed over design decisions, and RMS' insistence on getting his way +in such disagreements was the very reason for the split in the first +place. This same issue has come up again and again in merge talks and +we have never been able to come to a satisfactory resolution. To the +extent that RMS is willing to compromise at all, it appears to be of a +purely political rather than technical nature -- "If we support this +feature of yours, we also get to support this other feature of mine." +The XEmacs developers cannot see how such a process would lead to +anything but a mess of incompatible things hodgepodged together. + +@item +Because of the years of separate development, distinct and +incompatible interfaces have developed and merging would be extremely +difficult even with the above non-technical issues resolved. The +problem has been exacerbated by the issue of legal papers -- because +XEmacs code is not "kosher" from RMS' perspective, he discourages +developers from even looking at it out of legal concerns. Although it +is still possible to read the XEmacs documentation and run the +program, the practical effect of this prohibition has been to strongly +discourage code-sharing and cooperative development -- although a +great deal of GNU Emacs code has been incorporated into XEmacs, +practically none has gone the other direction. +@end itemize -Now, during the dump itself, the executable (code+data+symbols) is -written on disk using a special unexec() function. This function is -obviously heavily system dependent. And on some systems, it leads to an -executable which, although valid, cannot be stripped without damage. If -memory serves, this is especially the case for AIX binaries. On other -architectures it might work OK. +If you have a comment to add regarding the merge, it is a good idea to +avoid posting to the newsgroups, because of the very heated flamewars +that often result. Mail your questions to +@email{xemacs-beta@@xemacs.org} and @email{emacs-devel@@gnu.org}. -The Right Way to strip the emacs binary is to strip temacs prior to -dumping xemacs. This will always work, although you can do that only if -you install from sources (as temacs is @file{not} part of the binary -kits). -@end quotation +@unnumberedsec 1.7: External Packages -@email{nat@@nataa.fr.eu.org, Nat Makarevitch} writes: +@node Q1.7.1, Q1.7.2, Q1.6.6, Introduction +@unnumberedsubsec Q1.7.1: What is the package system? -@quotation -Here is the trick: +In order to reduce the size and increase the maintainability of +XEmacs, the majority of the Elisp packages that came with previous +releases have been unbundled. They have been replaced by the package +system. Each elisp add-on (or groups of them when they are small) now +comes in its own tarball that contains a small search hierarchy. -@enumerate -@item -[ ./configure; make ] +You select just the ones you need. Install them by untarring them into +the right place. On startup XEmacs will find them, set up the load +path correctly, install autoloads, etc, etc. -@item -rm src/xemacs +@xref{Q2.1.1}, for more info on how to download and install the packages. -@item -strip src/temacs +@node Q1.7.2, Q1.7.3, Q1.7.1, Introduction +@unnumberedsubsec Q1.7.2: Which external packages are there? -@item -make +@subheading Normal Packages -@item -cp src/xemacs /usr/local/bin/xemacs +A very broad collection of elisp packages. -@item -cp lib-src/DOC-19.16-XEmacs -@iftex -\ @* -@end iftex -/usr/local/lib/xemacs-19.16/i586-unknown-linuxaout -@end enumerate -@end quotation +@table @asis +@item Sun +Support for Sparcworks. -@node Q2.0.13, Q2.0.14, Q2.0.12, Installation -@unnumberedsubsec Q2.0.13: I don't need no steenkin' packages. Do I? +@item ada +Ada language support. -Strictly speaking, no. XEmacs will build and install just fine without -any packages installed. However, only the most basic editing functions -will be available with no packages installed, so installing packages is -an essential part of making your installed XEmacs _useful_. +@item apel +A Portable Emacs Library. Used by XEmacs MIME support. -@node Q2.0.14, Q2.0.15, Q2.0.13, Installation -@unnumberedsubsec Q2.0.14: How do I figure out which packages to install? +@item auctex +Basic TeX/LaTeX support. -Many people really liked the old way that packages were bundled and do -not want to mess with packages at all. You can grab all the packages at -once like you used to with old XEmacs versions. Download the file +@item bbdb +The Big Brother Data Base: a rolodex-like database program. -@file{xemacs-sumo.tar.gz} +@item build +Build XEmacs from within (UNIX, Windows). -For an XEmacs compiled with Mule you also need +@item c-support +Basic single-file add-ons for editing C code. -@file{xemacs-mule-sumo.tar.gz} +@item calc +Emacs calculator. -from the @file{packages} directory on your XEmacs mirror archive. -N.B. They are called 'Sumo Tarballs' for good reason. They are -currently about 15MB and 2.3MB (gzipped) respectively. +@item calendar +Calendar and diary support. -Install them by +@item cc-mode +C, C++, Objective-C, Java, CORBA IDL, Pike and AWK language support. -@code{cd $prefix/lib/xemacs ; gunzip -c <tarballname> | tar xf -} +@item clearcase +New Clearcase Version Control for XEmacs (UNIX, Windows). -See README.packages for more detailed installation instructions. +@item clearcase +Support for the Clearcase version control system. -As the Sumo tarballs are not regenerated as often as the individual -packages, it is recommended that you use the automatic package tools -afterwards to pick up any recent updates. +@item cookie +"Fortune cookie"-style messages. Includes Spook (suspicious phrases) +and Yow (Zippy quotes). -@node Q2.0.15, Q2.0.16, Q2.0.14, Installation -@unnumberedsubsec Q2.0.15: EFS fails with "500 AUTH not understood" (NEW) +@item crisp +Crisp/Brief emulation. -A typical error: FTP Error: USER request failed; 500 AUTH not understood. +@item debug +GUD, gdb, dbx debugging support. -Thanks to giacomo boffi @email{giacomo.boffi@@polimi.it} who recommends -on comp.emacs.xemacs: +@item dictionary +Interface to RFC2229 dictionary servers. - tell your ftp client to not attempt AUTH authentication (or do not - use FTP servers that don't understand AUTH) +@item dired +The DIRectory EDitor is for manipulating, and running commands on +files in a directory. -and notes that you need to add an element (often "-u") to -`efs-ftp-program-args'. Use M-x customize-variable, and verify the -needed flag with `man ftp' or other local documentation. +@item docbookide +DocBook editing support. -@node Q2.0.16, Q2.1.1, Q2.0.15, Installation -@unnumberedsubsec Q2.0.16: Cygwin XEmacs won't start: cygXpm-noX4.dll was not found (NEW) +@item ecb +Emacs source code browser. -The Cygwin binary distributed with the netinstaller uses an external DLL -to handle XPM images (such as toolbar buttons). You may get an error like +@item ecrypto +Crypto functionality in Emacs Lisp. - This application has failed to start because cygXpm-noX4.dll was not found. - Re-installing the application may fix this problem. +@item edebug +An Emacs Lisp debugger. -Andy Piper <andy@@xemacs.org> sez: +@item ediff +Interface over GNU patch. - cygXpm-noX4 is part of the cygwin distribution under libraries or - graphics, but is not installed by default. You need to run the - cygwin setup again and select this package. +@item edit-utils +Miscellaneous editor extensions, you probably need this. -Ie, reinstalling XEmacs won't help because it is not part of the XEmacs -distribution. +@item edt +DEC EDIT/EDT emulation. -@node Q2.1.1, Q2.1.2, Q2.0.16, Installation -@unnumberedsec 2.1: Trouble Shooting -@unnumberedsubsec Q2.1.1: Help! XEmacs just crashed on me! +@item efs +Treat files on remote systems the same as local files. -First of all, don't panic. Whenever XEmacs crashes, it tries extremely -hard to auto-save all of your files before dying. (The main time that -this will not happen is if the machine physically lost power or if you -killed the XEmacs process using @code{kill -9}). The next time you try -to edit those files, you will be informed that a more recent auto-save -file exists. You can use @kbd{M-x recover-file} to retrieve the -auto-saved version of the file. +@item eieio +Enhanced Implementation of Emacs Interpreted Objects. -You can use the command @kbd{M-x recover-session} after a crash to pick -up where you left off. +@item elib +Portable Emacs Lisp utilities library. -Now, XEmacs is not perfect, and there may occasionally be times, or -particular sequences of actions, that cause it to crash. If you can -come up with a reproducible way of doing this (or even if you have a -pretty good memory of exactly what you were doing at the time), the -maintainers would be very interested in knowing about it. The best way -to report a bug is using @kbd{M-x report-emacs-bug} (or by selecting -@samp{Send Bug Report...} from the Help menu). If that won't work -(e.g. you can't get XEmacs working at all), send ordinary mail to -@email{crashes@@xemacs.org}. @emph{MAKE SURE} to include the output from -the crash, especially including the Lisp backtrace, as well as the -XEmacs configuration from @kbd{M-x describe-installation} (or -equivalently, the file @file{Installation} in the top of the build -tree). Please note that the @samp{crashes} address is exclusively for -crash reports. The best way to report bugs in general is through the -@kbd{M-x report-emacs-bug} interface just mentioned, or if necessary by -emailing @email{xemacs-beta@@xemacs.org}. Note that the developers do -@emph{not} usually follow @samp{comp.emacs.xemacs} on a regular basis; -thus, this is better for general questions about XEmacs than bug -reports. +@item emerge +Another interface over GNU patch. -If at all possible, include a C stack backtrace of the core dump that -was produced. This shows where exactly things went wrong, and makes it -much easier to diagnose problems. To do this under Unix, you need to -locate the core file (it's called @file{core}, and is usually sitting in -the directory that you started XEmacs from, or your home directory if -that other directory was not writable). Then, go to that directory and -execute a command like: +@item erc +ERC is an Emacs InternetRelayChat client. -@example -gdb `which xemacs` core -@end example +@item escreen +Multiple editing sessions withing a single frame (like screen). -and then issue the command @samp{where} to get the stack backtrace. You -might have to use @code{dbx} or some similar debugger in place of -@code{gdb}. If you don't have any such debugger available, complain to -your system administrator. +@item eshell +Command shell implemented entirely in Emacs Lisp. -It's possible that a core file didn't get produced, in which case you're -out of luck. Go complain to your system administrator and tell him not -to disable core files by default. Also see @ref{Q2.1.15}, for tips and -techniques for dealing with a debugger. +@item ess +ESS: Emacs Speaks Statistics. -If you're under Microsoft Windows, you're out of luck unless you happen -to have a debugging aid installed on your system, for example Visual -C++. In this case, the crash will result in a message giving you the -option to enter a debugger (for example, by pressing @samp{Cancel}). Do -this and locate the stack-trace window. (If your XEmacs was built -without debugging information, the stack trace may not be very useful.) +@item eterm +Terminal emulation. -When making a problem report make sure that: +@item eudc +Emacs Unified Directory Client (LDAP, PH). -@enumerate -@item -Report @strong{all} of the information output by XEmacs during the -crash. +@item footnote +Footnoting in mail message editing modes. -@item -You mention what O/S & Hardware you are running XEmacs on. +@item forms +Forms editing support (obsolete, use Widget instead). -@item -What version of XEmacs you are running. +@item fortran-modes +Fortran support. -@item -What build options you are using. +@item fortran-modes +Fortran language support. -@item -If the problem is related to graphics and you are running Unix, we will -also need to know what version of the X Window System you are running, -and what window manager you are using. +@item frame-icon +Set up mode-specific icons for each frame under XEmacs. -@item -If the problem happened on a TTY, please include the terminal type. -@end enumerate +@item fsf-compat +GNU Emacs compatibility files. -Much of the information above is automatically generated by @kbd{M-x -report-emacs-bug}. Even more, and often useful, information can be -generated by redirecting the output of @code{make} and @code{make check} -to a file (@file{beta.err} is the default used by @code{build-report}), -and executing @kbd{M-x build-report}. +@item games +Tetris, Sokoban, and Snake. -@node Q2.1.2, Q2.1.3, Q2.1.1, Installation -@unnumberedsubsec Q2.1.2: Cryptic Minibuffer messages. +@item general-docs +General documentation. Presently, empty. -When I try to use some particular option of some particular package, I -get a cryptic error in the minibuffer. +@item gnats +XEmacs bug reports. -If you can't figure out what's going on, select Options/General -Options/Debug on Error from the Menubar and then try and make the error -happen again. This will give you a backtrace that may be enlightening. -If not, try reading through this FAQ; if that fails, you could try -posting to comp.emacs.xemacs (making sure to include the backtrace) and -someone may be able to help. If you can identify which Emacs lisp -source file the error is coming from you can get a more detailed stack -backtrace by doing the following: +@item gnus +The Gnus Newsreader and Mailreader. -@enumerate -@item -Visit the .el file in an XEmacs buffer. +@item haskell-mode +Haskell editing support. -@item -Issue the command @kbd{M-x eval-current-buffer}. +@item hm--html-menus +HTML editing. -@item -Reproduce the error. -@end enumerate +@item hyperbole +Hyperbole: The Everyday Info Manager. -Depending on the version of XEmacs, you may either select View->Show -Message Log (recent versions), Edit->Show Messages (some earlier -versions) or Help->Recent Keystrokes/Messages (other earlier versions) -from the menubar to see the most recent messages. This command is bound -to @kbd{C-h l} by default. +@item ibuffer +Advanced replacement for buffer-menu. -@node Q2.1.3, Q2.1.4, Q2.1.2, Installation -@unnumberedsubsec Q2.1.3: Translation Table Syntax messages at Startup +@item idlwave +Editing and Shell mode for the Interactive Data Language. -I get tons of translation table syntax error messages during startup. -How do I get rid of them? +@item igrep +Enhanced front-end for Grep. -There are two causes of this problem. The first usually only strikes -people using the prebuilt binaries. The culprit in both cases is the -file @file{XKeysymDB}. +@item ilisp +Front-end for interacting with Inferior Lisp (external lisps). -@itemize @bullet -@item -The binary cannot find the @file{XKeysymDB} file. The location is -hardcoded at compile time so if the system the binary was built on puts -it a different place than your system does, you have problems. To fix, -set the environment variable @code{XKEYSYMDB} to the location of the -@file{XKeysymDB} file on your system or to the location of the one -included with XEmacs which should be at -@iftex -@* -@end iftex -@file{<xemacs_root_directory>/lib/xemacs-19.16/etc/XKeysymDB}. +@item ispell +Spell-checking with GNU ispell. -@item -The binary is finding the XKeysymDB but it is out-of-date on your system -and does not contain the necessary lines. Either ask your system -administrator to replace it with the one which comes with XEmacs (which -is the stock R6 version and is backwards compatible) or set your -@code{XKEYSYMDB} variable to the location of XEmacs's described above. -@end itemize +@item jde +Integrated Development Environment for Java. -@node Q2.1.4, Q2.1.5, Q2.1.3, Installation -@unnumberedsubsec Q2.1.4: Startup warnings about deducing proper fonts? +@item liece +IRC (Internet Relay Chat) client for Emacs. Note, this package is +deprecated and will be removed, use riece instead. -How can I avoid the startup warnings about deducing proper fonts? +@item mail-lib +Fundamental lisp files for providing email support. -This is highly dependent on your installation, but try with the -following font as your base font for XEmacs and see what it does: +@item mailcrypt +Support for messaging encryption with PGP. -@format --adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1 -@end format +@item mew +Messaging in an Emacs World; a MIME-based email program. -More precisely, do the following in your resource file: +@item mh-e +The XEmacs Interface to the MH Mail System. -@format -Emacs.default.attributeFont: \ --adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1 -@end format +@item mine +Elisp implementation of the game 'Minehunt'. -If you just don't want to see the @samp{*Warnings*} buffer at startup -time, you can set this: +@item misc-games +Other amusements and diversions. -@lisp -(setq display-warning-minimum-level 'error) -@end lisp +@item mmm-mode +Support for Multiple Major Modes within a single buffer. -The buffer still exists; it just isn't in your face. +@item net-utils +Miscellaneous Networking Utilities. -@node Q2.1.5, Q2.1.6, Q2.1.4, Installation -@unnumberedsubsec Q2.1.5: XEmacs cannot connect to my X Terminal! +@item ocaml +Objective Caml editing support. -Help! I can not get XEmacs to display on my Envizex X-terminal! +@item oo-browser +OO-Browser: The Multi-Language Object-Oriented Code Browser. -Try setting the @code{DISPLAY} variable using the numeric IP address of -the host you are running XEmacs from. +@item ocaml +Objective Caml editing support. -@node Q2.1.6, Q2.1.7, Q2.1.5, Installation -@unnumberedsubsec Q2.1.6: XEmacs just locked up my Linux X server! +@item os-utils +Miscellaneous single-file O/S utilities, for printing, archiving, +compression, remote shells, etc. -There have been several reports of the X server locking up under Linux. -In all reported cases removing speedo and scaled fonts from the font -path corrected the problem. This can be done with the command -@code{xset}. +@item pc +PC style interface emulation. -It is possible that using a font server may also solve the problem. +@item pcl-cvs +CVS frontend. -@node Q2.1.7, Q2.1.8, Q2.1.6, Installation -@unnumberedsubsec Q2.1.7: HP Alt key as Meta. +@item pcomplete +Provides programmatic completion. -How can I make XEmacs recognize the Alt key of my HP workstation as a -Meta key? +@item perl-modes +Perl support. -Put the following line into a file and load it with xmodmap(1) before -starting XEmacs: +@item pgg +Emacs interface to various PGP implementations. -@example -remove Mod1 = Mode_switch -@end example +@item prog-modes +Support for various programming languages. -@node Q2.1.8, Q2.1.9, Q2.1.7, Installation -@unnumberedsubsec Q2.1.8: got (wrong-type-argument color-instance-p nil) +@item ps-print +Printing functions and utilities. -@email{nataliek@@rd.scitec.com.au, Natalie Kershaw} writes: +@item psgml +Validated HTML/SGML editing. -@quotation -I am trying to run xemacs 19.13 under X11R4. Whenever I move the mouse I -get the following error. Has anyone seen anything like this? This -doesn't occur on X11R5. +@item psgml-dtds +A collection of DTDs for psgml. Note that this package is deprecated +and will be removed in the future, most likely Q2/2003. Instead of using +this, you should install needed DTDs yourself. -@lisp -Signalling: -(error "got (wrong-type-argument color-instance-p nil) -and I don't know why!") -@end lisp -@end quotation +@item python-modes +Python language support. -@email{map01kd@@gold.ac.uk, dinos} writes: +@item reftex +Emacs support for LaTeX cross-references, citations. -@quotation -I think this is due to undefined resources; You need to define color -backgrounds and foregrounds into your @file{.../app-defaults/Emacs} -like: +@item riece +IRC (Internet Relay Chat) client for Emacs. -@example -*Foreground: Black ;everything will be of black on grey95, -*Background: Grey95 ;unless otherwise specified. -*cursorColor: Red3 ;red3 cursor with grey95 border. -*pointerColor: Red3 ;red3 pointer with grey95 border. -@end example -@end quotation +@item rmail +An obsolete Emacs mailer. If you do not already use it don't start. -Natalie Kershaw adds: +@item ruby-modes +Ruby support. -@quotation -What fixed the problem was adding some more colors to the X color -database (copying the X11R5 colors over), and also defining the -following resources: +@item sasl +Simple Authentication and Security Layer (SASL) library. -@example -xemacs*cursorColor: black -xemacs*pointerColor: black -@end example +@item scheme +Front-end support for Inferior Scheme. -With the new colors installed the problem still occurs if the above -resources are not defined. +@item semantic +Semantic bovinator (Yacc/Lex for XEmacs). Includes Senator. -If the new colors are not present then an additional error occurs on -XEmacs startup, which says @samp{Color Red3} not defined. -@end quotation +@item sgml +SGML/Linuxdoc-SGML editing. -@node Q2.1.9, Q2.1.10, Q2.1.8, Installation -@unnumberedsubsec Q2.1.9: XEmacs causes my OpenWindows 3.0 server to crash. +@item sh-script +Support for editing shell scripts. -The OpenWindows 3.0 server is incredibly buggy. Your best bet is to -replace it with one from the generic MIT X11 release. You might also -try disabling parts of your @file{init.el}/@file{.emacs}, like those -that enable background pixmaps. +@item sieve +Manage Sieve email filtering scripts. -@node Q2.1.10, Q2.1.11, Q2.1.9, Installation -@unnumberedsubsec Q2.1.10: Warnings from incorrect key modifiers. +@item slider +User interface tool. -The following information comes from the @file{PROBLEMS} file that comes -with XEmacs. +@item sml-mode +SML editing support. -If you're having troubles with HP/UX it is because HP/UX defines the -modifiers wrong in X. Here is a shell script to fix the problem; be -sure that it is run after VUE configures the X server. +@item sounds-au +XEmacs Sun sound files. -@example -#! /bin/sh -xmodmap 2> /dev/null - << EOF -keysym Alt_L = Meta_L -keysym Alt_R = Meta_R -EOF +@item sounds-wav +XEmacs Microsoft sound files. -xmodmap - << EOF -clear mod1 -keysym Mode_switch = NoSymbol -add mod1 = Meta_L -keysym Meta_R = Mode_switch -add mod2 = Mode_switch -EOF -@end example +@item speedbar +Provides a separate frame with convenient references. -@node Q2.1.11, Q2.1.12, Q2.1.10, Installation -@unnumberedsubsec Q2.1.11: @samp{Can't instantiate image error...} in toolbar -@c New +@item strokes +Mouse enhancement utility. -@email{expt@@alanine.ram.org, Dr. Ram Samudrala} writes: +@item supercite +An Emacs citation tool for News & Mail messages. -I just installed the XEmacs (20.4-2) RPMS that I downloaded from -@uref{http://www.xemacs.org/}. Everything works fine, except that when -I place my mouse over the toolbar, it beeps and gives me this message: +@item texinfo +XEmacs TeXinfo support. -@example - Can't instantiate image (probably cached): - [xbm :mask-file "/usr/include/X11/bitmaps/leftptrmsk :mask-data - (16 16 <strange control characters> ... -@end example +@item text-modes +Miscellaneous support for editing text files. -@email{kyle_jones@@wonderworks.com, Kyle Jones} writes: -@quotation -This is problem specific to some Chips and Technologies video -chips, when running XFree86. Putting +@item textools +Miscellaneous TeX support. -@code{Option "sw_cursor"} +@item time +Display time & date on the modeline. -in @file{XF86Config} gets rid of the problem. -@end quotation +@item tm +Emacs MIME support. Not needed for gnus >= 5.8.0. -@node Q2.1.12, Q2.1.13, Q2.1.11, Installation -@unnumberedsubsec Q2.1.12: Problems with Regular Expressions on DEC OSF1. +@item tooltalk +Support for building with Tooltalk. -I have xemacs 19.13 running on an alpha running OSF1 V3.2 148 and ispell -would not run because it claimed the version number was incorrect -although it was indeed OK. I traced the problem to the regular -expression handler. +@item tpu +DEC EDIT/TPU support. -@email{douglask@@dstc.edu.au, Douglas Kosovic} writes: +@item tramp +Remote shell-based file editing. This is similar to EFS or Ange-FTP, +but works with rsh/ssh and rcp/scp. -@quotation -Actually it's a DEC cc optimization bug that screws up the regexp -handling in XEmacs. +@item vc +Version Control for Free systems. -Rebuilding using the @samp{-migrate} switch for DEC cc (which uses a -different sort of optimization) works fine. -@end quotation +@item vc-cc +Version Control for ClearCase (UnFree) systems. -See @file{xemacs-19_13-dunix-3_2c.patch} at the following URL on how to -build with the @samp{-migrate} flag: +@item vhdl +Support for VHDL. -@example -@uref{http://www-digital.cern.ch/carney/emacs/emacs.html} -@c Link above, <URL:http://www-digital.cern.ch/carney/emacs/emacs.html> is -@c dead. And the directory `carney' is empty. +@item view-process +A Unix process browsing tool. +@item viper +VI emulation support. +@item vm +An Emacs mailer. -@end example +@item w3 +A Web browser. -NOTE: There have been a variety of other problems reported that are -fixed in this fashion. +@item x-symbol +Semi WYSIWYG for LaTeX, HTML, etc, using additional fonts. -@node Q2.1.13, Q2.1.14, Q2.1.12, Installation -@unnumberedsubsec Q2.1.13: HP/UX 10.10 and @code{create_process} failure. +@item xemacs-base +Fundamental XEmacs support, you almost certainly need this. -@email{Dave.Carrigan@@ipl.ca, Dave Carrigan} writes: +@item xemacs-devel +XEmacs Lisp developer support. This package contains utilities for +supporting Lisp development. It is a single-file package so it may be +tailored. -@quotation -With XEmacs 19.13 and HP/UX 10.10, anything that relies on the -@code{create_process} function fails. This breaks a lot of things -(shell-mode, compile, ange-ftp, to name a few). -@end quotation +@item xlib +Emacs interface to X server. -@email{johnson@@dtc.hp.com, Phil Johnson} writes: +@item xslide +XSL editing support. -@quotation -This is a problem specific to HP-UX 10.10. It only occurs when XEmacs -is compiled for shared libraries (the default), so you can work around -it by compiling a statically-linked binary (run configure with -@samp{--dynamic=no}). +@item xslt-process +A minor mode for (X)Emacs which allows running an XSLT processor on a +buffer. -I'm not sure whether the problem is with a particular shared library or -if it's a kernel problem which crept into 10.10. -@end quotation +@item xwem +X Emacs Window Manager. -@email{cognot@@ensg.u-nancy.fr, Richard Cognot} writes: +@item zenirc +ZENIRC IRC Client. +@end table -@quotation -I had a few problems with 10.10. Apparently, some of them were solved by -forcing a static link of libc (manually). -@end quotation +@subheading Mule Support (mule) -@node Q2.1.14, Q2.1.15, Q2.1.13, Installation -@unnumberedsubsec Q2.1.14: @kbd{C-g} doesn't work for me. Is it broken? +MULti-lingual Enhancement. Support for world scripts such as +Latin, Arabic, Cyrillic, Chinese, Japanese, Greek, Hebrew etc. +To use these packages your XEmacs must be compiled with Mule +support. -@email{ben@@xemacs.org, Ben Wing} writes: +@table @asis +@item edict +MULE: Lisp Interface to EDICT, Kanji Dictionary. -@quotation -@kbd{C-g} does work for most people in most circumstances. If it -doesn't, there are only two explanations: +@item egg-its +MULE: Wnn (4.2 and 6) support. SJ3 support. -@enumerate -@item -The code is wrapped with a binding of @code{inhibit-quit} to -@code{t}. @kbd{Ctrl-Shift-G} should still work, I think. +@item latin-unity +MULE: find single ISO 8859 character set to encode a buffer. -@item -SIGIO is broken on your system, but BROKEN_SIGIO isn't defined. -@end enumerate +@item latin-unity +Unify character sets in a buffer. When characters belong to disjoint +character sets, this attempts to translate the characters so +that they belong to one character set. If the buffer coding system is +not sufficient, this suggests different coding systems. -To test #2, try executing @code{(while t)} from the @samp{*scratch*} -buffer. If @kbd{C-g} doesn't interrupt, then you're seeing #2. -@end quotation +@item leim +MULE: Quail. All non-English and non-Japanese language support. -@email{terra@@diku.dk, Morten Welinder} writes: +@item locale +MULE: Localized menubars and localized splash screens. -@quotation -On some (but @emph{not} all) machines a hung XEmacs can be revived by -@code{kill -FPE <pid>}. This is a hack, of course, not a solution. -This technique works on a Sun4 running 4.1.3_U1. To see if it works for -you, start another XEmacs and test with that first. If you get a core -dump the method doesn't work and if you get @samp{Arithmetic error} then -it does. -@end quotation +@item lookup +Dictionary support. (This isn't an English dictionary program) -@node Q2.1.15, Q2.1.16, Q2.1.14, Installation -@unnumberedsubsec Q2.1.15: How to debug an XEmacs problem with a debugger +@item mule-base +MULE: Basic Mule support, required for building with Mule. -If XEmacs does crash on you, one of the most productive things you can -do to help get the bug fixed is to poke around a bit with the debugger. -Here are some hints: +@item mule-ucs +MULE: Extended coding systems (including Unicode) for XEmacs. -@itemize @bullet -@item -First of all, if the crash is at all reproducible, consider very -strongly recompiling your XEmacs with debugging symbols and with no -optimization (e.g. with GCC use the compiler flags @samp{-g -O0} -- -that's an "oh" followed by a zero), and with the configure options -@samp{--debug=yes} and @samp{--error-checking=all}. This will make your -XEmacs run somewhat slower, but you are a lot more likely to catch the -problem earlier (closer to its source). It makes it a lot easier to -determine what's going on with a debugger. +@item mule-ucs +Extended coding systems (including Unicode) for XEmacs. -@item -If it's not a true crash (@emph{i.e.}, XEmacs is hung, or a zombie -process), or it's inconvenient to run XEmacs again because XEmacs is -already running or is running in batch mode as part of a bunch of -scripts, you may be able to attach to the existing process with your -debugger. Most debuggers let you do this by substituting the process ID -for the core file when you invoke the debugger from the command line, or -by using the @code{attach} command or something similar. +@item skk +Another Japanese Language Input Method. Can be used without a +separate process running as a dictionary server. +@end table -@item -If you're able to run XEmacs under a debugger and reproduce the crash, -here are some things you can do: +@node Q1.7.3, Q1.7.4, Q1.7.2, Introduction +@unnumberedsubsec Q1.7.3: Do I need to have the packages to run XEmacs? -@item -If XEmacs is hitting an assertion failure, put a breakpoint on -@code{assert_failed()}. +Strictly speaking, no. XEmacs will build and install just fine without +any packages installed. However, only the most basic editing functions +will be available with no packages installed, so installing packages is +an essential part of making your installed XEmacs _useful_. -@item -If XEmacs is hitting some weird Lisp error that's causing it to crash -(e.g. during startup), put a breakpoint on @code{signal_1()}---this is -declared static in eval.c. +@node Q1.7.4, Q1.8.1, Q1.7.3, Introduction +@unnumberedsubsec Q1.7.4: Is there a way to find which package has particular functionality? -@item -If XEmacs is outputting lots of X errors, put a breakpoint on -@code{x_error_handler()}; that will tell you which call is causing them. +If you want to find out which package contains the functionality you +are looking for, use @kbd{M-x package-get-package-provider}, and give it a +symbol that is likely to be in that package. -@item -Internally, you will probably see lots of variables that hold objects of -type @code{Lisp_Object}. These are references to Lisp objects. -Printing them out with the debugger probably won't be too -useful---you'll likely just see a number. To decode them, do this: +For example, if some code you want to use has a @code{(require 'thingatpt)} +in it: @example -call dp (OBJECT) + M-x package-get-package-provider RET thingatpt RET @end example -where @var{OBJECT} is whatever you want to decode (it can be a variable, -a function call, etc.). This uses the Lisp printing routines to out a -readable representation on the TTY from which the xemacs process was -invoked. +which will return something like: @samp{(fsf-compat "1.08").} -@item -If you want to get a Lisp backtrace showing the Lisp call -stack, do this: +@unnumberedsec 1.8: Internationalization -@example -call db () -@end example +@node Q1.8.1, Q1.8.2, Q1.7.4, Introduction +@unnumberedsubsec Q1.8.1: What is the status of internationalization support aka MULE (including Asian language support)? -@item -Using @code{dp} and @code{db} has two disadvantages - they can only be -used with a running (including hung or zombie) xemacs process, and they -do not display the internal C structure of a Lisp Object. Even if all -you've got is a core dump, all is not lost. +Both the stable and development versions of XEmacs include +internationalization support (aka MULE). MULE currently (21.4) works on +UNIX and Linux systems. It is possible to build with MULE on Windows +systems, but if you really need MULE on Windows, it is recommended that +you build and use the development (21.5) version, and deal with the +instability of the development tree. Binaries compiled without MULE +support run faster than MULE capable XEmacsen. -If you're using GDB, there are some macros in the file -@file{src/.gdbinit} in the XEmacs source distribution that should make -it easier for you to decode Lisp objects. This file is automatically -read by gdb if gdb is run in the directory where xemacs was built, and -contains these useful macros to inspect the state of xemacs: +@node Q1.8.2, Q1.8.3, Q1.8.1, Introduction +@unnumberedsubsec Q1.8.2: How can I help with internationalization? -@table @code -@item pobj -Usage: pobj lisp_object @* -Print the internal C representation of a lisp object. +If you would like to help, you may want to join the +@email{xemacs-mule@@xemacs.org} mailing list. Especially needed are +people who speak/write languages other than English, who are willing to +use XEmacs/MULE regularly, and have some experience with Elisp. -@item xtype -Usage: xtype lisp_object @* -Print the Lisp type of a lisp object. +Translations of the TUTORIAL and man page are welcome, and XEmacs does +support multilingual menus, but we have few current translations. -@item lbt -Usage: lbt @* -Print the current Lisp stack trace. -Requires a running xemacs process. (It works by calling the db -routine described above.) +@xref{Q1.5.2, How do I become a Beta Tester?}. -@item ldp -Usage: ldp lisp_object @* -Print a Lisp Object value using the Lisp printer. -Requires a running xemacs process. (It works by calling the dp -routine described above.) +@node Q1.8.3, Q1.8.4, Q1.8.2, Introduction +@unnumberedsubsec Q1.8.3: How do I type non-ASCII characters? -@item run-temacs -Usage: run-temacs @* -Run temacs interactively, like xemacs. -Use this with debugging tools (like purify) that cannot deal with dumping, -or when temacs builds successfully, but xemacs does not. +@xref{Q3.0.6, How can you type in special characters in XEmacs?}, in +part 3 of this FAQ, for some simple methods that also work in non-MULE +builds of XEmacs (but only for one-octet coded character sets, and +mostly for ISO 8859/1). Many of the methods available for Cyrillic +(@pxref{Q1.8.7, How about Cyrillic modes?}) work without MULE. MULE +has more general capabilities. @xref{Q1.8.5, Please explain the +various input methods in MULE/XEmacs}. -@item dump-temacs -Usage: dump-temacs @* -Run the dumping part of the build procedure. -Use when debugging temacs, not xemacs! -Use this when temacs builds successfully, but xemacs does not. +@xref{Q4.0.8, How do I display non-ASCII characters?}, which covers +display of non-ASCII characters. -@item check-xemacs -Usage: check-xemacs @* -Run the test suite. Equivalent to 'make check'. +@node Q1.8.4, Q1.8.5, Q1.8.3, Introduction +@unnumberedsubsec Q1.8.4: Can XEmacs messages come out in a different language? -@item check-temacs -Usage: check-temacs @* -Run the test suite on temacs. Equivalent to 'make check-temacs'. -Use this with debugging tools (like purify) that cannot deal with dumping, -or when temacs builds successfully, but xemacs does not. -@end table +The message-catalog support was written but is badly bit-rotted. XEmacs +20 and 21 did @emph{not} support it, and early releases of XEmacs 22 +will not either. -If you are using Sun's @file{dbx} debugger, there is an equivalent file -@file{src/.dbxrc}, which defines the same commands for dbx. +However, menubar localization @emph{does} work. To enable it, add to +your @file{Emacs} file entries like this: -@item -If you're using a debugger to get a C stack backtrace and you're seeing -stack traces with some of the innermost frames mangled, it may be due to -dynamic linking. (This happens especially under Linux.) Consider -reconfiguring with @samp{--dynamic=no}. Also, sometimes (again under -Linux), stack backtraces of core dumps will have the frame where the -fatal signal occurred mangled; if you can obtain a stack trace while -running the XEmacs process under a debugger, the stack trace should be -clean. +@example +Emacs*XlwMenu.resourceLabels: True +Emacs*XlwMenu.file.labelString: Fichier +Emacs*XlwMenu.openInOtherWindow.labelString: In anderem Fenster oeffnen +@end example -@email{1CMC3466@@ibm.mtsac.edu, Curtiss} suggests upgrading to ld.so -version 1.8 if dynamic linking and debugging is a problem on Linux. +The name of the resource is derived from the non-localized entry by +removing punctuation and capitalizing as above. -@item -If you're using a debugger to get a C stack backtrace and you're -getting a completely mangled and bogus stack trace, it's probably due to -one of the following: +@node Q1.8.5, Q1.8.6, Q1.8.4, Introduction +@unnumberedsubsec Q1.8.5: Please explain the various input methods in MULE/XEmacs -@enumerate a -@item -Your executable has been stripped. Bad news. Tell your sysadmin not to -do this---it doesn't accomplish anything except to save a bit of disk -space, and makes debugging much much harder. +Mule supports a wide variety of input methods. There are three basic +classes: Lisp implementations, generic platform support, and library +interfaces. -@item -Your stack is getting trashed. Debugging this is hard; you have to do a -binary-search type of narrowing down where the crash occurs, until you -figure out exactly which line is causing the problem. Of course, this -only works if the bug is highly reproducible. Also, in many cases if -you run XEmacs from the debugger, the debugger can protect the stack -somewhat. However, if the stack is being smashed, it is typically the -case that there is a wild pointer somewhere in the program, often quite -far from where the crash occurs. +@emph{Lisp implementations} include Quail, which provides table-driven input +methods for almost all the character sets that Mule supports (including +all of the ISO 8859 family, the Indic languages, Thai, and so on), and +SKK, for Japanese. (SKK also supports an interface to an external +"dictionary server" process.) Quail supports both typical "dead-key" +methods (eg, in the "latin-1-prefix" method, @kbd{" a} produces ä, LATIN +SMALL LETTER A WITH DIAERESIS), and the complex dictionary-based phonetic +methods used for Asian ideographic languages like Chinese. -@item -If your stack trace has exactly one frame in it, with address 0x0, this -could simply mean that XEmacs attempted to execute code at that address, -e.g. through jumping to a null function pointer. Unfortunately, under -those circumstances, GDB under Linux doesn't know how to get a stack -trace. (Yes, this is the fourth Linux-related problem I've mentioned. I -have no idea why GDB under Linux is so bogus. Complain to the GDB -authors, or to comp.os.linux.development.system.) Again, you'll have to -use the narrowing-down process described above. +Lisp implementations can be less powerful (but they are not perceptibly +inefficient), and of course are not portable to non-Emacs applications. +The incompatibility can be very annoying. On the other hand, they +require no special platform support or external libraries, so if you can +display the characters, Mule can input them for you and you can edit, +anywhere. + +@emph{Generic platform support} is currently limited to the X Input +Method (XIM) framework, although support for MSIME (for MS Windows) is +planned, and IIIMF (Sun's Internet-Intranet Input Method Framework) +support is extremely desirable. XIM is enabled at build time by use of +the @samp{--with-xim} flag to @code{configure}. For use of XIM, see +your platform documentation. However, normally the input method you use +is specified via the @samp{LANG} and @samp{XMODIFIERS} environment +variables. + +Of course, input skills are portable across most applications. However, +especially in modern GUI systems the habit of using bucky bits has +fallen into sad disuse, and many XIM systems are poorly configured for +use with Emacs. For example, the kinput2 input manager (a separate +process providing an interface between Japanese dictionary servers such +as Canna and Wnn, and the application) tends to gobble up keystrokes +generating Meta characters. This means that to edit while using an XIM +input method, you must toggle the input method off every time you want +to use @kbd{M-f}. Your mileage may vary. + +@emph{Library interfaces} are most common for Japanese, although Wnn +supports Chinese (traditional and simplified) and Korean. There are +Chinese and Korean input servers available, but we do not know of any +patches for XEmacs to use them directly. You can use them via +IM-enabled terminals, by manipulating the terminal coding systems. We +describe only the Japanese-oriented systems here. The advantage of +these systems is that they are very powerful, and on platforms where +they are available there is typically a wide range of applications that +support them. Thus your input skills are portable across applications. + +Mule provides built-in interfaces to the following input methods: Wnn4, +Wnn6, Canna, and SJ3. These can be configured at build time. There are +patches available (no URL, sorry) to support the SKK server, as well. +Wnn and SJ3 use the @code{egg} user interface. The interface for Canna +is specialized to Canna. + +Wnn supports Japanese, Chinese and Korean. It is made by OMRON and Kyôto +University. It is a powerful and complex system. Wnn4 is free and Wnn6 +is not. Wnn uses grammatical hints and probability of word association, +so in principle Wnn can be cleverer than other methods. -@item -You will get a Lisp backtrace output when XEmacs crashes, so you'll have -something useful. +Canna, made by NEC, supports only Japanese. It is a simple and powerful +system. Canna uses only grammar, but its grammar and dictionary are +quite sophisticated. So for standard modern Japanese, Canna seems +cleverer than Wnn4. In addition, the UNIX version of Canna is free (now +there is a Microsoft Windows version). -@end enumerate +SJ3, by Sony, supports only Japanese. -@item -If you compile with the newer gcc variants gcc-2.8 or egcs, you will -also need gdb 4.17 or above. Earlier releases of gdb can't handle the -debug information generated by the newer compilers. +Egg consists of following parts: +@enumerate @item -In versions of XEmacs before 21.2.27, @file{src/.gdbinit} was named -@file{src/gdbinit}. This had the disadvantage of not being sourced -automatically by gdb, so you had to set that up yourself. +Input character Translation System (ITS) layer. +It translates ASCII inputs to Kana/PinYin/Hangul characters. @item -If you are running Microsoft Windows, the the file @file{nt/README} for -further information about debugging XEmacs. +Kana/PinYin/Hangul to Kanji transfer layer. +The interface layer to network Kana-Kanji server (Wnn and Sj3). +@end enumerate -@end itemize +These input methods are modal. They have a raw (alphabet) mode, a +phonetic input mode, and Kana-Kanji transfer mode. However there are +mode-less input methods for Egg and Canna. @samp{boiled-egg} is a +mode-less input method running on Egg. For Canna, @samp{canna.el} has a +tiny boiled-egg-like command, @code{(canna-boil)}, and there are some +boiled-egg-like utilities. -@node Q2.1.16, Q2.1.17, Q2.1.15, Installation -@unnumberedsubsec Q2.1.16: XEmacs crashes in @code{strcat} on HP/UX 10 +Much of this information was provided by @email{morioka@@jaist.ac.jp, +MORIOKA Tomohiko}. -From the problems database (through -the former address http://support.mayfield.hp.com/): +@node Q1.8.6, Q1.8.7, Q1.8.5, Introduction +@unnumberedsubsec Q1.8.6: How do I portably code for MULE/XEmacs? -@example -Problem Report: 5003302299 -Status: Open +MULE has evolved rapidly over the last few years, and the original third +party patch (for GNU Emacs 19), GNU Emacs 20+, and XEmacs 20+ have quite +different implementations. The APIs also vary although recent versions +of XEmacs have tended to converge to the GNU Emacs standard. -System/Model: 9000/700 -Product Name: HPUX S800 10.0X -Product Vers: 9245XB.10.00 +MULE implementations are going to continue to evolve. Both GNU Emacs +and XEmacs are working hard on Unicode support, which will involve new +APIs and probably variations on old ones. For XEmacs 22, the old ISO +2022-based system for recognizing encodings will be replaced by a much +more flexible system, which should improve accuracy of automatic coding +detections, but will also involve new APIs. -Description: strcat(3C) may read beyond -end of source string, can cause SIGSEGV +@email{morioka@@jaist.ac.jp, MORIOKA Tomohiko} writes: +@quotation +The application implementor must write separate code for these mule +variants. [Please don't hesitate to report these variants to us; they +are not, strictly speaking, bugs, but they give third-party developers +the same kind of creepy-crawly feeling. We'll do what we can. -- Ed.] -*** PROBLEM TEXT *** -strcat(3C) may read beyond the source string onto an unmapped page, -causing a segmentation violation. -@end example +MULE and the next version of Emacs are similar but the symbols are very +different---requiring separate code as well. -@node Q2.1.17, Q2.1.18, Q2.1.16, Installation -@unnumberedsubsec Q2.1.17: @samp{Marker does not point anywhere} +Namely we must support 3 kinds of mule variants and 4 or 5 or 6 kinds of +emacs variants... (;_;) I'm shocked, so I wrote a wrapper package called +@code{emu} to provide a common interface. [There is an XEmacs package +of APEL which provides much more comprehensive coverage. Be careful, +however; APEL has problems of its own. -- Ed.] -As with other errors, set @code{debug-on-error} to @code{t} to get the -backtrace when the error occurs. Specifically, two problems have been -reported (and fixed). +I have the following suggestions about dealing with mule variants: -@enumerate +@itemize @bullet @item -A problem with line-number-mode in XEmacs 19.14 affected a large number -of other packages. If you see this error message, turn off -line-number-mode. +@code{(featurep 'mule)} @code{t} on all mule variants @item -A problem with some early versions of Gnus 5.4 caused this error. -Upgrade your Gnus. -@end enumerate - -@node Q2.1.18, Q2.1.19, Q2.1.17, Installation -@unnumberedsubsec Q2.1.18: XEmacs is outputting lots of X errors. - -If this is happening, we would very much like to know what's causing -them. To find this out, see @ref{Q2.1.15}. Try to get both a C and Lisp -backtrace, and send them to @email{xemacs-beta@@xemacs.org}. +@code{(boundp 'MULE)} is @code{t} on only MULE. Maybe the next version +of Emacs will not have this symbol. -@node Q2.1.19, Q2.1.20, Q2.1.18, Installation -@unnumberedsubsec Q2.1.19: XEmacs does not follow the local timezone. +@item +MULE has a variable @code{mule-version}. Perhaps the next version of +Emacs will have this variable as well. +@end itemize -When using one of the prebuilt binaries many users have observed that -XEmacs uses the timezone under which it was built, but not the timezone -under which it is running. The solution is to add: +Following is a sample to distinguish mule variants: @lisp -(set-time-zone-rule "MET") +(if (featurep 'mule) + (cond ((boundp 'MULE) + ;; for original Mule + ) + ((string-match "XEmacs" emacs-version) + ;; for XEmacs with Mule + ) + (t + ;; for next version of Emacs + )) + ;; for old emacs variants + ) @end lisp +@end quotation -to your @file{init.el}/@file{.emacs} or the @file{site-start.el} file if -you can. Replace @code{MET} with your local timezone. - -@node Q2.1.20, Q2.1.21, Q2.1.19, Installation -@unnumberedsubsec Q2.1.20: @samp{Symbol's function definition is void: hkey-help-show.} - -This is a problem with a partially loaded hyperbole. Try adding: - -@lisp -(require 'hmouse-drv) -@end lisp +@node Q1.8.7, Q1.8.8, Q1.8.6, Introduction +@unnumberedsubsec Q1.8.7: How about Cyrillic modes? -where you load hyperbole and the problem should go away. +@email{ilya@@math.ohio-state.edu, Ilya Zakharevich} writes: -@node Q2.1.21, Q2.1.22, Q2.1.20, Installation -@unnumberedsubsec Q2.1.21: [This question intentionally left blank] +@quotation +There is a cyrillic mode in the file @file{mysetup.zip} in +@iftex +@* +@end iftex +@uref{ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs/}. This is a +modification to @email{ava@@math.jhu.ed, Valery Alexeev's} @file{russian.el} +which can be obtained from +@end quotation -@node Q2.1.22, Q2.1.23, Q2.1.21, Installation -@unnumberedsubsec Q2.1.22: XEmacs seems to take a really long time to do some things +@uref{http://www.math.uga.edu/~valery/russian.el}. -@email{dmoore@@ucsd.edu, David Moore} writes: +@email{d.barsky@@ee.surrey.ac.uk, Dima Barsky} writes: @quotation -Two things you can do: - -1) C level: - -When you see it going mad like this, you might want to use gdb from an -'xterm' to attach to the running process and get a stack trace. To do -this just run: +There is another cyrillic mode for both GNU Emacs and XEmacs by +@email{manin@@camelot.mssm.edu, Dmitrii +(Mitya) Manin} at +@iftex -@example -gdb /path/to/xemacs/xemacs #### -@end example +@end iftex +@uref{http://kulichki-lat.rambler.ru/centrolit/manin/cyr.el}. +@c Link above, <URL:http://camelot.mssm.edu/~manin/cyr.el> was dead. +@c Changed to russian host instead +@end quotation -Where @code{####} is the process id of your xemacs, instead of -specifying the core. When gdb attaches, the xemacs will stop [1] and -you can type `where' in gdb to get a stack trace as usual. To get -things moving again, you can just type `quit' in gdb. It'll tell you -the program is running and ask if you want to quit anyways. Say 'y' and -it'll quit and have your emacs continue from where it was at. - -2) Lisp level: - -Turn on debug-on-quit early on. When you think things are going slow -hit C-g and it may pop you in the debugger so you can see what routine -is running. Press `c' to get going again. +@email{rebecca.ore@@op.net, Rebecca Ore} writes: -debug-on-quit doesn't work if something's turned on inhibit-quit or in -some other strange cases. +@quotation +The fullest resource I found on Russian language use (in and out of +XEmacs) is @uref{http://www.ibiblio.org/sergei/Software/Software.html} @end quotation -@node Q2.1.23, Q2.1.24, Q2.1.22, Installation -@unnumberedsubsec Q2.1.23: Movemail on Linux does not work for XEmacs 19.15 and later. +@node Q1.8.8, Q1.8.9, Q1.8.7, Introduction +@unnumberedsubsec Q1.8.8: Does XEmacs support Unicode? -Movemail used to work fine in 19.14 but has stopped working in 19.15 -and 20.x. I am using Linux. +To get Unicode support, you need a Mule-enabled XEmacs. -@email{steve@@xemacs.org, SL Baur} writes: +21.5 has internal support for Unicode and supports it fully, although we +don't yet use it as the internal encoding. -@quotation -Movemail on Linux used to default to using flock file locking. With -19.15 and later versions it now defaults to using @code{.lock} file -locking. If this is not appropriate for your system, edit src/s/linux.h -and uncomment the line that reads: +21.4 supports Unicode partially -- as an external encoding for files, +processes, and terminals, but without font support. @xref{Q1.8.9, How +does XEmacs display Unicode?}. To get Unicode support in 21.4, +install Mule-UCS from packages in the usual way, and put @example -#define MAIL_USE_FLOCK +(require 'un-define) +(set-coding-priority-list '(utf-8)) +(set-coding-category-system 'utf-8 'utf-8) @end example -@end quotation -@node Q2.1.24, Q2.1.25, Q2.1.23, Installation -@unnumberedsubsec Q2.1.24: XEmacs won't start without network. +in your init file to enable the UTF-8 coding system. You may wish to +view the documentation of @code{set-coding-priority-list} if you find +that files that are not UTF-8 are being mis-recognized as UTF-8. -If XEmacs starts when you're on the network, but fails when you're not -on the network, you may be missing a "localhost" entry in your -@file{/etc/hosts} file. The file should contain an entry like: +Install standard national fonts (not Unicode fonts) for all character +sets you use. @xref{Q1.8.9, How does XEmacs display Unicode??}. -@example -127.0.0.1 localhost -@end example +Mule-UCS also supports 16-bit forms of Unicode (UTF-16). It does not +support 31-bit forms of Unicode (UTF-32 or UCS-4). -Add that line, and XEmacs will be happy. +@node Q1.8.9, , Q1.8.8, Introduction +@unnumberedsubsec Q1.8.9: How does XEmacs display Unicode? + +Mule doesn't have a Unicode charset internally, so there's nothing to +bind a Unicode registry to. It would not be straightforward to create, +either, because Unicode is not ISO 2022-compatible. You'd have to +translate it to multiple 96x96 pages. -@node Q2.1.25, , Q2.1.24, Installation -@unnumberedsubsec Q2.1.25:: After upgrading, XEmacs won't do `foo' any more! +This means that Mule-UCS uses ordinary national fonts for display. This +is not really a problem, except for those languages that use the Unified +Han characters. The problem here is that Mule-UCS maps from Unicode +code points to national character sets in a deterministic way. By +default, this means that Japanese fonts are tried first, then Chinese, +then Korean. To change the priority ordering, use the command +`un-define-change-charset-order'. -You have been used to doing `foo', but now when you invoke it (or click -the toolbar button or select the menu item), nothing (or an error) -happens. The simplest explanation is that you are missing a package -that is essential to you. You can either track it down and install it -(there is a list of packages and brief descriptions of their contents in -@file{etc/PACKAGES}), or install the `Sumo Tarball' (@pxref{Q2.0.14}). +It also means you can't use Unicode fonts directly, at least not without +extreme hackery. You can run -nw with (set-terminal-coding-system +'utf-8) if you really want a Unicode font for some reason. -@c #### should xref to XEmacs manual here +Real Unicode support will be introduced in XEmacs 22.0. -@node Customization, Subsystems, Installation, Top -@unnumbered 3 Customization and Options +@node Installation, Editing, Introduction, Top +@unnumbered 2 Installation and Troubleshooting -This is part 3 of the XEmacs Frequently Asked Questions list. This -section is devoted to Customization and screen settings. +This is part 2 of the XEmacs Frequently Asked Questions list. This +section is devoted to Installation, Maintenance and Troubleshooting. @menu -Customization---Emacs Lisp and @file{init.el}/@file{.emacs}: -* Q3.0.1:: What version of Emacs am I running? -* Q3.0.2:: How do I evaluate Elisp expressions? -* Q3.0.3:: @code{(setq tab-width 6)} behaves oddly. -* Q3.0.4:: How can I add directories to the @code{load-path}? -* Q3.0.5:: How to check if a lisp function is defined? -* Q3.0.6:: Can I force the output of @code{(face-list)} to a buffer? -* Q3.0.7:: Font selections don't get saved after @code{Save Options}. -* Q3.0.8:: How do I make a single minibuffer frame? -* Q3.0.9:: What is @code{Customize}? - -X Window System & Resources: -* Q3.1.1:: Where is a list of X resources? -* Q3.1.2:: How can I detect a color display? -* Q3.1.3:: [This question intentionally left blank] -* Q3.1.4:: [This question intentionally left blank] -* Q3.1.5:: How can I get the icon to just say @samp{XEmacs}? -* Q3.1.6:: How can I have the window title area display the full path? -* Q3.1.7:: @samp{xemacs -name junk} doesn't work? -* Q3.1.8:: @samp{-iconic} doesn't work. - -Textual Fonts & Colors: -* Q3.2.1:: How can I set color options from @file{init.el}/@file{.emacs}? -* Q3.2.2:: How do I set the text, menu and modeline fonts? -* Q3.2.3:: How can I set the colors when highlighting a region? -* Q3.2.4:: How can I limit color map usage? -* Q3.2.5:: My tty supports color, but XEmacs doesn't use them. -* Q3.2.6:: Can I have pixmap backgrounds in XEmacs? -* Q3.2.7:: How do I display non-ASCII characters? - -The Modeline: -* Q3.3.1:: How can I make the modeline go away? -* Q3.3.2:: How do you have XEmacs display the line number in the modeline? -* Q3.3.3:: How do I get XEmacs to put the time of day on the modeline? -* Q3.3.4:: How do I turn off current chapter from AUC TeX modeline? -* Q3.3.5:: How can one change the modeline color based on the mode used? - -3.4 Multiple Device Support: -* Q3.4.1:: How do I open a frame on another screen of my multi-headed display? -* Q3.4.2:: Can I really connect to a running XEmacs after calling up over a modem? How? - -3.5 The Keyboard: -* Q3.5.1:: How can I bind complex functions (or macros) to keys? -* Q3.5.2:: How can I stop down-arrow from adding empty lines to the bottom of my buffers? -* Q3.5.3:: How do I bind C-. and C-; to scroll one line up and down? -* Q3.5.4:: Globally binding @kbd{Delete}? -* Q3.5.5:: Scrolling one line at a time. -* Q3.5.6:: How to map @kbd{Help} key alone on Sun type4 keyboard? -* Q3.5.7:: How can you type in special characters in XEmacs? -* Q3.5.8:: [This question intentionally left blank] -* Q3.5.9:: How do I make the Delete key delete forward? -* Q3.5.10:: Can I turn on @dfn{sticky} modifier keys? -* Q3.5.11:: How do I map the arrow keys? - -The Cursor: -* Q3.6.1:: Is there a way to make the bar cursor thicker? -* Q3.6.2:: Is there a way to get back the old block cursor where the cursor covers the character in front of the point? -* Q3.6.3:: Can I make the cursor blink? - -The Mouse and Highlighting: -* Q3.7.1:: How can I turn off Mouse pasting? -* Q3.7.2:: How do I set control/meta/etc modifiers on mouse buttons? -* Q3.7.3:: Clicking the left button does not do anything in buffer list. -* Q3.7.4:: How can I get a list of buffers when I hit mouse button 3? -* Q3.7.5:: Why does cut-and-paste not work between XEmacs and a cmdtool? -* Q3.7.6:: How I can set XEmacs up so that it pastes where the text cursor is? -* Q3.7.7:: How do I select a rectangular region? -* Q3.7.8:: Why does @kbd{M-w} take so long? - -The Menubar and Toolbar: -* Q3.8.1:: How do I get rid of the menu (or menubar)? -* Q3.8.2:: Can I customize the basic menubar? -* Q3.8.3:: How do I control how many buffers are listed in the menu @code{Buffers} list? -* Q3.8.4:: Resources like @code{Emacs*menubar*font} are not working? -* Q3.8.5:: How can I bind a key to a function to toggle the toolbar? - -Scrollbars: -* Q3.9.1:: How can I disable the scrollbar? -* Q3.9.2:: How can one use resources to change scrollbar colors? -* Q3.9.3:: Moving the scrollbar can move the point; can I disable this? -* Q3.9.4:: How can I turn off automatic horizontal scrolling in specific modes? - -Text Selections: -* Q3.10.1:: How can I turn off or change highlighted selections? -* Q3.10.2:: How do I get that typing on an active region removes it? -* Q3.10.3:: Can I turn off the highlight during isearch? -* Q3.10.4:: How do I turn off highlighting after @kbd{C-x C-p} (mark-page)? -* Q3.10.5:: The region disappears when I hit the end of buffer while scrolling. -* Q3.10.6:: Why is killing so slow? +2.0: Installation (General) +* Q2.0.1:: How do I build and install XEmacs? +* Q2.0.2:: Where do I find external libraries? +* Q2.0.3:: How do I specify the paths that XEmacs uses for finding files? +* Q2.0.4:: Running XEmacs without installing +* Q2.0.5:: XEmacs is too big + +2.1: Package Installation +* Q2.1.1:: How do I install the packages? +* Q2.1.2:: Can I install the packages individually? +* Q2.1.3:: Can I install the packages automatically? +* Q2.1.4:: Can I upgrade or remove packages? +* Q2.1.5:: Which packages to install? +* Q2.1.6:: Can you describe the package location process in more detail? +* Q2.1.7:: EFS fails with "500 AUTH not understood" + +2.2: Unix/Mac OS X Installation (Also Relevant to Cygwin, MinGW) +* Q2.2.1:: Libraries in non-standard locations +* Q2.2.2:: Why can't I strip XEmacs? + +2.3: Windows Installation (Windows, Cygwin, MinGW) +* Q2.3.1:: What exactly are all the different ways to build XEmacs under Windows? +* Q2.3.2:: What compiler/libraries do I need to compile XEmacs? +* Q2.3.3:: How do I compile the native port? +* Q2.3.4:: What do I need for Cygwin? +* Q2.3.5:: How do I compile under Cygwin? +* Q2.3.6:: How do I compile using MinGW (aka @samp{the -mno-cygwin flag to gcc})? +* Q2.3.7:: How do I compile with X support? +* Q2.3.8:: Cygwin XEmacs won't start -- cygXpm-noX4.dll was not found (NEW) + +2.4: General Troubleshooting +* Q2.4.1:: How do I deal with bugs or with problems building, installing, or running? +* Q2.4.2:: Help! XEmacs just crashed on me! +* Q2.4.3:: XEmacs crashes and I compiled it myself. +* Q2.4.4:: How to debug an XEmacs problem with a debugger +* Q2.4.5:: I get a cryptic error message when trying to do something. +* Q2.4.6:: XEmacs hangs when I try to do something. +* Q2.4.7:: I get an error message when XEmacs is running in batch mode. +* Q2.4.8:: The keyboard or mouse is not working properly, or I have some other event-related problem. +* Q2.4.9:: @kbd{C-g} doesn't work for me. Is it broken? +* Q2.4.10:: How do I debug process-related problems? +* Q2.4.11:: XEmacs is outputting lots of X errors. +* Q2.4.12:: After upgrading, XEmacs won't do `foo' any more! + +2.5: Startup-Related Problems +* Q2.5.1:: XEmacs cannot connect to my X Terminal! +* Q2.5.2:: Startup problems related to paths or package locations. +* Q2.5.3:: XEmacs won't start without network. +* Q2.5.4:: Startup warnings about deducing proper fonts? +* Q2.5.5:: Warnings from incorrect key modifiers. +* Q2.5.6:: XEmacs 21.1 on Windows used to spawn an ugly console window on every startup. Has that been fixed? @end menu -@node Q3.0.1, Q3.0.2, Customization, Customization -@unnumberedsec 3.0: Customization -- Emacs Lisp and @file{init.el}/@file{.emacs} -@unnumberedsubsec Q3.0.1: What version of Emacs am I running? - -How can @file{init.el}/@file{.emacs} determine which of the family of -Emacsen I am using? - -To determine if you are currently running GNU Emacs 18, GNU Emacs 19, -XEmacs 19, XEmacs 20, or Epoch, and use appropriate code, check out the -example given in @file{etc/sample.init.el} (@file{etc/sample.emacs} in -XEmacs versions prior to 21.4). There are other nifty things in there -as well! - -For all new code, all you really need to do is: - -@lisp -(defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version)) -@end lisp - -@node Q3.0.2, Q3.0.3, Q3.0.1, Customization -@unnumberedsubsec Q3.0.2: How can I evaluate Emacs-Lisp expressions? - -I know I can evaluate Elisp expressions from @code{*scratch*} buffer -with @kbd{C-j} after the expression. How do I do it from another -buffer? - -Press @kbd{M-:} (the default binding of @code{eval-expression}), and -enter the expression to the minibuffer. - -@node Q3.0.3, Q3.0.4, Q3.0.2, Customization -@unnumberedsubsec Q3.0.3: @code{(setq tab-width 6)} behaves oddly. - -If you put @code{(setq tab-width 6)} in your -@file{init.el}/@file{.emacs} file it does not work! Is there a reason -for this? If you do it at the EVAL prompt it works fine!! How strange. - -Use @code{setq-default} instead, since @code{tab-width} is -all-buffer-local. - -@node Q3.0.4, Q3.0.5, Q3.0.3, Customization -@unnumberedsubsec Q3.0.4: How can I add directories to the @code{load-path}? - -Here are two ways to do that, one that puts your directories at the -front of the load-path, the other at the end: - -@lisp -;;; Add things at the beginning of the load-path, do not add -;;; duplicate directories: -(pushnew "bar" load-path :test 'equal) - -(pushnew "foo" load-path :test 'equal) - -;;; Add things at the end, unconditionally -(setq load-path (nconc load-path '("foo" "bar"))) -@end lisp +@unnumberedsec 2.0: Installation (General) -@email{keithh@@nortel.ca, keith (k.p.) hanlan} writes: +@node Q2.0.1, Q2.0.2, Installation, Installation +@unnumberedsubsec Q2.0.1: How do I build and install XEmacs? -@quotation -To add directories using Unix shell metacharacters use -@file{expand-file-name} like this: +See the file @file{etc/NEWS} for information on new features and other +user-visible changes since the last version of XEmacs. -@lisp -(push (expand-file-name "~keithh/.emacsdir") load-path) -@end lisp -@end quotation +The file @file{INSTALL} in the top-level directory says how to bring +up XEmacs on Unix and Cygwin, once you have loaded the entire subtree +of this directory. -@node Q3.0.5, Q3.0.6, Q3.0.4, Customization -@unnumberedsubsec Q3.0.5: How to check if a lisp function is defined? +See the file @file{nt/README} for instructions on building XEmacs for +Microsoft Windows. -Use the following elisp: +@xref{Q2.1.1}, for the installation of (essential) add on packages. -@lisp -(fboundp 'foo) -@end lisp +@node Q2.0.2, Q2.0.3, Q2.0.1, Installation +@unnumberedsubsec Q2.0.2: Where do I find external libraries? -It's almost always a mistake to test @code{emacs-version} or any similar -variables. +All external libraries used by XEmacs can be found on the XEmacs web +site +@iftex +@* +@end iftex +@uref{http://www.xemacs.org/Download/optLibs.html}. -Instead, use feature-tests, such as @code{featurep}, @code{boundp}, -@code{fboundp}, or even simple behavioral tests, eg.: +The library versions available here are known to work with XEmacs. +(Newer versions will probably work as well but we can't guarantee it.) +We try to keep the libraries up-to-date but may not always succeed. +Check the above page for the canonical locations of the external libraries, +allowing you to download the latest, bleeding-edge versions. -@lisp -(defvar foo-old-losing-code-p - (condition-case nil (progn (losing-code t) nil) - (wrong-number-of-arguments t))) -@end lisp +@node Q2.0.3, Q2.0.4, Q2.0.2, Installation +@unnumberedsubsec Q2.0.3: How do I specify the paths that XEmacs uses for finding files? -There is an incredible amount of broken code out there which could work -much better more often in more places if it did the above instead of -trying to divine its environment from the value of one variable. +You can specify what paths to use by using a number of different flags +when running configure. See the section MAKE VARIABLES in the top-level +file INSTALL in the XEmacs distribution for a listing of those flags. -@node Q3.0.6, Q3.0.7, Q3.0.5, Customization -@unnumberedsubsec Q3.0.6: Can I force the output of @code{(face-list)} to a buffer? +Most of the time, however, the simplest fix is: @strong{do not} specify +paths as you might for GNU Emacs. XEmacs can generally determine the +necessary paths dynamically at run time. The only path that generally +needs to be specified is the root directory to install into. That can +be specified by passing the @code{--prefix} flag to configure. For a +description of the XEmacs install tree, please consult the @file{NEWS} +file. -It would be good having it in a buffer, as the output of -@code{(face-list)} is too wide to fit to a minibuffer. +@node Q2.0.4, Q2.0.5, Q2.0.3, Installation +@unnumberedsubsec Q2.0.4: Running XEmacs without installing -Evaluate the expression in the @samp{*scratch*} buffer with point after -the rightmost paren and typing @kbd{C-j}. +How can I just try XEmacs without installing it? -If the minibuffer smallness is the only problem you encounter, you can -simply press @kbd{C-h l} to get the former minibuffer contents in a -buffer. +XEmacs will run in place without requiring installation and copying of +the Lisp directories, and without having to specify a special build-time +flag. It's the copying of the Lisp directories that requires so much +space. XEmacs is largely written in Lisp. -@node Q3.0.7, Q3.0.8, Q3.0.6, Customization -@unnumberedsubsec Q3.0.7: Font selections in don't get saved after @code{Save Options}. +A good method is to make a shell alias for xemacs: -@email{mannj@@ll.mit.edu, John Mann} writes: +@example +alias xemacs=/src/xemacs-21.5/src/xemacs +@end example -@quotation -You have to go to Options->Frame Appearance and unselect -@samp{Frame-Local Font Menu}. If this option is selected, font changes -are only applied to the @emph{current} frame and do @emph{not} get saved -when you save options. -@end quotation +(You will obviously use whatever directory you downloaded the source +tree to instead of @file{/src/xemacs-21.5}). -Also, set the following in your @file{init.el}/@file{.emacs}: +This will let you run XEmacs without massive copying. -@lisp -(setq options-save-faces t) -@end lisp +@node Q2.0.5, Q2.1.1, Q2.0.4, Installation +@unnumberedsubsec Q2.0.5: XEmacs is too big -@node Q3.0.8, Q3.0.9, Q3.0.7, Customization -@unnumberedsubsec Q3.0.8: How do I get a single minibuffer frame? +The space required by the installation directories can be +reduced dramatically if desired. Gzip all the .el files. Remove all +the packages you'll never want to use. Remove the TexInfo manuals. +Remove the Info (and use just hardcopy versions of the manual). Remove +most of the stuff in etc. Remove or gzip all the source code. Gzip or +remove the C source code. Configure it so that copies are not made of +the support lisp. -@email{acs@@acm.org, Vin Shelton} writes: +These are all Emacs Lisp source code and bytecompiled object code. You +may safely gzip everything named *.el here. You may remove any package +you don't use. @emph{Nothing bad will happen if you delete a package +that you do not use}. You must be sure you do not use it though, so be +conservative at first. -@lisp -(setq initial-frame-plist '(minibuffer nil)) -(setq default-frame-plist '(minibuffer nil)) -(setq default-minibuffer-frame - (make-frame - '(minibuffer only - width 86 - height 1 - menubar-visible-p nil - default-toolbar-visible-p nil - name "minibuffer" - top -2 - left -2 - has-modeline-p nil))) -(frame-notice-user-settings) -@end lisp +Any package with the possible exceptions of xemacs-base, and EFS are +candidates for removal. Ask yourself, @emph{Do I ever want to use this +package?} If the answer is no, then it is a candidate for removal. -@strong{Please note:} The single minibuffer frame may not be to everyone's -taste, and there any number of other XEmacs options settings that may -make it difficult or inconvenient to use. +First, gzip all the .el files. Then go about package by package and +start gzipping the .elc files. Then run XEmacs and do whatever it is +you normally do. If nothing bad happens, then remove the package. You +can remove a package via the PUI interface +(@code{M-x pui-list-packages}, then press @kbd{d} to mark the packages +you wish to delete, and then @kbd{x} to delete them. -@node Q3.0.9, Q3.1.1, Q3.0.8, Customization -@unnumberedsubsec Q3.0.9: What is @code{Customize}? +Another method is to do @code{M-x package-get-delete-package}. -Starting with XEmacs 20.2 there is new system 'Customize' for customizing -XEmacs options. +@unnumberedsec 2.1: Package Installation -You can access @code{Customize} from the @code{Options} menu -or invoking one of customize commands by typing eg. -@kbd{M-x customize}, @kbd{M-x customize-face}, -@kbd{M-x customize-variable} or @kbd{M-x customize-apropos}. +@node Q2.1.1, Q2.1.2, Q2.0.5, Installation +@unnumberedsubsec Q2.1.1: How do I install the packages? -Starting with XEmacs 20.3 there is also new `browser' mode for Customize. -Try it out with @kbd{M-x customize-browse} +There are three ways to install the packages. -@node Q3.1.1, Q3.1.2, Q3.0.9, Customization -@unnumberedsec 3.1: X Window System & Resources -@unnumberedsubsec Q3.1.1: Where is a list of X resources? +@enumerate +@item +Manually, all at once, using the 'Sumo Tarball'. +@item +Manually, using individual package tarballs. +@item +Automatically, using the package tools from XEmacs. +@end enumerate -Search through the @file{NEWS} file for @samp{X Resources}. A fairly -comprehensive list is given after it. +If you don't want to mess with the packages, it is easiest to just +grab them manually, all at once. (For the other two ways, +@xref{Q2.1.2}, and @xref{Q2.1.3}.) Download the file -In addition, an @file{app-defaults} file @file{etc/Emacs.ad} is -supplied, listing the defaults. The file @file{etc/sample.Xresources} -gives a different set of defaults that you might consider for -installation in your @file{~/.Xresources} file. It is nearly the same -as @file{etc/Emacs.ad}, but a few entries are altered. Be careful about -installing the contents of this file into your @file{.Xresources} (or -legacy @file{.Xdefaults}) file if you use GNU Emacs under X11 as well. +@file{xemacs-sumo.tar.gz} -@node Q3.1.2, Q3.1.3, Q3.1.1, Customization -@unnumberedsubsec Q3.1.2: How can I detect a color display? +For an XEmacs compiled with Mule you also need -You can test the return value of the function @code{(device-class)}, as -in: +@file{xemacs-mule-sumo.tar.gz} -@lisp -(when (eq (device-class) 'color) - (set-face-foreground 'font-lock-comment-face "Grey") - (set-face-foreground 'font-lock-string-face "Red") - .... - ) -@end lisp +These are in the @file{packages} directory on your XEmacs mirror +archive: @uref{ftp://ftp.xemacs.org/pub/xemacs/packages} or its +mirrors. N.B. They are called 'Sumo Tarballs' for good reason. They +are currently about 19MB and 4.5MB (gzipped) respectively. -@node Q3.1.3, Q3.1.4, Q3.1.2, Customization -@unnumberedsubsec Q3.1.3: [This question intentionally left blank] +Install them on Unix and Mac OS X using the shell/Terminal command -@node Q3.1.4, Q3.1.5, Q3.1.3, Customization -@unnumberedsubsec Q3.1.4: [This question intentionally left blank] +@code{cd $prefix/lib/xemacs ; gunzip -c <tarballname> | tar xf -} -@node Q3.1.5, Q3.1.6, Q3.1.4, Customization -@unnumberedsubsec Q3.1.5: How can I get the icon to just say @samp{XEmacs}? +Where @samp{$prefix} is what you gave to the @samp{--prefix} flag to +@file{configure}, and defaults to @file{/usr/local}. -I'd like the icon to just say @samp{XEmacs}, and not include the name of -the current file in it. +If you have GNU tar you can use: -Add the following line to your @file{init.el}/@file{.emacs}: +@code{cd $prefix/lib/xemacs ; tar zxvf <tarballname>} -@lisp -(setq frame-icon-title-format "XEmacs") -@end lisp +If you have the packages somewhere nonstandard and don't want to +bother with @samp{$prefix} (for example, you're a developer and are +compiling the packages yourself, and want your own private copy of +everything), you can also directly specify this using @file{configure}. +To do this under 21.5 and above use the @samp{--package-prefix} parameter +to specify the directory under which you untarred the above tarballs. +Under 21.4 and previous you need to use @samp{--package-path}, +something like this: -@node Q3.1.6, Q3.1.7, Q3.1.5, Customization -@unnumberedsubsec Q3.1.6: How can I have the window title area display the full path? +@example + configure --package-path="~/.xemacs::/src/xemacs/site-packages:/src/xemacs/xemacs-packages:/src/xemacs/mule-packages" ... +@end example -I'd like to have the window title area display the full directory/name -of the current buffer file and not just the name. +Under Windows, you need to place the above @samp{tar.gz} files in the +directory specified using the @samp{PACKAGE_PREFIX} value in +@file{nt/config.inc} and by default is @file{\Program Files\XEmacs}. +(To untar a @samp{tar.gz} file you will need to use a utility such as +WinZip, unless you have Cygwin or a similar environment installed, in +which case the above Unix shell command should work fine.) If you want +the packages somewhere else, just change @samp{PACKAGE_PREFIX}. + +Note that XEmacs finds the packages automatically anywhere underneath +the directory tree where it expects to find the packages. All you +need to do is put stuff there; you don't need to run any program to +tell XEmacs to find the packges, or do anything of that sort. -Add the following line to your @file{init.el}/@file{.emacs}: +However, XEmacs will only notice newly installed packages when it +starts up, so you will have to restart if you are already running +XEmacs. -@lisp -(setq frame-title-format "%S: %f") -@end lisp +For more details, @xref{Startup Paths,,,xemacs, the XEmacs User's +Manual}, and @xref{Packages,,,xemacs, the XEmacs User's Manual}. -A more sophisticated title might be: +As the Sumo tarballs are not regenerated as often as the individual +packages, it is recommended that you use the automatic package tools +afterwards to pick up any recent updates. -@lisp -(setq frame-title-format - '("%S: " (buffer-file-name "%f" - (dired-directory dired-directory "%b")))) -@end lisp +@emph{NOTE}: For detailed information about how the package +hierarchies work, @xref{Package Overview,,,lispref, the XEmacs Lisp +Reference Manual}. -That is, use the file name, or the dired-directory, or the buffer name. +@node Q2.1.2, Q2.1.3, Q2.1.1, Installation +@unnumberedsubsec Q2.1.2: Can I install the packages individually? -@node Q3.1.7, Q3.1.8, Q3.1.6, Customization -@unnumberedsubsec Q3.1.7: @samp{xemacs -name junk} doesn't work? +Yes, you can download individual packages from the FTP site (@pxref{Q2.1.1}). Since packages are automatically noticed at startup, you just have to put them in the right place. -When I run @samp{xterm -name junk}, I get an xterm whose class name -according to xprop, is @samp{junk}. This is the way it's supposed to -work, I think. When I run @samp{xemacs -name junk} the class name is -not set to @samp{junk}. It's still @samp{emacs}. What does -@samp{xemacs -name} really do? The reason I ask is that my window -manager (fvwm) will make a window sticky and I use XEmacs to read my -mail. I want that XEmacs window to be sticky, without having to use the -window manager's function to set the window sticky. What gives? +Note: If you are upgrading packages already installed, it's best to +remove the old package first (@pxref{Q2.1.4}). -@samp{xemacs -name} sets the application name for the program (that is, -the thing which normally comes from @samp{argv[0]}). Using @samp{-name} -is the same as making a copy of the executable with that new name. The -@code{WM_CLASS} property on each frame is set to the frame-name, and the -application-class. So, if you did @samp{xemacs -name FOO} and then -created a frame named @var{BAR}, you'd get an X window with WM_CLASS = -@code{( "BAR", "Emacs")}. However, the resource hierarchy for this -widget would be: +For example if we are installing the @samp{xemacs-base} +package (version 1.48): @example -Name: FOO .shell .container .BAR -Class: Emacs .TopLevelEmacsShell.EmacsManager.EmacsFrame + mkdir $prefix/lib/xemacs/xemacs-packages RET # if it does not exist yet + cd $prefix/lib/xemacs/xemacs-packages RET + gunzip -c /path/to/xemacs-base-1.48-pkg.tar.gz | tar xvf - RET @end example -instead of the default +Or if you have GNU tar, the last step can be: @example -Name: xemacs.shell .container .emacs -Class: Emacs .TopLevelEmacsShell.EmacsManager.EmacsFrame + tar zxvf /path/to/xemacs-base-1.48-pkg.tar.gz RET @end example +For MULE related packages, it is best to untar into the @samp{mule-packages} +hierarchy, i.e. for the @samp{mule-base} package, version 1.37: -It is arguable that the first element of WM_CLASS should be set to the -application-name instead of the frame-name, but I think that's less -flexible, since it does not give you the ability to have multiple frames -with different WM_CLASS properties. Another possibility would be for -the default frame name to come from the application name instead of -simply being @samp{emacs}. However, at this point, making that change -would be troublesome: it would mean that many users would have to make -yet another change to their resource files (since the default frame name -would suddenly change from @samp{emacs} to @samp{xemacs}, or whatever -the executable happened to be named), so we'd rather avoid it. - -To make a frame with a particular name use: - -@lisp -(make-frame '((name . "the-name"))) -@end lisp - -@node Q3.1.8, Q3.2.1, Q3.1.7, Customization -@unnumberedsubsec Q3.1.8: @samp{-iconic} doesn't work. - -When I start up XEmacs using @samp{-iconic} it doesn't work right. -Using @samp{-unmapped} on the command line, and setting the -@code{initiallyUnmapped} X Resource don't seem to help much either... - -@email{ben@@xemacs.org, Ben Wing} writes: - -@quotation -Ugh, this stuff is such an incredible mess that I've about given up -getting it to work. The principal problem is numerous window-manager -bugs... -@end quotation +@example + mkdir $prefix/lib/xemacs/mule-packages RET # if it does not exist yet + cd $prefix/lib/xemacs/mule-packages RET + gunzip -c /path/to/mule-base-1.37-pkg.tar.gz | tar xvf - RET +@end example -@node Q3.2.1, Q3.2.2, Q3.1.8, Customization -@unnumberedsec 3.2: Textual Fonts & Colors -@unnumberedsubsec Q3.2.1: How can I set color options from @file{init.el}/@file{.emacs}? +Or if you have GNU tar, the last step can be: -How can I set the most commonly used color options from my -@file{init.el}/@file{.emacs} instead of from my @file{.Xresources}? +@example + tar zxvf /path/to/mule-base-1.37-pkg.tar.gz RET +@end example -Like this: +@node Q2.1.3, Q2.1.4, Q2.1.2, Installation +@unnumberedsubsec Q2.1.3: Can I install the packages automatically? -@lisp -(set-face-background 'default "bisque") ; frame background -(set-face-foreground 'default "black") ; normal text -(set-face-background 'zmacs-region "red") ; When selecting w/ - ; mouse -(set-face-foreground 'zmacs-region "yellow") -(set-face-font 'default "*courier-bold-r*120-100-100*") -(set-face-background 'highlight "blue") ; Ie when selecting - ; buffers -(set-face-foreground 'highlight "yellow") -(set-face-background 'modeline "blue") ; Line at bottom - ; of buffer -(set-face-foreground 'modeline "white") -(set-face-font 'modeline "*bold-r-normal*140-100-100*") -(set-face-background 'isearch "yellow") ; When highlighting - ; while searching -(set-face-foreground 'isearch "red") -(setq x-pointer-foreground-color "black") ; Adds to bg color, - ; so keep black -(setq x-pointer-background-color "blue") ; This is color - ; you really - ; want ptr/crsr -@end lisp +XEmacs comes with some tools to make the periodic updating and +installing easier. It will notice if new packages or versions are +available and will fetch them from the FTP site. -@node Q3.2.2, Q3.2.3, Q3.2.1, Customization -@unnumberedsubsec Q3.2.2: How do I set the text, menu and modeline fonts? +Unfortunately this requires that a few packages are already in place. +You will have to install them by hand as above or use a SUMO tarball. +This requirement will hopefully go away in the future. The packages +you need are: -Note that you should use @samp{Emacs.} and not @samp{Emacs*} when -setting face values. +@example + efs - To fetch the files from the FTP site or mirrors. + xemacs-base - Needed by efs. +@end example -In @file{.Xresources}: +and optionally: @example -Emacs.default.attributeFont: -*-*-medium-r-*-*-*-120-*-*-m-*-*-* -Emacs*menubar*font: fixed -Emacs.modeline.attributeFont: fixed + mailcrypt - For PGP verification of the package-index file. @end example -This is confusing because @samp{default} and @samp{modeline} are face -names, and can be found listed with all faces in the current mode by -using @kbd{M-x set-face-font (enter) ?}. They use the face-specific -resource @samp{attributeFont}. +After installing these by hand, fire up XEmacs and follow these +steps. -On the other hand, @samp{menubar} is a normal X thing that uses the -resource @samp{font}. With Motif it @emph{may be} necessary to use -@samp{fontList} @emph{instead of} @samp{font}. In @emph{non-Motif} -configurations with Mule it @emph{is} necessary to use @samp{fontSet} -instead of @samp{font}. (Sorry, there just is no simple recipe here.) +@enumerate +@item +Choose a download site. +@itemize @bullet +@item +via menu: Tools -> Packages -> Set Download Site +@item +via keyb: M-x customize-variable RET package-get-remote RET +(put in the details of remote host and directory) +@end itemize -@node Q3.2.3, Q3.2.4, Q3.2.2, Customization -@unnumberedsubsec Q3.2.3: How can I set the colors when highlighting a region? +If the package tarballs _AND_ the package-index file are in a +local directory, you can: M-x pui-set-local-package-get-directory RET -How can I set the background/foreground colors when highlighting a -region? +@item +Obtain a list of packages and display the list in a buffer named +"*Packages*". +@itemize @bullet +@item +menu: Tools -> Packages -> List & Install +@item +keyb: M-x pui-list-packages RET +@end itemize -You can change the face @code{zmacs-region} either in your -@file{.Xresources}: +XEmacs will now connect to the remote site and download the +latest package-index file. -@example -Emacs.zmacs-region.attributeForeground: firebrick -Emacs.zmacs-region.attributeBackground: lightseagreen -@end example +The resulting buffer, "*Packages*" has brief instructions at the +end of the buffer. -or in your @file{init.el}/@file{.emacs}: +@item +Choose the packages you wish to install. +@itemize @bullet +@item +mouse: Click button 2 on the package name. +@item +keyb: RET on the package name +@end itemize -@lisp -(set-face-background 'zmacs-region "red") -(set-face-foreground 'zmacs-region "yellow") -@end lisp +@item +Make sure you have everything you need. +@itemize @bullet +@item +menu: Packages -> Add Required +@item +keyb: r +@end itemize -@node Q3.2.4, Q3.2.5, Q3.2.3, Customization -@unnumberedsubsec Q3.2.4: How can I limit color map usage? +XEmacs will now search for packages that are required by the +ones that you have chosen to install and offer to select +those packages also. -I'm using Netscape (or another color grabber like XEmacs); -is there any way to limit the number of available colors in the color map? +For novices and gurus alike, this step can save your bacon. +It's easy to forget to install a critical package. -Answer: No, but you can start Netscape before XEmacs, and it will use -the closest available color if the colormap is full. You can also limit -the number of colors Netscape uses, using the flags -mono, -ncols <#> or --install (for mono, limiting to <#> colors, or for using a private color -map). +@item +Download and install the packages. +@itemize @bullet +@item +menu: Packages -> Install/Remove Selected +@item +keyb: x +@end itemize +@end enumerate -If you have the money, another solution would be to use a truecolor or -direct color video. +@node Q2.1.4, Q2.1.5, Q2.1.3, Installation +@unnumberedsubsec Q2.1.4: Can I upgrade or remove packages? -@node Q3.2.5, Q3.2.6, Q3.2.4, Customization -@unnumberedsubsec Q3.2.5: My tty supports color, but XEmacs doesn't use them. +As the exact files and their locations contained in a package may +change it is recommended to remove a package first before installing a +new version. In order to facilitate removal each package contains an +pgkinfo/MANIFEST.pkgname file which list all the files belong to the +package. M-x package-admin-delete-binary-package RET can be used to +remove a package using this file. -XEmacs tries to automatically determine whether your tty supports color, -but sometimes guesses wrong. In that case, you can make XEmacs Do The -Right Thing using this Lisp code: +Note that the interactive package tools included with XEmacs already do +this for you. -@lisp -(if (eq 'tty (device-type)) - (set-device-class nil 'color)) -@end lisp +@node Q2.1.5, Q2.1.6, Q2.1.4, Installation +@unnumberedsubsec Q2.1.5: Which packages to install? -@node Q3.2.6, Q3.2.7, Q3.2.5, Customization -@unnumberedsubsec Q3.2.6: Can I have pixmap backgrounds in XEmacs? -@c New -@email{jvillaci@@wahnsinnig.extreme.indiana.edu, Juan Villacis} writes: +Unless you are an advanced user, just install everything. -@quotation -There are several ways to do it. For example, you could specify a -default pixmap image to use in your @file{~/.Xresources}, e.g., +If you really want to install only what's absolutely needed, a good +minimal set of packages for XEmacs-latin1 would be +@example +xemacs-base, xemacs-devel, c-support, cc-mode, debug, dired, efs, +edit-utils, fsf-compat, mail-lib, net-utils, os-utils, prog-modes, +text-modes, time, mailcrypt +@end example + +If you are using the XEmacs package tools, don't forget to do: @example - Emacs*EmacsFrame.default.attributeBackgroundPixmap: /path/to/image.xpm + Packages -> Add Required @end example +To make sure you have everything that the packages you have chosen to +install need. -and then reload ~/.Xresources and restart XEmacs. Alternatively, -since each face can have its own pixmap background, a better way -would be to set a face's pixmap within your XEmacs init file, e.g., +@xref{Q1.7.2}, for a description of the various packages. -@lisp - (set-face-background-pixmap 'default "/path/to/image.xpm") - (set-face-background-pixmap 'bold "/path/to/another_image.xpm") -@end lisp +@node Q2.1.6, Q2.1.7, Q2.1.5, Installation +@unnumberedsubsec Q2.1.6: Can you describe the package location process in more detail? -and so on. You can also do this interactively via @kbd{M-x edit-faces}. +On startup XEmacs looks for packages in so-called package hierarchies. +Normally, there are three system wide hierarchies, like this: -@end quotation +@example +$prefix/lib/xemacs/xemacs-packages/ + Normal packages go here. -@node Q3.2.7, Q3.3.1, Q3.2.6, Customization -@unnumberedsubsec Q3.2.7: How do I display non-ASCII characters? -@c New +$prefix/lib/xemacs/mule-packages/ + Mule packages go here and are only searched by MULE-enabled XEmacsen. -If you're using a Mule-enabled XEmacs, then display is automatic. If -you're not seeing the characters you expect, either (1) you don't have -appropriate fonts available or (2) XEmacs did not correctly detect the -coding system (@pxref{Recognize Coding, , , xemacs}). In case (1), -install fonts as is customary for your platform. In case (2), you -need to tell XEmacs explicitly what coding systems you're using. -@ref{Specify Coding, , , xemacs}. +$prefix/lib/xemacs/site-packages/ + Local and 3rd party packages go here. +@end example -If your XEmacs is not Mule-enabled, and for some reason getting a -Mule-enabled XEmacs seems like the wrong thing to do, all is not lost. -You can arrange it by brute force. In @file{event-Xt.c} (suppress the -urge to look in this file---play Doom instead, because you'll survive -longer), it is written: +This is what you get when you untar the SUMO tarballs under +@file{$prefix/lib/xemacs}. -@quotation -In a non-Mule world, a user can still have a multi-lingual editor, by -doing @code{(set-face-font "-*-iso8859-2" (current-buffer))} for all -their Latin-2 buffers, etc. -@end quotation +@file{$prefix} is specified using the @samp{--prefix} parameter to +@file{configure}, and defaults to @file{usr/local}. -For the related problem of @emph{inputting} non-ASCII characters in a -non-Mule XEmacs, @xref{Q3.5.7}. +If the package path is not explicitly specified, XEmacs looks for the +package directory @file{xemacs-packages} (and @file{mule-packages} and +@file{site-packages}) first under @samp{~/.xemacs}, then for a sister +directory @file{lib/xemacs-VERSION} of the directory in which the +XEmacs executable is located, then for a sister directory +@file{lib/xemacs}. The XEmacs executable (under Unix at least) is +installed by default in @file{/usr/local/bin}; this explains why +XEmacs in its default installation will find packages that you put +under @file{/usr/local/lib/xemacs}. -@node Q3.3.1, Q3.3.2, Q3.2.7, Customization -@unnumberedsec 3.3: The Modeline -@unnumberedsubsec Q3.3.1: How can I make the modeline go away? +You can specify where exactly XEmacs looks for packages by using the +@samp{--package-prefix} or @samp{--package-path} parameters to +@file{configure} (or the equivalent settings in @file{config.inc}, +under Windows), or setting the @samp{EMACSPACKAGEPATH} environment +variable (which has the same format as @samp{--package-path}). +@xref{Q2.1.1}. -@lisp -(set-specifier has-modeline-p nil) -@end lisp +See @file{configure.usage} for more info about the format of these +@file{configure} parameters. -@c Starting with XEmacs 19.14 the modeline responds to mouse clicks, so if -@c you haven't liked or used the modeline in the past, you might want to -@c try the new version out. -@c -@node Q3.3.2, Q3.3.3, Q3.3.1, Customization -@unnumberedsubsec Q3.3.2: How do you have XEmacs display the line number in the modeline? +In addition to the system wide packages, each user can have his own +packages installed under @file{~/.xemacs/}. If you want to install +packages there using the interactive tools, you need to set +@code{package-get-install-to-user-init-directory} to @code{t}. -Add the following line to your @file{init.el}/@file{.emacs} file to -display the line number: +The site-packages hierarchy replaces the old @file{site-lisp} +directory. XEmacs no longer looks into a @file{site-lisp} directly by +default. A good place to put @file{site-start.el} would be in +@file{$prefix/lib/xemacs/site-packages/lisp/}. -@lisp -(line-number-mode 1) -@end lisp +@node Q2.1.7, Q2.2.1, Q2.1.6, Installation +@unnumberedsubsec Q2.1.7: EFS fails with "500 AUTH not understood" (NEW) -Use the following to display the column number: +A typical error: FTP Error: USER request failed; 500 AUTH not understood. -@lisp -(column-number-mode 1) -@end lisp +Thanks to giacomo boffi @email{giacomo.boffi@@polimi.it} who recommends +on comp.emacs.xemacs: -Or select from the @code{Options} menu -@iftex -@* -@end iftex -@code{Advanced (Customize)->Emacs->Editing->Basics->Line Number Mode} -and/or -@iftex -@* -@end iftex -@code{Advanced (Customize)->Emacs->Editing->Basics->Column Number Mode} + tell your ftp client to not attempt AUTH authentication (or do not + use FTP servers that don't understand AUTH) -Or type @kbd{M-x customize @key{RET} editing-basics @key{RET}}. +and notes that you need to add an element (often "-u") to +`efs-ftp-program-args'. Use M-x customize-variable, and verify the +needed flag with `man ftp' or other local documentation. -@node Q3.3.3, Q3.3.4, Q3.3.2, Customization -@unnumberedsubsec Q3.3.3: How do I get XEmacs to put the time of day on the modeline? +@unnumberedsec 2.2: Unix/Mac OS X Installation (Also Relevant to Cygwin, MinGW) -Add the following line to your @file{init.el}/@file{.emacs} file to -display the time: +@node Q2.2.1, Q2.2.2, Q2.1.7, Installation +@unnumberedsubsec Q2.2.1: Libraries in non-standard locations -@lisp -(display-time) -@end lisp +If your libraries are in a non-standard location, you can specify the location +using the following flags to @file{configure}: -See @code{Customize} from the @code{Options} menu for customization. +@example +--site-libraries=WHATEVER +--site-includes=WHATEVER +@end example -@node Q3.3.4, Q3.3.5, Q3.3.3, Customization -@unnumberedsubsec Q3.3.4: How do I turn off current chapter from AUC TeX modeline? +If you have multiple paths to specify, use the following syntax: -With AUC TeX, fast typing is hard because the current chapter, section -etc. are given in the modeline. How can I turn this off? +@example +--site-libraries='/path/one /path/two /path/etc' +@end example -It's not AUC TeX, it comes from @code{func-menu} in @file{func-menu.el}. +@node Q2.2.2, Q2.3.1, Q2.2.1, Installation +@unnumberedsubsec Q2.2.2: Why can't I strip XEmacs? -@c Add this code to your @file{init.el}/@file{.emacs} to turn it off: -@c -@c @lisp -@c (setq fume-display-in-modeline-p nil) -@c @end lisp -@c -@c Or just add a hook to @code{TeX-mode-hook} to turn it off only for TeX -@c mode: -@c -@c @lisp -@c (add-hook 'TeX-mode-hook -@c '(lambda () (setq fume-display-in-modeline-p nil))) -@c @end lisp -@c -@email{dhughes@@origin-at.co.uk, David Hughes} writes: +@email{cognot@@fronsac.ensg.u-nancy.fr, Richard Cognot} writes: @quotation -Try this; you'll still get the function name displayed in the modeline, -but it won't attempt to keep track when you modify the file. To refresh -when it gets out of synch, you simply need click on the @samp{Rescan -Buffer} option in the function-menu. - -@lisp -(setq-default fume-auto-rescan-buffer-p nil) -@end lisp -@end quotation +Because of the way XEmacs (and every other Emacsen, AFAIK) is built. The +link gives you a bare-boned emacs (called temacs). temacs is then run, +preloading some of the lisp files. The result is then dumped into a new +executable, named xemacs, which will contain all of the preloaded lisp +functions and data. -@node Q3.3.5, Q3.4.1, Q3.3.4, Customization -@unnumberedsubsec Q3.3.5: How can one change the modeline color based on the mode used? +Now, during the dump itself, the executable (code+data+symbols) is +written on disk using a special unexec() function. This function is +obviously heavily system dependent. And on some systems, it leads to an +executable which, although valid, cannot be stripped without damage. If +memory serves, this is especially the case for AIX binaries. On other +architectures it might work OK. -You can use something like the following: +The Right Way to strip the emacs binary is to strip temacs prior to +dumping xemacs. This will always work, although you can do that only if +you install from sources (as temacs is @file{not} part of the binary +kits). +@end quotation -@lisp -(add-hook 'lisp-mode-hook - (lambda () - (set-face-background 'modeline "red" (current-buffer)))) -@end lisp +@email{nat@@nataa.fr.eu.org, Nat Makarevitch} writes: -Then, when editing a Lisp file (i.e. when in Lisp mode), the modeline -colors change from the default set in your @file{init.el}/@file{.emacs}. -The change will only be made in the buffer you just entered (which -contains the Lisp file you are editing) and will not affect the modeline -colors anywhere else. +@quotation +Here is the trick: -Notes: +@enumerate +@item +[ ./configure; make ] -@itemize @bullet +@item +rm src/xemacs -@item The hook is the mode name plus @code{-hook}. eg. c-mode-hook, -c++-mode-hook, emacs-lisp-mode-hook (used for your -@file{init.el}/@file{.emacs} or a @file{xx.el} file), -lisp-interaction-mode-hook (the @samp{*scratch*} buffer), -text-mode-hook, etc. +@item +strip src/temacs @item -Be sure to use @code{add-hook}, not @code{(setq c-mode-hook xxxx)}, -otherwise you will erase anything that anybody has already put on the -hook. +make @item -You can also do @code{(set-face-font 'modeline @var{font})}, -eg. @code{(set-face-font 'modeline "*bold-r-normal*140-100-100*" -(current-buffer))} if you wish the modeline font to vary based on the -current mode. -@end itemize +cp src/xemacs /usr/local/bin/xemacs -There are additional modeline faces, @code{modeline-buffer-id}, -@code{modeline-mousable}, and @code{modeline-mousable-minor-mode}, which -you may want to customize. +@item +cp lib-src/DOC-19.16-XEmacs +@iftex +\ @* +@end iftex +/usr/local/lib/xemacs-19.16/i586-unknown-linuxaout +@end enumerate +@end quotation -@node Q3.4.1, Q3.4.2, Q3.3.5, Customization -@unnumberedsec 3.4: Multiple Device Support -@unnumberedsubsec Q3.4.1: How do I open a frame on another screen of my multi-headed display? +@unnumberedsec 2.3: Windows Installation (Windows, Cygwin, MinGW) -Use the command @kbd{M-x make-frame-on-display}. This command is also -on the File menu in the menubar. +@node Q2.3.1, Q2.3.2, Q2.2.2, Installation +@unnumberedsubsec Q2.3.1: What exactly are all the different ways to build XEmacs under Windows? -The command @code{make-frame-on-tty} also exists, which will establish a -connection to any tty-like device. Opening the TTY devices should be -left to @code{gnuclient}, though. +XEmacs can be built in several ways in the MS Windows environment. -@node Q3.4.2, Q3.5.1, Q3.4.1, Customization -@unnumberedsubsec Q3.4.2: Can I really connect to a running XEmacs after calling up over a modem? How? +The standard way is what we call the "native" port. It uses the Win32 +API and has no connection with X whatsoever -- it does not require X +libraries to build, nor does it require an X server to run. The native +port is the most reliable version and provides the best graphical +support. Almost all development is geared towards this version, and +there is little reason not to use it. -Yes. Use @code{gnuclient -nw}. (Prior to 20.3, use the @code{gnuattach} -program supplied with XEmacs instead.) +The second way to build is the Cygwin port. It takes advantage of +Cygnus emulation library under Win32. @xref{Q1.2.5, What are Cygwin +and MinGW, and do I need them to run XEmacs?}, for more information. -Also see @ref{Q5.0.12}. +A third way is the MinGW port. It uses the Cygwin environment to +build but does not require it at runtime. @xref{Q1.2.5, What are +Cygwin and MinGW, and do I need them to run XEmacs?}, for more +information. -@node Q3.5.1, Q3.5.2, Q3.4.2, Customization -@unnumberedsec 3.5: The Keyboard -@unnumberedsubsec Q3.5.1: How can I bind complex functions (or macros) to keys? +Finally, you might also be able to build the non-Cygwin, non-MinGW "X" +port. This was actually the first version of XEmacs that ran under MS +Windows, and although the code is still in XEmacs, it's essentially +orphaned and it's unlikely it will compile without a lot of work. If +you want an MS Windows versin of XEmacs that supports X, use the Cygwin +version. (The X support there is actively maintained, so that Windows +developers can test the X support in XEmacs.) -As an example, say you want the @kbd{paste} key on a Sun keyboard to -insert the current Primary X selection at point. You can accomplish this -with: +@node Q2.3.2, Q2.3.3, Q2.3.1, Installation +@unnumberedsubsec Q2.3.2: What compiler/libraries do I need to compile XEmacs? -@lisp -(define-key global-map [f18] 'x-insert-selection) -@end lisp +You need Visual C++ 4.2, 5.0, or 6.0 for the native version. (We have +some beta testers currently trying to compile with VC.NET, aka version +7.0, but we can't yet report complete success.) For the Cygwin and +MinGW versions, you need the Cygwin environment, which comes with GCC, +the compiler used for those versions. @xref{Q1.2.5, What are Cygwin +and MinGW, and do I need them to run XEmacs?}, for more information on +Cygwin and MinGW. -However, this only works if there is a current X selection (the -selection will be highlighted). The functionality I like is for the -@kbd{paste} key to insert the current X selection if there is one, -otherwise insert the contents of the clipboard. To do this you need to -pass arguments to @code{x-insert-selection}. This is done by wrapping -the call in a 'lambda form: +@node Q2.3.3, Q2.3.4, Q2.3.2, Installation +@unnumberedsubsec Q2.3.3: How do I compile the native port? -@lisp -(global-set-key [f18] - (lambda () (interactive) (x-insert-selection t nil))) -@end lisp +Please read the file @file{nt/README} in the XEmacs distribution, which +contains the full description. -This binds the f18 key to a @dfn{generic} functional object. The -interactive spec is required because only interactive functions can be -bound to keys. +@node Q2.3.4, Q2.3.5, Q2.3.3, Installation +@unnumberedsubsec Q2.3.4: What do I need for Cygwin? -For the FAQ example you could use: +You can find the Cygwin tools and compiler at: -@lisp -(global-set-key [(control ?.)] - (lambda () (interactive) (scroll-up 1))) -(global-set-key [(control ?;)] - (lambda () (interactive) (scroll-up -1))) -@end lisp +@uref{http://www.cygwin.com/} -This is fine if you only need a few functions within the lambda body. -If you're doing more it's cleaner to define a separate function as in -question 3.5.3 (@pxref{Q3.5.3}). +Click on the @samp{Install or update now!} link, which will download a +file @file{setup.exe}, which you can use to download everything +else. (You will need to pick a mirror site; @samp{mirrors.rcn.net} is +probably the best.) You should go ahead and install everything -- +you'll get various ancillary libraries that XEmacs needs or likes, +e.g. XPM, PNG, JPEG, TIFF, etc. You can also get X Windows here, if you +want to compile under X. -@node Q3.5.2, Q3.5.3, Q3.5.1, Customization -@unnumberedsubsec Q3.5.2: How can I stop down-arrow from adding empty lines to the bottom of my buffers? +If you want to compile without X, you will need the @file{xpm-nox} +library, which must be specifically selected in the Cygwin netinstaller; +it is not selected by default. The package has had various names. +Currently it is called @file{cygXpm-noX4.dll}. -Add the following line to your @file{init.el}/@file{.emacs} file: +@node Q2.3.5, Q2.3.6, Q2.3.4, Installation +@unnumberedsubsec Q2.3.5: How do I compile under Cygwin? -@lisp -(setq next-line-add-newlines nil) -@end lisp +Similar as on Unix; use the usual `configure' and `make' process. +Some problems to watch out for: -This has been the default setting in XEmacs for some time. +@itemize @bullet +@item +make sure HOME is set. This controls where you +@file{init.el} file comes from; -@node Q3.5.3, Q3.5.4, Q3.5.2, Customization -@unnumberedsubsec Q3.5.3: How do I bind C-. and C-; to scroll one line up and down? +@item +@samp{CYGWIN} needs to be set to @samp{tty} for process support to work; -Add the following (Thanks to @email{mly@@adoc.xerox.com, Richard Mlynarik} and -@email{wayne@@zen.cac.stratus.com, Wayne Newberry}) to @file{.emacs}: +@item +picking up some other grep or other UNIX-like tools can kill configure; -@lisp -(defun scroll-up-one-line () - (interactive) - (scroll-up 1)) +@item +static heap too small, adjust @file{src/sheap-adjust.h} to a more positive +number; -(defun scroll-down-one-line () - (interactive) - (scroll-down 1)) +@item +(Unconfirmed) The Cygwin version doesn't understand +@file{//machine/path} type paths so you will need to manually mount a +directory of this form under a unix style directory for a build to work +on the directory; -(global-set-key [(control ?.)] 'scroll-up-one-line) ; C-. -(global-set-key [(control ?;)] 'scroll-down-one-line) ; C-; -@end lisp +@item +If you're building @strong{WITHOUT} X11, don't forget to change symlinks +@file{/usr/lib/libXpm.a} and @file{/usr/lib/libXpm.dll.a} to point to +the non-X versions of these libraries. By default they point to the X +versions. So: -The key point is that you can only bind simple functions to keys; you -can not bind a key to a function that you're also passing arguments to. -(@pxref{Q3.5.1} for a better answer). +@example +/usr/lib/libXpm.a -> /usr/lib/libXpm-noX.a +/usr/lib/libXpm.dll.a -> /usr/lib/libXpm-noX.dll.a +@end example -@node Q3.5.4, Q3.5.5, Q3.5.3, Customization -@unnumberedsubsec Q3.5.4: Globally binding @kbd{Delete}? +(This advice may now be obsolete because of the availability of the +cygXpm-noX4.dll package from Cygwin. Send confirmation to +@email{faq@@xemacs.org}.) -I cannot manage to globally bind my @kbd{Delete} key to something other -than the default. How does one do this? +@item +Other problems are listed in the @file{PROBLEMS} file, in the top-level +directory of the XEmacs sources. -Answer: The problem is that many modes explicitly bind @kbd{Delete}. To -get around this, try the following: +@end itemize -@lisp -(defun foo () - (interactive) - (message "You hit DELETE")) -(define-key key-translation-map 'delete 'redirected-delete) -(global-set-key 'redirected-delete 'foo) -@end lisp +@node Q2.3.6, Q2.3.7, Q2.3.5, Installation +@unnumberedsubsec Q2.3.6: How do I compile using MinGW (aka @samp{the -mno-cygwin flag to gcc})? -Also see @ref{Q3.5.10}. +Similar to the method for Unix. Things to remember: -@node Q3.5.5, Q3.5.6, Q3.5.4, Customization -@unnumberedsubsec Q3.5.5: Scrolling one line at a time. +@itemize @bullet +@item +Specify the target host on the command line for @file{./configure}, e.g. +@samp{./configure i586-pc-mingw32}. -Can the cursor keys scroll the screen a line at a time, rather than the -default half page jump? I tend it to find it disorienting. +@item +Be sure that your build directory is mounted such that it has the +same path either as a cygwin path (@file{/build/xemacs}) or as a Windows +path (@file{c:\build\xemacs}). -Try this: +@item +Build @samp{gcc -mno-cygwin} versions of the extra libs, i.e. @file{libpng}, +@file{compface}, etc. -@lisp -(defun scroll-one-line-up (&optional arg) - "Scroll the selected window up (forward in the text) one line (or N lines)." - (interactive "p") - (scroll-up (or arg 1))) - -(defun scroll-one-line-down (&optional arg) - "Scroll the selected window down (backward in the text) one line (or N)." - (interactive "p") - (scroll-down (or arg 1))) +@item +Specify the target location of the extra libs on the command line +to @file{configure}, e.g. +@samp{./configure --site-prefixes=/build/libs i586-pc-mingw32}. +@end itemize -(global-set-key [up] 'scroll-one-line-up) -(global-set-key [down] 'scroll-one-line-down) -@end lisp +@node Q2.3.7, Q2.3.8, Q2.3.6, Installation +@unnumberedsubsec Q2.3.7: How do I compile with X support? -The following will also work but will affect more than just the cursor -keys (i.e. @kbd{C-n} and @kbd{C-p}): +To compile under Cygwin, all you need to do is install XFree86, which +is available as part of the standard Cygwin installation. +@uref{http://www.cygwin.com/}. Once installed, @file{configure} +should automatically find the X libraries and compile with X support. -@lisp -(setq scroll-step 1) -@end lisp +As noted above, the non-Cygwin X support is basically orphaned, and +probably won't work. But if it want to try, it's described in +@file{nt/README} in some detail. Basically, you need to get X11 +libraries from @uref{http://ftp.x.org}, and compile them. If the +precompiled versions are available somewhere, we don't know of it. -Starting with XEmacs-20.3 you can also change this with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Environment->Windows->Scroll Step...} or type -@kbd{M-x customize @key{RET} windows @key{RET}}. +@node Q2.3.8, Q2.4.1, Q2.3.7, Installation +@unnumberedsubsec Q2.3.8: Cygwin XEmacs won't start -- cygXpm-noX4.dll was not found (NEW) -@node Q3.5.6, Q3.5.7, Q3.5.5, Customization -@unnumberedsubsec Q3.5.6: How to map @kbd{Help} key alone on Sun type4 keyboard? +The Cygwin binary distributed with the netinstaller uses an external DLL +to handle XPM images (such as toolbar buttons). You may get an error like -The following works in GNU Emacs 19: +@example +This application has failed to start because cygXpm-noX4.dll was not found. +Re-installing the application may fix this problem. +@end example -@lisp -(global-set-key [help] 'help-command);; Help -@end lisp +Andy Piper <andy@@xemacs.org> sez: -The following works in XEmacs with the addition of shift: +@example +cygXpm-noX4 is part of the cygwin distribution under libraries or +graphics, but is not installed by default. You need to run the +cygwin setup again and select this package. +@end example -@lisp -(global-set-key [(shift help)] 'help-command);; Help -@end lisp +Ie, reinstalling XEmacs won't help because it is not part of the XEmacs +distribution. -But it doesn't work alone. This is in the file @file{PROBLEMS} which -should have come with your XEmacs installation: @emph{Emacs ignores the -@kbd{help} key when running OLWM}. +@unnumberedsec 2.4: General Troubleshooting -OLWM grabs the @kbd{help} key, and retransmits it to the appropriate -client using -@iftex -@* -@end iftex -@code{XSendEvent}. Allowing Emacs to react to synthetic -events is a security hole, so this is turned off by default. You can -enable it by setting the variable @code{x-allow-sendevents} to t. You -can also cause fix this by telling OLWM to not grab the help key, with -the null binding @code{OpenWindows.KeyboardCommand.Help:}. +@node Q2.4.1, Q2.4.2, Q2.3.8, Installation +@unnumberedsubsec Q2.4.1: How do I deal with bugs or with problems building, installing, or running? -@node Q3.5.7, Q3.5.8, Q3.5.6, Customization -@unnumberedsubsec Q3.5.7: How can you type in special characters in XEmacs? -@c Changed -One way is to use the package @code{x-compose}. Then you can use -sequences like @kbd{Compose " a} to get ä, etc. +The file @file{PROBLEMS} contains information on many common problems that +occur in building, installing and running XEmacs. -Another way is to use the @code{iso-insert} package. Then you can use -sequences like @kbd{C-x 8 " a} to get ä, etc. +Reports of bugs in XEmacs should be sent to +@email{xemacs-beta@@xemacs.org}. You can also post to the newsgroup +comp.emacs.xemacs (or equivalentlt, send to the mailing list +@email{xemacs@@xemacs.org}), but it is less likely that the developers +will see it in a timely fashion. @xref{Bugs,,, xemacs, the XEmacs +User's Manual}, for more information on how to report bugs. +@xref{Q1.4.2}, for more information on mailing lists relating to +XEmacs. -@email{glynn@@sensei.co.uk, Glynn Clements} writes: +There are three ways to read the Bugs section. -@quotation -It depends upon your X server. +@enumerate +@item +In a printed copy of the XEmacs manual. -Generally, the simplest way is to define a key as Multi_key with -xmodmap, e.g. -@c hey, show some respect, willya -- there's xkeycaps, isn't there? -- -@c chr ;) +@item +With Info. First, start XEmacs. From the menu, select +@samp{Help->Info (Online Docs)->Info Contents} to enter Info, then +click on @samp{XEmacs}, then on @samp{Bugs}. Or, use the keyboard: do +@kbd{C-h i} to enter Info, then @kbd{m XEmacs RET} to get to the Emacs +manual, then @kbd{m Bugs RET} to get to the section on bugs. Or use +standalone Info in a like manner. (Standalone Info is part of the +Texinfo distribution, not part of the XEmacs distribution.) + +@item +By hand. Do @example - xmodmap -e 'keycode 0xff20 = Multi_key' +cat info/xemacs* | more "+/^File: xemacs.info, Node: Bugs," @end example +@end enumerate -You will need to pick an appropriate keycode. Use xev to find out the -keycodes for each key. +@node Q2.4.2, Q2.4.3, Q2.4.1, Installation +@unnumberedsubsec Q2.4.2: Help! XEmacs just crashed on me! -[NB: On a `Windows' keyboard, recent versions of XFree86 automatically -define the right `Windows' key as Multi_key'.] +First of all, don't panic. Whenever XEmacs crashes, it tries extremely +hard to auto-save all of your files before dying. (The main time that +this will not happen is if the machine physically lost power or if you +killed the XEmacs process using @code{kill -9}). The next time you try +to edit those files, you will be informed that a more recent auto-save +file exists. You can use @kbd{M-x recover-file} to retrieve the +auto-saved version of the file. -Once you have Multi_key defined, you can use e.g. -@example - Multi a ' => á - Multi e " => ë - Multi c , => ç -@end example +You can use the command @kbd{M-x recover-session} after a crash to pick +up where you left off. -etc. +Now, XEmacs is not perfect, and there may occasionally be times, or +particular sequences of actions, that cause it to crash. If you can +come up with a reproducible way of doing this (or even if you have a +pretty good memory of exactly what you were doing at the time), the +maintainers would be very interested in knowing about it. The best +way to report a bug is using @kbd{M-x report-emacs-bug} (or by +selecting @samp{Send Bug Report...} from the Help menu). If that +won't work (e.g. you can't get XEmacs working at all), send ordinary +mail to @email{xemacs-beta@@xemacs.org}. @emph{MAKE SURE} to include +the output from the crash, especially including the Lisp backtrace, as +well as the XEmacs configuration from @kbd{M-x describe-installation} +(or equivalently, the file @file{Installation} in the top of the build +tree). Note that the developers do @emph{not} usually follow +@samp{comp.emacs.xemacs} on a regular basis; thus, this is better for +general questions about XEmacs than bug reports. + +If at all possible, include a C stack backtrace of the core dump that +was produced. This shows where exactly things went wrong, and makes +it much easier to diagnose problems. To do this under Unix and Mac OS +X, you need to locate the core file (it's called @file{core}, and is +usually sitting in the directory that you started XEmacs from, or your +home directory if that other directory was not writable). Then, go to +that directory and execute a command like: -Also, recent versions of XFree86 define various AltGr-<key> -combinations as dead keys, i.e. @example - AltGr [ => dead_diaeresis - AltGr ] => dead_tilde - AltGr ; => dead_acute +gdb `which xemacs` core @end example -etc. -Running @samp{xmodmap -pk} will list all of the defined keysyms. -@end quotation +and then issue the command @samp{where} to get the stack backtrace. You +might have to use @code{dbx} or some similar debugger in place of +@code{gdb}. If you don't have any such debugger available, complain to +your system administrator. -For the related problem of @emph{displaying} non-ASCII characters in a -non-Mule XEmacs, @xref{Q3.2.7}. +It's possible that a core file didn't get produced or the stack trace +from gdb is garbage, in which case you're out of luck unless you can +reproduce the bug. A nonexistent core file can happen in some +circumstances on some operating systems, depending on what exactly +triggered the crash. It's also possible, however, that your limits +are set to turn them off. You may be able to reenable them using a +command like @samp{unlimit coredumpsize} or @samp{ulimit -c}. (To find +out how your limits are set, use the command @samp{limit}.) However, if +you didn't explicitly set your limits this way, go complain to your +system administrator and tell him not to disable core files by +default. + +A garbaged stack trace can happen for various reasons. Some versions +of gdb are broken on certain operating systems and aren't able to read +the core file. It's also possible that the stack got overwritten +during the crash. A very simple reason, however, is that your version +of XEmacs was compiled without debugging information or had the +debugging information stripped. A compilation with optimization can +also result in partly or completely garbaged stack trace. In such +cases, you will need to recompile XEmacs with debugging information +and without optimization; @xref{Q2.4.4, How to debug an XEmacs problem +with a debugger}. Note also that core files currently don't work at +all under Cygwin, and the only way to get a backtrace is to run XEmacs +from gdb. + +If you cannot get a backtrace from the core dump, but can reproduce +the problem, try running XEmacs under gdb. The goal is to get clean C +and Lisp backtraces and submit a bug report including full +configuration information as described above, as this will greatly +assist in the process of tracking down the bug. However, even partial +information is better than none. The process of getting backtraces +from gdb is described in detail in @ref{Q2.4.4, How to debug an XEmacs +problem with a debugger}. -@node Q3.5.8, Q3.5.9, Q3.5.7, Customization -@unnumberedsubsec Q3.5.8: [This question intentionally left blank] +If you're under Microsoft Windows, you're out of luck unless you happen +to have a debugging aid installed on your system, for example Visual +C++. In this case, the crash will result in a message giving you the +option to enter a debugger (for example, by pressing @samp{Cancel}). Do +this and locate the stack-trace window. (If your XEmacs was built +without debugging information, the stack trace may not be very useful.) -Obsolete question, left blank to avoid renumbering. +When making a problem report make sure that: -@node Q3.5.9, Q3.5.10, Q3.5.8, Customization -@unnumberedsubsec Q3.5.9: How do I make the Delete key delete forward? +@enumerate +@item +Report @strong{all} of the information output by XEmacs during the +crash. -With XEmacs-20.2 use the @code{delbs} package: +@item +You mention what O/S and Hardware you are running XEmacs on. -@lisp -(require 'delbs) -@end lisp +@item +What version of XEmacs you are running. -This will give you the functions @code{delbs-enable-delete-forward} to -set things up, and @code{delbs-disable-delete-forward} to revert to -``normal'' behavior. Note that @code{delbackspace} package is obsolete. +@item +What build options you are using. -Starting with XEmacs-20.3 better solution is to set variable -@code{delete-key-deletes-forward} to t. You can also change this with -Customize. Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Editing->Basics->Delete Key Deletes Forward} or -type @kbd{M-x customize @key{RET} editing-basics @key{RET}}. +@item +If the problem is related to graphics and you are running Unix or Mac +OS X, we will also need to know what version of the X Window System +you are running, and what window manager you are using. -Also see @ref{Q3.5.4}. +@item +If the problem happened on a TTY, please include the terminal type. -@node Q3.5.10, Q3.5.11, Q3.5.9, Customization -@unnumberedsubsec Q3.5.10: Can I turn on @dfn{sticky} modifier keys? +@item +Try very hard to get both C and Lisp backtraces, as described above. +@end enumerate -Yes, with @code{(setq modifier-keys-are-sticky t)}. This will give the -effect of being able to press and release Shift and have the next -character typed come out in upper case. This will affect all the other -modifier keys like Control and Meta as well. +Much of the information above is automatically generated by @kbd{M-x +report-emacs-bug}. Even more, and often useful, information can be +generated by redirecting the output of @code{make} and @code{make check} +to a file (@file{beta.err} is the default used by @code{build-report}), +and executing @kbd{M-x build-report}. -@email{ben@@xemacs.org, Ben Wing} writes: -@quotation -One thing about the sticky modifiers is that if you move the mouse out -of the frame and back in, it cancels all currently ``stuck'' modifiers. -@end quotation +@node Q2.4.3, Q2.4.4, Q2.4.2, Installation +@unnumberedsubsec Q2.4.3: XEmacs crashes and I compiled it myself. -@node Q3.5.11, Q3.6.1, Q3.5.10, Customization -@unnumberedsubsec Q3.5.11: How do I map the arrow keys? -@c New -Say you want to map @kbd{C-@key{right}} to forward-word: +There have been a variety of reports of crashes due to compilers with +buggy optimizers. If you are compiling with optimization, consider +turning it off (@pxref{Q2.4.4, How to debug an XEmacs problem with a +debugger}) and recompiling. + +Please see the @file{PROBLEMS} file that comes with XEmacs (it's in +the top-level source directory) to read what it says about your +platform. -@email{sds@@usa.net, Sam Steingold} writes: +If you compiled XEmacs using @samp{--use-union-type} (or the option +@samp{USE_UNION_TYPE} in @file{config.inc} under Windows), try +recompiling again without it. The union type has been known to trigger +compiler errors in a number of cases. -@quotation -@lisp -; both XEmacs and Emacs -(define-key global-map [(control right)] 'forward-word) -@end lisp -or -@lisp -; Emacs only -(define-key global-map [C-right] 'forward-word) -@end lisp -or -@lisp -; ver > 20, both -(define-key global-map (kbd "C-<right>") 'forward-word) -@end lisp -@end quotation +@node Q2.4.4, Q2.4.5, Q2.4.3, Installation +@unnumberedsubsec Q2.4.4: How to debug an XEmacs problem with a debugger +If XEmacs does crash on you, one of the most productive things you can +do to help get the bug fixed is to poke around a bit with the debugger. +Here are some hints: +@itemize @bullet +@item +First of all, if the crash is at all reproducible, consider very +strongly recompiling your XEmacs with debugging symbols and with no +optimization (e.g. with GCC use the compiler flags @samp{-g -O0} -- +that's an "oh" followed by a zero), and with the configure options +@samp{--debug=yes} and @samp{--error-checking=all}. This will make +your XEmacs run somewhat slower, but you are a lot more likely to +catch the problem earlier (closer to its source). It makes it a lot +easier to determine what's going on with a debugger. The way to +control the compiler flags is with the configuration option +@samp{--cflags}. If you have a recent version of 21.5, you should use +@samp{--without-optimization} in preference to directly setting +@samp{--cflags}. -@node Q3.6.1, Q3.6.2, Q3.5.11, Customization -@unnumberedsec 3.6: The Cursor -@unnumberedsubsec Q3.6.1: Is there a way to make the bar cursor thicker? +@item +If it's not a true crash (@emph{i.e.}, XEmacs is hung, or a zombie +process), or it's inconvenient to run XEmacs again because XEmacs is +already running or is running in batch mode as part of a bunch of +scripts, you may be able to attach to the existing process with your +debugger. Under Unix and Mac OS X, the typical way to do this is to +first use some variant of the @samp{ps} command to figure out the +process ID of XEmacs, for example @samp{ps -auxww | grep xemacs} under +a BSD variant, @samp{ps -elf | grep xemacs} under Linux or System V, +or @samp{ps -aW | grep xemacs} under Cygwin. Then run -I'd like to have the bar cursor a little thicker, as I tend to "lose" it -often. +@example +gdb /path/to/xemacs/xemacs #### +@end example -For a 1 pixel bar cursor, use: +Where @code{####} is the process id of your XEmacs. (If you're not +sure, try using @samp{which xemacs}.) When gdb attaches, the xemacs +will stop and you can type @samp{where} in gdb to get a stack trace as +usual. To get things moving again, you can just type @samp{quit} in +gdb. It'll tell you the program is running and ask if you want to +quit anyways. Say @samp{y} and it'll quit and have your emacs +continue from where it was at. + +If you're running another debugger, a similar method may work, or you +may have to run the debugger first and then use the @code{attach} +command or something similar. + +Under Microsoft Windows, use the menu item @samp{Build->Start +Debug->Attach to Process...} and select the XEmacs process from the list +given. -@lisp -(setq bar-cursor t) -@end lisp +@item +If you're able to run XEmacs under a debugger and reproduce the crash, +here are some things you can do: -For a 2 pixel bar cursor, use: +@item +If XEmacs is hitting an assertion failure, put a breakpoint on +@code{assert_failed()}. -@lisp -(setq bar-cursor 'anything-else) -@end lisp +@item +If XEmacs is hitting some weird Lisp error that's causing it to crash +(e.g. during startup), put a breakpoint on @code{signal_1()}---this is +declared static in @file{eval.c}. -Starting with XEmacs-20.3 you can also change these with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Environment->Display->Bar Cursor...} or type -@kbd{M-x customize @key{RET} display @key{RET}}. +@item +If XEmacs is outputting lots of X errors, put a breakpoint on +@code{x_error_handler()}; that will tell you which call is causing +them. Note that the result may not be very useful by default because +X Windows normally operates asynchronously: A bunch of commands are +buffered up and then sent to the server all at once. This greatly +improves performance over a network but means that an error may not be +reported until the server receives the commands, which can be long +after XEmacs made the erroneous calls. For best results, you need to +make the X server synchronous before getting the backtrace. This can +be done by starting XEmacs with the @samp{-sync} option or executing +the Lisp code @code{(x-debug-mode t)}. -You can use a color to make it stand out better: +@item +Internally, you will probably see lots of variables that hold objects of +type @code{Lisp_Object}. These are references to Lisp objects. +Printing them out with the debugger probably won't be too +useful---you'll likely just see a number. To decode them, do this: @example -Emacs*cursorColor: Red +call debug_print (OBJECT) @end example -@node Q3.6.2, Q3.6.3, Q3.6.1, Customization -@unnumberedsubsec Q3.6.2: Is there a way to get back the block cursor? - -@lisp -(setq bar-cursor nil) -@end lisp - -Starting with XEmacs 20.3 you can also change this with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Environment->Display->Bar Cursor...} or type -@kbd{M-x customize @key{RET} display @key{RET}}. +where @var{OBJECT} is whatever you want to decode (it can be a variable, +a function call, etc.). This uses the Lisp printing routines to out a +readable representation on the TTY from which the xemacs process was +invoked. -@node Q3.6.3, Q3.7.1, Q3.6.2, Customization -@unnumberedsubsec Q3.6.3: Can I make the cursor blink? +Under 21.5 and later, @code{dp} is defined as an easier-to-type equivalent +of @code{debug_print}. You can also try @code{dpa} if you can't see +the output from @code{debug_print} (this will return a string containing +the output), or use @code{debug_p3} if @code{debug_print} itself triggers +a crash (this is a less comprehensive but super-safe way to print out +a Lisp object). -Yes, like this: +@item +If you want to get a Lisp backtrace showing the Lisp call +stack, do this: -@lisp -(blink-cursor-mode) -@end lisp +@example +call debug_backtrace () +@end example -This function toggles between a steady cursor and a blinking cursor. -You may also set this mode from the menu bar by selecting @samp{Options -=> Frame Appearance => Blinking Cursor}. Remember to save options. +Under 21.5 and later, @code{db} is defined as an easier-to-type equivalent +of @code{debug_backtrace}. -@node Q3.7.1, Q3.7.2, Q3.6.3, Customization -@unnumberedsec 3.7: The Mouse and Highlighting -@unnumberedsubsec Q3.7.1: How can I turn off Mouse pasting? +@item +Using @code{debug_print} and @code{debug_backtrace} has two +disadvantages - they can only be used with a running (including hung +or zombie) xemacs process, and they do not display the internal C +structure of a Lisp Object. Even if all you've got is a core dump, +all is not lost. -I keep hitting the middle mouse button by accident and getting stuff -pasted into my buffer so how can I turn this off? +If you're using GDB, there are some macros in the file +@file{src/.gdbinit} in the XEmacs source distribution that should make +it easier for you to decode Lisp objects. This file is automatically +read by gdb if gdb is run in the directory where xemacs was built, and +contains these useful macros to inspect the state of xemacs: -Here is an alternative binding, whereby the middle mouse button selects -(but does not cut) the expression under the mouse. Clicking middle on a -left or right paren will select to the matching one. Note that you can -use @code{define-key} or @code{global-set-key}. +@table @code +@item pobj +Usage: pobj lisp_object @* +Print the internal C representation of a lisp object. -@lisp -(defun mouse-set-point-and-select (event) - "Sets the point at the mouse location, then marks following form" - (interactive "@@e") - (mouse-set-point event) - (mark-sexp 1)) -(define-key global-map [button2] 'mouse-set-point-and-select) -@end lisp +@item xtype +Usage: xtype lisp_object @* +Print the Lisp type of a lisp object. -@node Q3.7.2, Q3.7.3, Q3.7.1, Customization -@unnumberedsubsec Q3.7.2: How do I set control/meta/etc modifiers on mouse buttons? +@item lbt +Usage: lbt @* +Print the current Lisp stack trace. +Requires a running xemacs process. (It works by calling the db +routine described above.) -Use, for instance, @code{[(meta button1)]}. For example, here is a common -setting for Common Lisp programmers who use the bundled @code{ilisp} -package, whereby meta-button1 on a function name will find the file where -the function name was defined, and put you at that location in the source -file. +@item ldp +Usage: ldp lisp_object @* +Print a Lisp Object value using the Lisp printer. +Requires a running xemacs process. (It works by calling the dp +routine described above.) -[Inside a function that gets called by the lisp-mode-hook and -ilisp-mode-hook] +@item run-temacs +Usage: run-temacs @* +Run temacs interactively, like xemacs. +Use this with debugging tools (like purify) that cannot deal with dumping, +or when temacs builds successfully, but xemacs does not. -@lisp -(local-set-key [(meta button1)] 'edit-definitions-lisp) -@end lisp +@item dump-temacs +Usage: dump-temacs @* +Run the dumping part of the build procedure. +Use when debugging temacs, not xemacs! +Use this when temacs builds successfully, but xemacs does not. -@node Q3.7.3, Q3.7.4, Q3.7.2, Customization -@unnumberedsubsec Q3.7.3: Clicking the left button does not do anything in buffer list. +@item check-xemacs +Usage: check-xemacs @* +Run the test suite. Equivalent to 'make check'. -I do @kbd{C-x C-b} to get a list of buffers and the entries get -highlighted when I move the mouse over them but clicking the left mouse -does not do anything. +@item check-temacs +Usage: check-temacs @* +Run the test suite on temacs. Equivalent to 'make check-temacs'. +Use this with debugging tools (like purify) that cannot deal with dumping, +or when temacs builds successfully, but xemacs does not. +@end table -Use the middle mouse button. +If you are using Sun's @file{dbx} debugger, there is an equivalent file +@file{src/.dbxrc}, which defines the same commands for dbx. -@node Q3.7.4, Q3.7.5, Q3.7.3, Customization -@unnumberedsubsec Q3.7.4: How can I get a list of buffers when I hit mouse button 3? +@item +If you're using a debugger to get a C stack backtrace and you're seeing +stack traces with some of the innermost frames mangled, it may be due to +dynamic linking. (This happens especially under Linux.) Consider +reconfiguring with @samp{--dynamic=no}. Also, sometimes (again under +Linux), stack backtraces of core dumps will have the frame where the +fatal signal occurred mangled; if you can obtain a stack trace while +running the XEmacs process under a debugger, the stack trace should be +clean. -The following code will replace the default popup on button3: +@email{1CMC3466@@ibm.mtsac.edu, Curtiss} suggests upgrading to ld.so +version 1.8 if dynamic linking and debugging is a problem on Linux. -@lisp -(global-set-key [button3] 'popup-buffer-menu) -@end lisp +@item +If you're using a debugger to get a C stack backtrace and you're +getting a completely mangled and bogus stack trace, it's probably due to +one of the following: -@node Q3.7.5, Q3.7.6, Q3.7.4, Customization -@unnumberedsubsec Q3.7.5: Why does cut-and-paste not work between XEmacs and a cmdtool? +@enumerate a +@item +Your executable has been stripped. Bad news. Tell your sysadmin not to +do this---it doesn't accomplish anything except to save a bit of disk +space, and makes debugging much much harder. -We don't know. It's a bug. There does seem to be a work-around, -however. Try running xclipboard first. It appears to fix the problem -even if you exit it. (This should be mostly fixed in 19.13, but we -haven't yet verified that). +@item +Your stack is getting trashed. Debugging this is hard; you have to do a +binary-search type of narrowing down where the crash occurs, until you +figure out exactly which line is causing the problem. Of course, this +only works if the bug is highly reproducible. Also, in many cases if +you run XEmacs from the debugger, the debugger can protect the stack +somewhat. However, if the stack is being smashed, it is typically the +case that there is a wild pointer somewhere in the program, often quite +far from where the crash occurs. -@node Q3.7.6, Q3.7.7, Q3.7.5, Customization -@unnumberedsubsec Q3.7.6: How I can set XEmacs up so that it pastes where the text cursor is? +@item +If your stack trace has exactly one frame in it, with address 0x0, this +could simply mean that XEmacs attempted to execute code at that address, +e.g. through jumping to a null function pointer. Unfortunately, under +those circumstances, GDB under Linux doesn't know how to get a stack +trace. (Yes, this is the fourth Linux-related problem I've mentioned. I +have no idea why GDB under Linux is so bogus. Complain to the GDB +authors, or to comp.os.linux.development.system.) Again, you'll have to +use the narrowing-down process described above. -By default XEmacs pastes X selections where the mouse pointer is. How -do I disable this? +@item +You will get a Lisp backtrace output when XEmacs crashes, so you'll have +something useful. -Examine the function @code{mouse-yank}, by typing @kbd{C-h f mouse-yank -@key{RET}}. +@end enumerate -To get XEmacs to paste at the text cursor, add this your @file{init.el}/@file{.emacs}: +@item +If you compile with the newer gcc variants gcc-2.8 or egcs, you will +also need gdb 4.17 or above. Earlier releases of gdb can't handle the +debug information generated by the newer compilers. -@lisp -(setq mouse-yank-at-point t) -@end lisp +@item +In versions of XEmacs before 21.2.27, @file{src/.gdbinit} was named +@file{src/gdbinit}. This had the disadvantage of not being sourced +automatically by gdb, so you had to set that up yourself. -Starting with XEmacs-20.2 you can also change this with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Editing->Mouse->Yank At Point...} or type -@kbd{M-x customize @key{RET} mouse @key{RET}}. +@item +If you are running Microsoft Windows, the the file @file{nt/README} for +further information about debugging XEmacs. -@node Q3.7.7, Q3.7.8, Q3.7.6, Customization -@unnumberedsubsec Q3.7.7: How do I select a rectangular region? +@end itemize -Just select the region normally, then use the rectangle commands (e.g. -@code{kill-rectangle} on it. The region does not highlight as a -rectangle, but the commands work just fine. +@node Q2.4.5, Q2.4.6, Q2.4.4, Installation +@unnumberedsubsec Q2.4.5: I get a cryptic error message when trying to do something. -To actually sweep out rectangular regions with the mouse you can use -@code{mouse-track-do-rectangle} which is assigned to @kbd{M-button1}. -Then use rectangle commands. +When I try to use some particular option of some particular package, I +get a cryptic error message in the minibuffer. -You can also do the following to change default behavior to sweep out -rectangular regions: +If the message went by too quickly, use @samp{Help->Recent Messages} +from the menubar (or type @kbd{C-h l}) to see recent messages. -@lisp -(setq mouse-track-rectangle-p t) -@end lisp +If you can't figure out what's going on, select +@samp{Options->Troubleshooting->Debug on Error} from the menubar (or +type @kbd{M-:} then @kbd{(setq debug-on-error t)}) then try and make +the error happen again. This will put in the debugger (you can get +out of this and continue what you were doing before by typing @kbd{c}) +and give you a backtrace that may be enlightening. If not, try +reading through this FAQ; if that fails, you could try posting to +@samp{comp.emacs.xemacs} (making sure to include the backtrace) and +someone may be able to help. If you can identify which XEmacs Lisp +source file the error is coming from you can get a more detailed stack +backtrace by doing the following: -Starting with XEmacs-20.2 you can also change this with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Editing->Mouse->Track Rectangle...} or type -@kbd{M-x customize @key{RET} mouse @key{RET}}. +@enumerate +@item +Visit the .el file in an XEmacs buffer. +@item +Issue the command @kbd{M-x eval-current-buffer}. -@example - mouse-track-do-rectangle: (event) - -- an interactive compiled Lisp function. - Like `mouse-track' but selects rectangles instead of regions. -@end example +@item +Reproduce the error. +@end enumerate -@node Q3.7.8, Q3.8.1, Q3.7.7, Customization -@unnumberedsubsec Q3.7.8: Why does @kbd{M-w} take so long? +For more information on debugging Lisp code, @xref{Debugging,,, +lispref, XEmacs Lisp Reference Manual}. -It actually doesn't. It leaves the region visible for a second so that -you can see what area is being yanked. If you start working, though, it -will immediately complete its operation. In other words, it will only -delay for a second if you let it. +@node Q2.4.6, Q2.4.7, Q2.4.5, Installation +@unnumberedsubsec Q2.4.6: XEmacs hangs when I try to do something. -@node Q3.8.1, Q3.8.2, Q3.7.8, Customization -@unnumberedsec 3.8: The Menubar and Toolbar -@unnumberedsubsec Q3.8.1: How do I get rid of the menu (or menubar)? +XEmacs might just be slow; some operations take a long time. XEmacs +may also be waiting on a response from the network, for example when +you are trying to send mail. + +You can usually interrupt XEmacs by typing @kbd{C-g}. If not (for +example, Lisp code explicitly disabled this by setting +@code{inhibit-quit}), you can use the "critical quit" mechanism by +typing @kbd{Control-Shift-G}. This should also pop you into the +debugger and give you a backtrace, which can tell you where the +problem is (@pxref{Q2.4.4, How to debug an XEmacs problem with a +debugger}). (Note that setting @code{debug-on-quit} or selecting +@samp{Options->Troubleshooting->Debug on Quit} will also cause regular +@kbd{C-g} to enter the debugger and give you a backtrace.) + +If you can't interrupt XEmacs this way, or for some reason XEmacs is +not talking to the keyboard, you can try sending the @samp{SIGINT} +signal using the @samp{kill} command. + +If the Lisp backtrace isn't enlightening, or if XEmacs is so hung that +you can't interrupt it at all, you could try attaching to the process +and getting a C stack backtrace. @xref{Q2.4.4, How to debug an XEmacs +problem with a debugger}. + +@node Q2.4.7, Q2.4.8, Q2.4.6, Installation +@unnumberedsubsec Q2.4.7: I get an error message when XEmacs is running in batch mode. + +Typically this happens when you are trying to compile some Elisp code. +If you are doing this as part of XEmacs or the XEmacs packages, you +should automatically get a backtrace, which can help you determine the +source of the problem. In other cases, you can get equivalent results +by setting the environment variable @samp{XEMACSDEBUG} to @samp{(setq +stack-trace-on-error t load-always-display-messages t +load-ignore-out-of-date-elc-files t load-show-full-path-in-messages +t)} (this needs to be all on one line; to set an environment variable, +use @samp{export XEMACSDEBUG='FOO'} under @samp{bash}, @samp{zsh}, +etc. or @samp{setenv XEMACSDEBUG 'FOO'} under @samp{csh} and +@samp{tcsh}). @samp{XEMACSDEBUG} specifies Lisp code that will be +executed at startup time. + +If the backtrace is not sufficiently useful in helping you diagnose +the problem, you should consider using a debugger such as GDB. +@xref{Q2.4.4, How to debug an XEmacs problem with a debugger}. You +probably want to set a breakpoint on @code{signal_1}. Since such +errors often occur during compiling, which is often triggered by a +complex command run from a make suite, it may be easier to attach to +the process once it's running. + +Under Microsoft Windows (and perhaps other operating systems), there +is another useful trick you can do if you have configured with +debugging support (configure option @samp{--debug} or setting +@samp{DEBUG_XEMACS} in @file{nt/config.inc}). Set the environment +variable @samp{XEMACSDEBUG} (as described above) to @samp{(setq +debug-on-error t)}. Then, when an error occurs noninteractively, +instead of trying to invoke the Lisp debugger (which obviously won't +work), XEmacs will break out to a C debugger using +@code{(force-debugging-signal t)}. @emph{NOTE}: This runs +@code{abort()}!!! (As well as and after executing INT 3 under MS +Windows, which should invoke a debugger if it's active.) This is +guaranteed to kill XEmacs! (But in this situation, XEmacs is about to +die anyway, and if no debugger is present, this will usefully dump +core.) + +@node Q2.4.8, Q2.4.9, Q2.4.7, Installation +@unnumberedsubsec Q2.4.8: The keyboard or mouse is not working properly, or I have some other event-related problem. + +XEmacs has various facilities for debugging event handling. + +First, try setting the variable @code{debug-emacs-events} to non-zero. +This will output various information showing which events are being +received and how they are being translated. This may show you, for +example, that a key command is getting intercepted using +@code{key-translation-map}; this problem can otherwise be very tricky +to debug. + +Under X, you can see exactly which events are being received from the +window system by setting @code{x-debug-events} to non-zero. (The value +@samp{1} gives you regular output, and @samp{2} gives you verbose +output, including all parameters.) + +A similar facility exists under MS Windows: Set +@code{debug-mswindows-events} to non-zero. (The value @samp{1} gives +you regular output. The value @samp{2} gives you verbose output, +including all parameters. The value @samp{3} gives you +super-gorily-detailed output.) -@c If you are running XEmacs 19.13 or earlier, add this command to your -@c @file{init.el}/@file{.emacs}. -@c -@c @lisp -@c (set-menubar nil) -@c @end lisp -@c -@c Starting with XEmacs 19.14 the preferred method is: -@c -@lisp -(set-specifier menubar-visible-p nil) -@end lisp +@node Q2.4.9, Q2.4.10, Q2.4.8, Installation +@unnumberedsubsec Q2.4.9: @kbd{C-g} doesn't work for me. Is it broken? -@node Q3.8.2, Q3.8.3, Q3.8.1, Customization -@unnumberedsubsec Q3.8.2: Can I customize the basic menubar? +@kbd{C-g} does work for most people in most circumstances. If it +doesn't, there are two possible explanations: -For an extensive menubar, add this line to your @file{init.el}/@file{.emacs}: +@enumerate +@item +XEmacs is hung in a way that prevents @kbd{C-g} from working. This +can happen when code is wrapped with a binding of @code{inhibit-quit} +to @code{t}; you should still be able interrupt XEmacs using "critical +quit". On the other hand, XEmacs may be seriously wedged. (If you're +lucky, sending @samp{SIGINT} to the XEmacs process will interrupt it.) +@xref{Q2.4.6, XEmacs hangs when I try to do something.}. -@lisp -(load "big-menubar") -@end lisp +@item +@kbd{C-g} is indeed broken on your system. To test, try executing +@code{(while t)} from the @samp{*scratch*} buffer. If @kbd{C-g} +doesn't interrupt, then it's broken. This used to happen with systems +where @samp{SIGIO} was broken, but @samp{BROKEN_SIGIO} wasn't defined. +However, there may not be very many such systems nowadays. +@end enumerate -If you'd like to write your own, this file provides as good a set of -examples as any to start from. The file is located in edit-utils -package. +@node Q2.4.10, Q2.4.11, Q2.4.9, Installation +@unnumberedsubsec Q2.4.10: How do I debug process-related problems? -@node Q3.8.3, Q3.8.4, Q3.8.2, Customization -@unnumberedsubsec Q3.8.3: How do I control how many buffers are listed in the menu @code{Buffers List}? +Under MS Windows, you can set the variable +@code{debug-mswindows-process-command-lines} to non-@samp{nil} to get +information on exactly what is getting passed to a process. This can +be useful in determining problems with quoting. (Under Unix, a process +receives each argument separately, but under MS Windows a single +command line is received, and arguments with spaces or other special +characters in them must be quoted. Unfortunately this means that each +process, potentially at least, has its own quoting conventions, and +the code to process quoting conventions in @file{cmd.exe}, the Visual +C++ startup code and the like is baroque and poorly documented. +XEmacs uses the variable +@code{mswindows-construct-process-command-line-alist} to construct a +command line from a list of arguments based on the command to be run, +but it is (and cannot be) a perfect solution.) -Add the following to your @file{init.el}/@file{.emacs} (suit to fit): +@node Q2.4.11, Q2.4.12, Q2.4.10, Installation +@unnumberedsubsec Q2.4.11: XEmacs is outputting lots of X errors. -@lisp -(setq buffers-menu-max-size 20) -@end lisp +If this is happening, we would very much like to know what's causing +them. To find this out, see @ref{Q2.4.4, How to debug an XEmacs +problem with a debugger}. Try to get both a C and Lisp backtrace, and +send them along with the full error output to +@email{xemacs-beta@@xemacs.org}. + +@node Q2.4.12, Q2.5.1, Q2.4.11, Installation +@unnumberedsubsec Q2.4.12: After upgrading, XEmacs won't do `foo' any more! + +You have been used to doing `foo', but now when you invoke it (or +click the toolbar button or select the menu item), nothing (or an +error) happens. The simplest explanation is that you are missing a +package that is essential to you. You can either track it down and +install it (there is a list of packages and brief descriptions of +their contents in @file{etc/PACKAGES}), or install the `Sumo Tarball' +(@pxref{Q2.1.2, How do I figure out which packages to install?}). -For no limit, use an argument of @samp{nil}. +@c #### should xref to XEmacs manual here -Starting with XEmacs-20.3 you can also change this with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Environment->Menu->Buffers Menu->Max Size...} or -type @kbd{M-x customize @key{RET} buffers-menu @key{RET}}. +@unnumberedsec 2.5: Startup-Related Problems -@node Q3.8.4, Q3.8.5, Q3.8.3, Customization -@unnumberedsubsec Q3.8.4: Resources like @code{Emacs*menubar*font} are not working? +@node Q2.5.1, Q2.5.2, Q2.4.12, Installation +@unnumberedsubsec Q2.5.1: XEmacs cannot connect to my X Terminal! -I am trying to use a resource like @code{Emacs*menubar*font} to set the -font of the menubar but it's not working. +Help! I can not get XEmacs to display on my Envizex X-terminal! -In Motif, the use of @samp{font} resources is obsoleted in order to -support internationalization. If you are using the real Motif menubar, -this resource is not recognized at all; you have to say: +Try setting the @code{DISPLAY} variable using the numeric IP address of +the host you are running XEmacs from. -@example -Emacs*menubar*fontList: FONT -@end example +@node Q2.5.2, Q2.5.3, Q2.5.1, Installation +@unnumberedsubsec Q2.5.2 Startup problems related to paths or package locations. -If you are using the Lucid menubar, for backward compatibility with -existing user configurations, the @samp{font} resource is recognized. -Since this is not supported by Motif itself, the code is a kludge and -the @samp{font} resource will be recognized only if the @samp{fontList} -resource resource is unset. This means that the resource +First of all, if XEmacs can't find the packages, check to make sure +that you put the packages in the right place, or that you told XEmacs +where to look for the packages when you compiled it. @xref{Q2.1.1}. + +If something is still going wrong, or you get a startup warning about +not being able to deduce some paths, you can get detailed information +on the path-searching process at startup by setting the environment +variable @samp{EMACSDEBUGPATHS} to a non-null value. One thing to +look for if you're having package problems is the value of +@samp{configure-package-path}. This corresponds to what was compiled +into XEmacs using the @samp{--package-prefix} or @samp{--package-path} +parameter (@pxref{Q2.1.1}). If this has the value of @samp{nil}, +this means that no value was compiled into XEmacs using these parameters. -@example -*fontList: FONT -@end example +@node Q2.5.3, Q2.5.4, Q2.5.2, Installation +@unnumberedsubsec Q2.5.3: XEmacs won't start without network. -will override +If XEmacs starts when you're on the network, but fails when you're not +on the network, you may be missing a "localhost" entry in your +@file{/etc/hosts} file. The file should contain an entry like: @example -Emacs*menubar*font: FONT +127.0.0.1 localhost @end example -even though the latter is more specific. +Add that line, and XEmacs will be happy. -In non-Motif configurations using @samp{--with-mule} and -@samp{--with-xfs} it @emph{is} necessary to use the @code{fontSet} -resource @emph{instead of} the @code{font} resource. The backward -compatibility kludge was never implemented for non-Motif builds. -Example: +@node Q2.5.4, Q2.5.5, Q2.5.3, Installation +@unnumberedsubsec Q2.5.4: Startup warnings about deducing proper fonts? -@example -*fontSet: FONT -@end example +How can I avoid the startup warnings about deducing proper fonts? -@node Q3.8.5, Q3.9.1, Q3.8.4, Customization -@unnumberedsubsec Q3.8.5: How can I bind a key to a function to toggle the toolbar? +This is highly dependent on your installation, but try with the +following font as your base font for XEmacs and see what it does: -Try something like: +@format +-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1 +@end format + +More precisely, do the following in your resource file: + +@format +Emacs.default.attributeFont: \ +-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1 +@end format + +If you just don't want to see the @samp{*Warnings*} buffer at startup +time, you can set this: @lisp -(defun my-toggle-toolbar () - (interactive) - (set-specifier default-toolbar-visible-p - (not (specifier-instance default-toolbar-visible-p)))) -(global-set-key "\C-xT" 'my-toggle-toolbar) +(setq display-warning-minimum-level 'error) @end lisp -There are redisplay bugs in 19.14 that may make the preceding result in -a messed-up display, especially for frames with multiple windows. You -may need to resize the frame before XEmacs completely realizes the -toolbar is really gone. +The buffer still exists; it just isn't in your face. -Thanks to @email{martin@@xemacs.org, Martin Buchholz} for the correct -code. +@node Q2.5.5, Q2.5.6, Q2.5.4, Installation +@unnumberedsubsec Q2.5.5: Warnings from incorrect key modifiers. -@node Q3.9.1, Q3.9.2, Q3.8.5, Customization -@unnumberedsec 3.9: Scrollbars -@unnumberedsubsec Q3.9.1: How can I disable the scrollbar? +The following information comes from the @file{PROBLEMS} file that comes +with XEmacs. -To disable them for all frames, add the following line to -your @file{.Xresources}: +If you're having troubles with HP/UX it is because HP/UX defines the +modifiers wrong in X. Here is a shell script to fix the problem; be +sure that it is run after VUE configures the X server. @example -Emacs.scrollBarWidth: 0 +#! /bin/sh +xmodmap 2> /dev/null - << EOF +keysym Alt_L = Meta_L +keysym Alt_R = Meta_R +EOF + +xmodmap - << EOF +clear mod1 +keysym Mode_switch = NoSymbol +add mod1 = Meta_L +keysym Meta_R = Mode_switch +add mod2 = Mode_switch +EOF @end example -Or select from the @code{Options} menu @code{Frame Appearance->Scrollbars}. -Remember to save options. +@node Q2.5.6, , Q2.5.5, Installation +@unnumberedsubsec Q2.5.6: XEmacs 21.1 on Windows used to spawn an ugly console window on every startup. Has that been fixed? -To turn the scrollbar off on a per-frame basis, use the following -function: +Yes. -@lisp -(set-specifier scrollbar-width 0 (selected-frame)) -@end lisp +The console was there because @file{temacs} (and in turn, @file{xemacs}) +was a console application, and Windows typically creates a new +console for a console process unless the creating process requests that +one isn't created. This used to be fixed with @file{runemacs}, a small +Windows application that existed merely to start @file{xemacs}, stating +that it didn't want a console. -You can actually turn the scrollbars on at any level you want by -substituting for (selected-frame) in the above command. For example, to -turn the scrollbars off only in a single buffer: +XEmacs 21.4 fixes this cleanly by the virtue of being a true "GUI" +application. The explanation of what that means is included for +educational value. -@lisp -(set-specifier scrollbar-width 0 (current-buffer)) -@end lisp -@c -@c In XEmacs versions prior to 19.14, you had to use the hairier construct: -@c -@c @lisp -@c (set-specifier scrollbar-width (cons (selected-frame) 0)) -@c @end lisp +When building an application to be run in a Win32 environment, you must +state which sub-system it is to run in. Valid subsystems include +"console" and "gui". The subsystem you use affects the run time +libraries linked into your application, the start up function that is +run before control is handed over to your application, the entry point +to your program, and how Windows normally invokes your program. (Console +programs automatically get a console created for them at startup if +their stdin/stdout don't point anywhere useful, which is the case when +run from the GUI. This is a stupid design, of course -- instead, the +console should get created only when the first I/O actually occurs! +GUI programs have an equally stupid design: When called from +@file{CMD.EXE}/@file{COMMAND.COM}, their stdin/stdout will be set to +point nowhere useful, even though the command shell has its own +stdin/stdout. It's as if someone who had learned a bit about stdio but +had no actual knowledge of interprocess communication designed the +scheme; unfortunately, the whole process-communication aspect of the +Win32 API is equally badly designed.) For example, the entry point for a +console app is "main" (which is what you'd expect for a C/C++ program), +but the entry point for a "gui" app is "WinMain". This confuses and +annoys a lot of programmers who've grown up on Unix systems, where the +kernel doesn't really care whether your application is a gui program or +not. -@node Q3.9.2, Q3.9.3, Q3.9.1, Customization -@unnumberedsubsec Q3.9.2: How can one use resources to change scrollbar colors? +For reasons not altogether clear, and are lost in the mists of time and +tradition, XEmacs on Win32 started out as a console application, and +therefore a console was automatically created for it. (It may have been +made a console application partly because a console is needed in some +circumstances, especially under Win95, to interrupt, terminate, or send +signals to a child process, and because of the bogosity mentioned above +with GUI programs and the standard command shell. Currently, XEmacs +just creates and immediately hides a console when necessary, and +works around the "no useful stdio" problem by creating its own console +window as necessary to display messages in.) -Here's a recap of how to use resources to change your scrollbar colors: +@node Editing, Display, Installation, Top +@unnumbered 3 Editing Functions -@example -! Motif scrollbars +This is part 3 of the XEmacs Frequently Asked Questions list. This +section is devoted to the editing-related capabilities of XEmacs (the +keyboard, mouse, buffers, text selections, etc.) and how to customize +them. -Emacs*XmScrollBar.Background: skyblue -Emacs*XmScrollBar.troughColor: lightgray +@menu +3.0: The Keyboard +* Q3.0.1:: How can I customize the keyboard? +* Q3.0.2:: How can I bind complex functions (or macros) to keys? +* Q3.0.3:: How do I bind C-. and C-; to scroll one line up and down? +* Q3.0.4:: Globally binding @kbd{Delete}? +* Q3.0.5:: How to map @kbd{Help} key alone on Sun type4 keyboard? +* Q3.0.6:: How can you type in special characters in XEmacs? +* Q3.0.7:: Can I turn on @dfn{sticky} modifier keys? +* Q3.0.8:: How do I map the arrow keys? +* Q3.0.9:: HP Alt key as Meta. +* Q3.0.10:: Why does edt emulation not work? +* Q3.0.11:: How can I emulate VI and use it as my default mode? + +3.1: The Mouse +* Q3.1.1:: How can I turn off Mouse pasting? +* Q3.1.2:: How do I set control/meta/etc modifiers on mouse buttons? +* Q3.1.3:: Clicking the left button does not do anything in buffer list. +* Q3.1.4:: How can I get a list of buffers when I hit mouse button 3? +* Q3.1.5:: How can I set XEmacs up so that it pastes where the text cursor is? + +3.2: Buffers, Text Editing +* Q3.2.1:: Can I have the end of the buffer delimited in some way? +* Q3.2.2:: How do I insert today's date into a buffer? +* Q3.2.3:: How do I get a single minibuffer frame? +* Q3.2.4:: How can I enable auto-indent and/or Filladapt? +* Q3.2.5:: How can I get XEmacs to come up in text/auto-fill mode by default? + +3.3: Text Selections +* Q3.3.1:: How do I select a rectangular region? +* Q3.3.2:: How can I turn off or change highlighted selections? +* Q3.3.3:: How do I cause typing on an active region to remove it? +* Q3.3.4:: Can I turn off the highlight during isearch? +* Q3.3.5:: Why is killing so slow? +* Q3.3.6:: Why does @kbd{M-w} take so long? + +3.4: Editing Source Code +* Q3.4.1:: I do not like cc-mode. How do I use the old c-mode? +* Q3.4.2:: How do you make XEmacs indent CL if-clauses correctly? +@end menu -! Athena scrollbars +@unnumberedsec 3.0: The Keyboard -Emacs*Scrollbar.Foreground: skyblue -Emacs*Scrollbar.Background: lightgray -@end example +@node Q3.0.1, Q3.0.2, Editing, Editing +@unnumberedsubsec Q3.0.1: How can I customize the keyboard? -Note the capitalization of @code{Scrollbar} for the Athena widget. +#### Write me. -@node Q3.9.3, Q3.9.4, Q3.9.2, Customization -@unnumberedsubsec Q3.9.3: Moving the scrollbar can move the point; can I disable this? +@node Q3.0.2, Q3.0.3, Q3.0.1, Editing +@unnumberedsubsec Q3.0.2: How can I bind complex functions (or macros) to keys? -When I move the scrollbar in an XEmacs window, it moves the point as -well, which should not be the default behavior. Is this a bug or a -feature? Can I disable it? +As an example, say you want the @kbd{paste} key on a Sun keyboard to +insert the current Primary X selection at point. You can accomplish this +with: -The current behavior is a feature, not a bug. Point remains at the same -buffer position as long as that position does not scroll off the screen. -In that event, point will end up in either the upper-left or lower-left -hand corner. +@lisp +(define-key global-map [f18] 'x-insert-selection) +@end lisp -This cannot be changed. +However, this only works if there is a current X selection (the +selection will be highlighted). The functionality I like is for the +@kbd{paste} key to insert the current X selection if there is one, +otherwise insert the contents of the clipboard. To do this you need to +pass arguments to @code{x-insert-selection}. This is done by wrapping +the call in a 'lambda form: -@node Q3.9.4, Q3.10.1, Q3.9.3, Customization -@unnumberedsubsec Q3.9.4: How can I turn off automatic horizontal scrolling in specific modes? +@lisp +(global-set-key [f18] + (lambda () (interactive) (x-insert-selection t nil))) +@end lisp -Do @code{(setq truncate-lines t)} in the mode-hooks for any modes -in which you want lines truncated. +This binds the f18 key to a @dfn{generic} functional object. The +interactive spec is required because only interactive functions can be +bound to keys. -More precisely: If @code{truncate-lines} is nil, horizontal scrollbars -will never appear. Otherwise, they will appear only if the value of -@code{scrollbar-height} for that buffer/window/etc. is non-zero. If you -do +For the FAQ example you could use: @lisp -(set-specifier scrollbar-height 0) +(global-set-key [(control ?.)] + (lambda () (interactive) (scroll-up 1))) +(global-set-key [(control ?;)] + (lambda () (interactive) (scroll-up -1))) @end lisp -then horizontal scrollbars will not appear in truncated buffers unless -the package specifically asked for them. +This is fine if you only need a few functions within the lambda body. +If you're doing more it's cleaner to define a separate function. +@xref{Q3.0.3, How do I bind C-. and C-; to scroll one line up and +down?}. -@node Q3.10.1, Q3.10.2, Q3.9.4, Customization -@unnumberedsec 3.10: Text Selections -@unnumberedsubsec Q3.10.1: How can I turn off or change highlighted selections? +@node Q3.0.3, Q3.0.4, Q3.0.2, Editing +@unnumberedsubsec Q3.0.3: How do I bind C-. and C-; to scroll one line up and down? -The @code{zmacs} mode allows for what some might call gratuitous -highlighting for selected regions (either by setting mark or by using -the mouse). This is the default behavior. To turn off, add the -following line to your @file{init.el}/@file{.emacs} file: +Add the following (Thanks to @email{mly@@adoc.xerox.com, Richard Mlynarik} and +@email{wayne@@zen.cac.stratus.com, Wayne Newberry}) to @file{.emacs}: @lisp -(setq zmacs-regions nil) -@end lisp +(defun scroll-up-one-line () + (interactive) + (scroll-up 1)) -Starting with XEmacs-20.2 you can also change this with Customize. Select -from the @code{Options} menu @code{Advanced (Customize)->Emacs->Editing->Basics->Zmacs -Regions} or type @kbd{M-x customize @key{RET} editing-basics @key{RET}}. +(defun scroll-down-one-line () + (interactive) + (scroll-down 1)) -To change the face for selection, look at @code{Options->Customize} on -the menubar. +(global-set-key [(control ?.)] 'scroll-up-one-line) ; C-. +(global-set-key [(control ?;)] 'scroll-down-one-line) ; C-; +@end lisp -@node Q3.10.2, Q3.10.3, Q3.10.1, Customization -@unnumberedsubsec Q3.10.2: How do I get that typing on an active region removes it? +The key point is that you can only bind simple functions to keys; you +can not bind a key to a function that you're also passing arguments +to. (@pxref{Q3.0.2, How can I bind complex functions (or macros) to +keys?} for a better answer). -I want to change things so that if I select some text and start typing, -the typed text replaces the selected text, similar to Motif. +@node Q3.0.4, Q3.0.5, Q3.0.3, Editing +@unnumberedsubsec Q3.0.4: Globally binding @kbd{Delete}? -You want to use something called @dfn{pending delete}. Pending delete -is what happens when you select a region (with the mouse or keyboard) -and you press a key to replace the selected region by the key you typed. -Usually backspace kills the selected region. +I cannot manage to globally bind my @kbd{Delete} key to something other +than the default. How does one do this? -To get this behavior, ensure that you have the @file{pc} package -installed, and add the following lines to your -@file{init.el}/@file{.emacs}: +Answer: The problem is that many modes explicitly bind @kbd{Delete}. To +get around this, try the following: @lisp -(cond - ((fboundp 'turn-on-pending-delete) - (turn-on-pending-delete)) - ((fboundp 'pending-delete-on) - (pending-delete-on t))) +(defun foo () + (interactive) + (message "You hit DELETE")) + +(define-key key-translation-map 'delete 'redirected-delete) +(global-set-key 'redirected-delete 'foo) @end lisp -Note that this will work with both Backspace and Delete. This code is a -tad more complicated than it has to be for XEmacs in order to make it -more portable. +@node Q3.0.5, Q3.0.6, Q3.0.4, Editing +@unnumberedsubsec Q3.0.5: How to map @kbd{Help} key alone on Sun type4 keyboard? -@node Q3.10.3, Q3.10.4, Q3.10.2, Customization -@unnumberedsubsec Q3.10.3: Can I turn off the highlight during isearch? +The following works in GNU Emacs 19: -I do not like my text highlighted while I am doing isearch as I am not -able to see what's underneath. How do I turn it off? +@lisp +(global-set-key [help] 'help-command);; Help +@end lisp -Put the following in your @file{init.el}/@file{.emacs}: +The following works in XEmacs with the addition of shift: @lisp -(setq isearch-highlight nil) +(global-set-key [(shift help)] 'help-command);; Help @end lisp -Starting with XEmacs-20.2 you can also change this with Customize. Type -@kbd{M-x customize-variable @key{RET} isearch-highlight @key{RET}}. +But it doesn't work alone. This is in the file @file{PROBLEMS} which +should have come with your XEmacs installation: @emph{Emacs ignores the +@kbd{help} key when running OLWM}. -Note also that isearch-highlight affects query-replace and ispell. -Instead of disabling isearch-highlight you may find that a better -solution consists of customizing the @code{isearch} face. +OLWM grabs the @kbd{help} key, and retransmits it to the appropriate +client using +@iftex +@* +@end iftex +@code{XSendEvent}. Allowing Emacs to react to synthetic +events is a security hole, so this is turned off by default. You can +enable it by setting the variable @code{x-allow-sendevents} to t. You +can also cause fix this by telling OLWM to not grab the help key, with +the null binding @code{OpenWindows.KeyboardCommand.Help:}. -@node Q3.10.4, Q3.10.5, Q3.10.3, Customization -@unnumberedsubsec Q3.10.4: How do I turn off highlighting after @kbd{C-x C-p} (mark-page)? +@node Q3.0.6, Q3.0.7, Q3.0.5, Editing +@unnumberedsubsec Q3.0.6: How can you type in special characters in XEmacs? +One way is to use the package @code{x-compose}. Then you can use +sequences like @kbd{Compose " a} to get ä, etc. -Put this in your @code{.emacs}: +Another way is to use the @code{iso-insert} package. Then you can use +sequences like @kbd{C-x 8 " a} to get ä, etc. -@lisp -(setq zmacs-regions nil) -@end lisp +@email{glynn@@sensei.co.uk, Glynn Clements} writes: -@strong{Warning: This command turns off all region highlighting.} +@quotation +It depends upon your X server. -Also see @ref{Q3.10.1}. +Generally, the simplest way is to define a key as Multi_key with +xmodmap, e.g. +@c hey, show some respect, willya -- there's xkeycaps, isn't there? -- +@c chr ;) +@example + xmodmap -e 'keycode 0xff20 = Multi_key' +@end example -@node Q3.10.5, Q3.10.6, Q3.10.4, Customization -@unnumberedsubsec Q3.10.5: The region disappears when I hit the end of buffer while scrolling. +You will need to pick an appropriate keycode. Use xev to find out the +keycodes for each key. -This has been fixed by default starting with XEmacs-20.3. +[NB: On a `Windows' keyboard, recent versions of XFree86 automatically +define the right `Windows' key as Multi_key'.] -With older versions you can turn this feature (if it indeed is a feature) -off like this: +Once you have Multi_key defined, you can use e.g. +@example + Multi a ' => á + Multi e " => ë + Multi c , => ç +@end example -@lisp -(defadvice scroll-up (around scroll-up freeze) - (interactive "_P") - (let ((zmacs-region-stays t)) - (if (interactive-p) - (condition-case nil - ad-do-it - (end-of-buffer (goto-char (point-max)))) - ad-do-it))) +etc. -(defadvice scroll-down (around scroll-down freeze) - (interactive "_P") - (let ((zmacs-region-stays t)) - (if (interactive-p) - (condition-case nil - ad-do-it - (beginning-of-buffer (goto-char (point-min)))) - ad-do-it))) -@end lisp +Also, recent versions of XFree86 define various AltGr-<key> +combinations as dead keys, i.e. +@example + AltGr [ => dead_diaeresis + AltGr ] => dead_tilde + AltGr ; => dead_acute +@end example +etc. -Thanks to @email{raman@@adobe.com, T. V. Raman} for assistance in deriving this -answer. +Running @samp{xmodmap -pk} will list all of the defined keysyms. +@end quotation -@node Q3.10.6, , Q3.10.5, Customization -@unnumberedsubsec Q3.10.6: Why is killing so slow? +For the related problem of @emph{displaying} non-ASCII characters in a +non-Mule XEmacs, @xref{Q4.0.8, How do I display non-ASCII characters?}. -This actually is an X Windows question, although you'll notice it with -keyboard operations as well as while using the GUI. Basically, there -are four ways to communicate interprogram via the X server: +@node Q3.0.7, Q3.0.8, Q3.0.6, Editing +@unnumberedsubsec Q3.0.7: Can I turn on @dfn{sticky} modifier keys? -@table @strong -@item Primary selection -a transient selection that gets replaced every time a new selection is made +Yes, with @code{(setq modifier-keys-are-sticky t)}. This will give the +effect of being able to press and release Shift and have the next +character typed come out in upper case. This will affect all the other +modifier keys like Control and Meta as well. -@item Secondary selection -for "exchanging" with the primary selection +@email{ben@@xemacs.org, Ben Wing} writes: -@item Cut buffers -a clipboard internal to the X server (deprecated) +@quotation +One thing about the sticky modifiers is that if you move the mouse out +of the frame and back in, it cancels all currently ``stuck'' modifiers. +@end quotation -@item Clipboard selection -a selection with a notification protocol that allows a separate app to -manage the clipboard -@end table +@node Q3.0.8, Q3.0.9, Q3.0.7, Editing +@unnumberedsubsec Q3.0.8: How do I map the arrow keys? +@c New +Say you want to map @kbd{C-@key{right}} to forward-word: -The cut buffers are deprecated because managing them is even more -inefficient than the clipboard notification protocol. The primary -selection works fine for many users and applications, but is not very -robust under intensive or sophisticated use. +@email{sds@@usa.net, Sam Steingold} writes: -In Motif and MS Windows, a clipboard has become the primary means for -managing cut and paste. These means that "modern" applications tend to -be oriented toward a true clipboard, rather than the primary selection. -(On Windows, there is nothing equivalent to the primary selection.) -It's not that XEmacs doesn't support the simple primary selection -method, it's that more and more other applications don't. +@quotation +@lisp +; both XEmacs and Emacs +(define-key global-map [(control right)] 'forward-word) +@end lisp +or +@lisp +; Emacs only +(define-key global-map [C-right] 'forward-word) +@end lisp +or +@lisp +; ver > 20, both +(define-key global-map (kbd "C-<right>") 'forward-word) +@end lisp +@end quotation -So the slowdown occurs because XEmacs now engages in the clipboard -notification protocol on @emph{every} kill. This is especially slow on -Motif. +@node Q3.0.9, Q3.0.10, Q3.0.8, Editing +@unnumberedsubsec Q3.0.9: HP Alt key as Meta. -With most people running most clients and server on the same host, and -many of the rest working over very fast communication, you may expect -that the situation is not going to improve. +How can I make XEmacs recognize the Alt key of my HP workstation as a +Meta key? -There are a number of workarounds. The most effective is to use a -special command to do selection ownership only when you intend to paste -to another application. Useful commands are @code{kill-primary-selection} -and @code{copy-primary-selection}. These work only on text selected -with the mouse (probably; experiment), and are bound by default to the -@kbd{Cut} and @kbd{Copy}, respectively, buttons on the toolbar. -@code{copy-primary-selection} is also bound to @kbd{C-Insert}. You can -yank the clipboard contents with @code{yank-primary-selection}, bound to -the @kbd{Paste} toolbar button and @kbd{Sh-Insert}. +Put the following line into a file and load it with xmodmap(1) before +starting XEmacs: -If you are communicating by cut and paste with applications that use the -primary selection, then you can customize -@code{interprogram-cut-function} to @code{nil}, restoring the XEmacs -version 20 behavior. How can you tell if a program will support this? -Motifly-correct programs require the clipboard; you lose. For others, -only by trying it. You also need to customize the complementary -@code{interprogram-paste-function} to @code{nil}. (Otherwise -XEmacs-to-XEmacs pastes will not work correctly.) +@example +remove Mod1 = Mode_switch +@end example -You may get some relief on Motif by setting -@code{x-selection-strict-motif-ownership} to nil, but this means you will -only intermittently be able to paste XEmacs kills to Motif applications. +@node Q3.0.10, Q3.0.11, Q3.0.9, Editing +@unnumberedsubsec Q3.0.10: Why does edt emulation not work? -Thanks to Jeff Mincy and Glynn Clements for corrections. +We don't know, but you can use tpu-edt emulation instead, which works +fine and is a little fancier than the standard edt emulation. To do +this, add the following line to your @file{init.el}: -@node Subsystems, Miscellaneous, Customization, Top -@unnumbered 4 Major Subsystems +@lisp +(tpu-edt) +@end lisp -This is part 4 of the XEmacs Frequently Asked Questions list. This -section is devoted to major XEmacs subsystems. +If you don't want it to replace @kbd{C-h} with an edt-style help menu +add this as well: -@menu -Reading Mail with VM: -* Q4.0.1:: How do I set up VM to retrieve remote mail using POP? -* Q4.0.2:: How do I get VM to filter mail for me? -* Q4.0.3:: How can I get VM to automatically check for new mail? -* Q4.0.4:: [This question intentionally left blank] -* Q4.0.5:: How do I get my outgoing mail archived? -* Q4.0.6:: I have various addresses at which I receive mail. How can I tell VM to ignore them when doing a "reply-all"? -* Q4.0.7:: Is there a mailing list or FAQ for VM? -* Q4.0.8:: Remote mail reading with VM. -* Q4.0.9:: rmail or VM gets an error incorporating new mail. -* Q4.0.10:: How do I make VM stay in a single frame? -* Q4.0.11:: How do I make VM or mh-e display graphical smilies? -* Q4.0.12:: Customization of VM not covered in the manual or here. - -Web browsing with W3: -* Q4.1.1:: What is W3? -* Q4.1.2:: How do I run W3 from behind a firewall? -* Q4.1.3:: Is it true that W3 supports style sheets and tables? - -Reading Netnews and Mail with Gnus: -* Q4.2.1:: GNUS, (ding) Gnus, Gnus 5, September Gnus, Red Gnus,argh! -* Q4.2.2:: [This question intentionally left blank] -* Q4.2.3:: How do I make Gnus stay within a single frame? -* Q4.2.4:: How do I customize the From: line? - -Other Mail & News: -* Q4.3.1:: How can I read and/or compose MIME messages? -* Q4.3.2:: What is TM and where do I get it? -* Q4.3.3:: Why isn't this @code{movemail} program working? -* Q4.3.4:: Movemail is also distributed by Netscape? Can that cause problems? -* Q4.3.5:: Where do I find pstogif (required by tm)? - -Sparcworks, EOS, and WorkShop: -* Q4.4.1:: What is SPARCworks, EOS, and WorkShop -* Q4.4.2:: How do I start the Sun Workshop support in XEmacs 21? - -Energize: -* Q4.5.1:: What is/was Energize? - -Infodock: -* Q4.6.1:: What is Infodock? - -Other Unbundled Packages: -* Q4.7.1:: What is AUC TeX? Where do you get it? -* Q4.7.2:: Are there any Emacs Lisp Spreadsheets? -* Q4.7.3:: [This question intentionally left blank] -* Q4.7.4:: Problems installing AUC TeX -* Q4.7.5:: Is there a reason for an Emacs package not to be included in XEmacs? -* Q4.7.6:: Is there a MatLab mode? -* Q4.7.7:: Can I edit files on other hosts? -@end menu +@lisp +(global-set-key [(control h)] 'help-for-help) +@end lisp -@node Q4.0.1, Q4.0.2, Subsystems, Subsystems -@unnumberedsec 4.0: Reading Mail with VM -@unnumberedsubsec Q4.0.1: How do I set up VM to retrieve mail from a remote site using POP? +@node Q3.0.11, Q3.1.1, Q3.0.10, Editing +@unnumberedsubsec Q3.0.11: How can I emulate VI and use it as my default mode? -Use @code{vm-spool-files}, like this for example: +Our recommended VI emulator is viper. To make viper-mode the default, +add this to your @file{init.el}: @lisp -(setq vm-spool-files '("/var/spool/mail/wing" - "netcom23.netcom.com:110:pass:wing:MYPASS")) +(viper-mode) @end lisp -Of course substitute your actual password for MYPASS. - -@node Q4.0.2, Q4.0.3, Q4.0.1, Subsystems -@unnumberedsubsec Q4.0.2: How do I get VM to filter mail for me? +@email{kifer@@CS.SunySB.EDU, Michael Kifer} writes: -One possibility is to use procmail to split your mail before it gets to -VM. I prefer this personally, since there are many strange and -wonderful things one can do with procmail. Procmail may be found at -@uref{ftp://ftp.informatik.rwth-aachen.de/pub/packages/procmail/}. +@quotation +This should be added as close to the top of @file{init.el} as you can get +it, otherwise some minor modes may not get viper-ized. +@end quotation -Also see the Mail Filtering FAQ at: -@iftex -@* -@end iftex -@uref{ftp://rtfm.mit.edu/pub/usenet/news.answers/mail/filtering-faq}. -@c Link above, -@c <URL:http://www.cis.ohio-state.edu/hypertext/faq/usenet/mail/filtering-faq/faq.html> -@c was dead. +@unnumberedsec 3.1: The Mouse -@node Q4.0.3, Q4.0.4, Q4.0.2, Subsystems -@unnumberedsubsec Q4.0.3: How can I get VM to automatically check for new mail? +@node Q3.1.1, Q3.1.2, Q3.0.11, Editing +@unnumberedsubsec Q3.1.1: How can I turn off Mouse pasting? -@email{turner@@lanl.gov, John Turner} writes: +I keep hitting the middle mouse button by accident and getting stuff +pasted into my buffer so how can I turn this off? -@quotation -Use the following: +Here is an alternative binding, whereby the middle mouse button selects +(but does not cut) the expression under the mouse. Clicking middle on a +left or right paren will select to the matching one. Note that you can +use @code{define-key} or @code{global-set-key}. @lisp -(setq vm-auto-get-new-mail 60) +(defun mouse-set-point-and-select (event) + "Sets the point at the mouse location, then marks following form" + (interactive "@@e") + (mouse-set-point event) + (mark-sexp 1)) +(define-key global-map [button2] 'mouse-set-point-and-select) @end lisp -@end quotation -@node Q4.0.4, Q4.0.5, Q4.0.3, Subsystems -@unnumberedsubsec Q4.0.4: [This question intentionally left blank] +@node Q3.1.2, Q3.1.3, Q3.1.1, Editing +@unnumberedsubsec Q3.1.2: How do I set control/meta/etc modifiers on mouse buttons? -Obsolete question, left blank to avoid renumbering. +Use, for instance, @code{[(meta button1)]}. For example, here is a common +setting for Common Lisp programmers who use the bundled @code{ilisp} +package, whereby meta-button1 on a function name will find the file where +the function name was defined, and put you at that location in the source +file. -@node Q4.0.5, Q4.0.6, Q4.0.4, Subsystems -@unnumberedsubsec Q4.0.5: How do I get my outgoing mail archived? +[Inside a function that gets called by the lisp-mode-hook and +ilisp-mode-hook] @lisp -(setq mail-archive-file-name "~/outbox") +(local-set-key [(meta button1)] 'edit-definitions-lisp) @end lisp -@node Q4.0.6, Q4.0.7, Q4.0.5, Subsystems -@unnumberedsubsec Q4.0.6: I have various addresses at which I receive mail. How can I tell VM to ignore them when doing a "reply-all"? +@node Q3.1.3, Q3.1.4, Q3.1.2, Editing +@unnumberedsubsec Q3.1.3: Clicking the left button does not do anything in buffer list. -Set @code{vm-reply-ignored-addresses} to a list, like +I do @kbd{C-x C-b} to get a list of buffers and the entries get +highlighted when I move the mouse over them but clicking the left mouse +does not do anything. + +Use the middle mouse button. + +@node Q3.1.4, Q3.1.5, Q3.1.3, Editing +@unnumberedsubsec Q3.1.4: How can I get a list of buffers when I hit mouse button 3? + +The following code will replace the default popup on button3: @lisp -(setq vm-reply-ignored-addresses - '("wing@@nuspl@@nvwls.cc.purdue.edu,netcom[0-9]*.netcom.com" - "wing@@netcom.com" "wing@@xemacs.org")) +(global-set-key [button3] 'popup-buffer-menu) @end lisp -Note that each string is a regular expression. +@node Q3.1.5, Q3.2.1, Q3.1.4, Editing +@unnumberedsubsec Q3.1.5: How can I set XEmacs up so that it pastes where the text cursor is? -@node Q4.0.7, Q4.0.8, Q4.0.6, Subsystems -@unnumberedsubsec Q4.0.7: Is there a mailing list or FAQ for VM? +By default XEmacs pastes X selections where the mouse pointer is. How +do I disable this? -A FAQ for VM exists at @uref{http://www.wonderworks.com/vm/FAQ.html}. +Examine the function @code{mouse-yank}, by typing @kbd{C-h f mouse-yank +@key{RET}}. -VM has its own newsgroups gnu.emacs.vm.info and gnu.emacs.vm.bug. +To get XEmacs to paste at the text cursor, add this your @file{init.el}: -@node Q4.0.8, Q4.0.9, Q4.0.7, Subsystems -@unnumberedsubsec Q4.0.8: Remote mail reading with VM. +@lisp +(setq mouse-yank-at-point t) +@end lisp -My mailbox lives at the office on a big honkin server. My regular INBOX -lives on my honkin desktop machine. I now can PPP to the office from -home which is far from honking... I'd like to be able to read mail at -home without storing it here and I'd like to use xemacs and VM at -home... Is there a recommended setup? +You can also change this with Customize. Select from the +@code{Options} menu @code{Advanced +(Customize)->Emacs->Editing->Mouse->Yank At Point...} or type @kbd{M-x +customize @key{RET} mouse @key{RET}}. -@email{nuspl@@nvwls.cc.purdue.edu, Joseph J. Nuspl Jr.} writes: +@unnumberedsec 3.2: Buffers, Text Editing -@quotation -There are several ways to do this. +@node Q3.2.1, Q3.2.2, Q3.1.5, Editing +@unnumberedsubsec Q3.2.1: Can I have the end of the buffer delimited in some way? -@enumerate -@item -Set your display to your home machine and run dxpc or one of the other X -compressors. +Say, with: @samp{[END]}? -@item -NFS mount your desktop machine on your home machine and modify your pop -command on your home machine to rsh to your desktop machine and actually -do the pop get's. +Try this: -@item -Run a POP server on your desktop machine as well and do a sort of two -tiered POP get. -@end enumerate -@end quotation +@lisp +(let ((ext (make-extent (point-min) (point-max)))) + (set-extent-property ext 'start-closed t) + (set-extent-property ext 'end-closed t) + (set-extent-property ext 'detachable nil) + (set-extent-end-glyph ext (make-glyph [string :data "[END]"]))) +@end lisp - @email{wmperry@@monolith.spry.com, William Perry} adds: +Since this is XEmacs, you can specify an icon to be shown on +window-system devices. To do so, change the @code{make-glyph} call to +something like this: -@quotation -Or you could run a pop script periodically on your desktop machine, and -just use ange-ftp or NFS to get to your mailbox. I used to do this all -the time back at IU. -@end quotation +@lisp +(make-glyph '([xpm :file "~/something.xpm"] + [string :data "[END]"])) +@end lisp + +You can inline the @sc{xpm} definition yourself by specifying +@code{:data} instead of @code{:file}. Here is such a full-featured +version that works on both X and TTY devices: -@node Q4.0.9, Q4.0.10, Q4.0.8, Subsystems -@unnumberedsubsec Q4.0.9: rmail or VM gets an error incorporating new mail. +@lisp +(let ((ext (make-extent (point-min) (point-max)))) + (set-extent-property ext 'start-closed t) + (set-extent-property ext 'end-closed t) + (set-extent-property ext 'detachable nil) + (set-extent-end-glyph ext (make-glyph '([xpm :data "\ +/* XPM */ +static char* eye = @{ +\"20 11 7 2\", +\"__ c None\" +\"_` c #7f7f7f\", +\"_a c #fefefe\", +\"_b c #7f0000\", +\"_c c #fefe00\", +\"_d c #fe0000\", +\"_e c #bfbfbf\", +\"___________`_`_`___b_b_b_b_________`____\", +\"_________`_`_`___b_c_c_c_b_b____________\", +\"_____`_`_`_e___b_b_c_c_c___b___b_______`\", +\"___`_`_e_a___b_b_d___b___b___b___b______\", +\"_`_`_e_a_e___b_b_d_b___b___b___b___b____\", +\"_`_`_a_e_a___b_b_d___b___b___b___b___b__\", +\"_`_`_e_a_e___b_b_d_b___b___b___b___b_b__\", +\"___`_`_e_a___b_b_b_d_c___b___b___d_b____\", +\"_____`_`_e_e___b_b_b_d_c___b_b_d_b______\", +\"_`_____`_`_`_`___b_b_b_d_d_d_d_b________\", +\"___`_____`_`_`_`___b_b_b_b_b_b__________\", +@} ;"] + [string :data "[END]"])))) +@end lisp -Quoting the XEmacs PROBLEMS file: +Note that you might want to make this a function, and put it to a hook. +We leave that as an exercise for the reader. -@quotation -rmail and VM get new mail from @file{/usr/spool/mail/$USER} using a -program called @code{movemail}. This program interlocks with -@code{/bin/mail} using the protocol defined by @code{/bin/mail}. - -There are two different protocols in general use. One of them uses the -@code{flock} system call. The other involves creating a lock file; -@code{movemail} must be able to write in @file{/usr/spool/mail} in order -to do this. You control which one is used by defining, or not defining, -the macro @code{MAIL_USE_FLOCK} in @file{config.h} or the m- or s- file -it includes. +@node Q3.2.2, Q3.2.3, Q3.2.1, Editing +@unnumberedsubsec Q3.2.2: How do I insert today's date into a buffer? -@strong{IF YOU DON'T USE THE FORM OF INTERLOCKING THAT IS NORMAL ON YOUR -SYSTEM, YOU CAN LOSE MAIL!} +Like this: -If your system uses the lock file protocol, and fascist restrictions -prevent ordinary users from writing the lock files in -@file{/usr/spool/mail}, you may need to make @code{movemail} setgid to a -suitable group such as @samp{mail}. You can use these commands (as -root): +@lisp +(insert (current-time-string)) +@end lisp -@example -chgrp mail movemail -chmod 2755 movemail -@end example +@node Q3.2.3, Q3.2.4, Q3.2.2, Editing +@unnumberedsubsec Q3.2.3: How do I get a single minibuffer frame? -If your system uses the lock file protocol, and fascist restrictions -prevent ordinary users from writing the lock files in -@file{/usr/spool/mail}, you may need to make @code{movemail} setgid to a -suitable group such as @code{mail}. To do this, use the following -commands (as root) after doing the make install. +@email{acs@@acm.org, Vin Shelton} writes: -@example -chgrp mail movemail -chmod 2755 movemail -@end example +@lisp +(setq initial-frame-plist '(minibuffer nil)) +(setq default-frame-plist '(minibuffer nil)) +(setq default-minibuffer-frame + (make-frame + '(minibuffer only + width 86 + height 1 + menubar-visible-p nil + default-toolbar-visible-p nil + name "minibuffer" + top -2 + left -2 + has-modeline-p nil))) +(frame-notice-user-settings) +@end lisp -Installation normally copies movemail from the build directory to an -installation directory which is usually under @file{/usr/local/lib}. -The installed copy of @code{movemail} is usually in the directory -@file{/usr/local/lib/emacs/VERSION/TARGET}. You must change the group -and mode of the installed copy; changing the group and mode of the build -directory copy is ineffective. -@end quotation +@strong{Please note:} The single minibuffer frame may not be to everyone's +taste, and there any number of other XEmacs options settings that may +make it difficult or inconvenient to use. -@node Q4.0.10, Q4.0.11, Q4.0.9, Subsystems -@unnumberedsubsec Q4.0.10: How do I make VM stay in a single frame? +@node Q3.2.4, Q3.2.5, Q3.2.3, Editing +@unnumberedsubsec Q3.2.4: How can I enable auto-indent and/or Filladapt? -John.@email{Cooper@@Eng.Sun.COM, John S Cooper} writes: +Put the following line in your @file{init.el}: -@quotation @lisp - ; Don't use multiple frames -(setq vm-frame-per-composition nil) -(setq vm-frame-per-folder nil) -(setq vm-frame-per-edit nil) -(setq vm-frame-per-summary nil) +(setq indent-line-function 'indent-relative-maybe) @end lisp -@end quotation -@node Q4.0.11, Q4.0.12, Q4.0.10, Subsystems -@unnumberedsubsec Q4.0.11: How do I make VM or mh-e display graphical smilies? -@c Changed June -For mh-e use the following: +If you want to get fancy, try the @code{filladapt} package available +standard with XEmacs. Put this into your @file{init.el}: @lisp -(add-hook 'mh-show-mode-hook '(lambda () - (smiley-region (point-min) - (point-max)))) +(require 'filladapt) +(setq-default filladapt-mode t) +(add-hook 'c-mode-hook 'turn-off-filladapt-mode) @end lisp -@email{bill@@carpenter.ORG, WJCarpenter} writes: -For VM use the following: -@lisp - (autoload 'smiley-region "smiley" nil t) - (add-hook 'vm-select-message-hook - '(lambda () - (smiley-region (point-min) - (point-max)))) -@end lisp +This will enable Filladapt for all modes except C mode, where it doesn't +work well. To turn Filladapt on only in particular major modes, remove +the @code{(setq-default ...)} line and use +@code{turn-on-filladapt-mode}, like this: -For tm use the following: @lisp -(autoload 'smiley-buffer "smiley" nil t) -(add-hook 'mime-viewer/plain-text-preview-hook 'smiley-buffer) +(add-hook 'text-mode-hook 'turn-on-filladapt-mode) @end lisp -@node Q4.0.12, Q4.1.1, Q4.0.11, Subsystems -@unnumberedsubsec Q4.0.12: Customization of VM not covered in the manual, or here. +You can customize filling and adaptive filling with Customize. +Select from the @code{Options} menu +@code{Advanced (Customize)->Emacs->Editing->Fill->Fill...} +or type @kbd{M-x customize @key{RET} fill @key{RET}}. -@email{boffi@@hp735.stru.polimi.it, giacomo boffi} writes: +Note that well-behaving text-lookalike modes will run +@code{text-mode-hook} by default (e.g. that's what Message does). For +the nasty ones, you'll have to provide the @code{add-hook}s yourself. -@quotation -The meta-answer is to look into the file @file{vm-vars.el}, in the vm -directory of the lisp library. +Please note that the @code{fa-extras} package is no longer useful. -@file{vm-vars.el} contains, initializes and carefully describes, with -examples of usage, the plethora of user options that @emph{fully} -control VM's behavior. +@node Q3.2.5, Q3.3.1, Q3.2.4, Editing +@unnumberedsubsec Q3.2.5: How can I get XEmacs to come up in text/auto-fill mode by default? -Enter vm-vars, @code{forward-search} for toolbar, find the variables -that control the toolbar placement, appearance, existence, copy to your -@file{init.el}/@file{.emacs} or @file{.vm} and modify according to the -detailed instructions. +Try the following lisp in your @file{init.el}: -The above also applies to all the various features of VM: search for -some keywords, maybe the first you conjure isn't appropriate, find the -appropriate variables, copy and experiment. -@end quotation +@lisp +(setq default-major-mode 'text-mode) +(setq text-mode-hook 'turn-on-auto-fill) +@end lisp -@node Q4.1.1, Q4.1.2, Q4.0.12, Subsystems -@unnumberedsec 4.1: Web browsing with W3 -@unnumberedsubsec Q4.1.1: What is W3? +@strong{WARNING}: note that changing the value of +@code{default-major-mode} from @code{fundamental-mode} can break a large +amount of built-in code that expects newly created buffers to be in +@code{fundamental-mode}. (Changing from @code{fundamental-mode} to +@code{text-mode} might not wreak too much havoc, but changing to +something more exotic like a lisp-mode would break many Emacs packages). -W3 is an advanced graphical browser written in Emacs lisp that runs on -XEmacs. It has full support for cascaded style sheets, and more... +Note that Emacs by default starts up in buffer @code{*scratch*} in +@code{initial-major-mode}, which defaults to +@code{lisp-interaction-mode}. Thus adding the following form to your +Emacs init file will cause the initial @code{*scratch*} buffer to be put +into auto-fill'ed @code{text-mode}: -It has a home web page at -@uref{http://www.cs.indiana.edu/elisp/w3/docs.html}. +@lisp +(setq initial-major-mode + (lambda () + (text-mode) + (turn-on-auto-fill))) +@end lisp + +Note that after your init file is loaded, if +@code{inhibit-startup-message} is @code{nil} (the default) and the +startup buffer is @code{*scratch*} then the startup message will be +inserted into @code{*scratch*}; it will be removed after a timeout by +erasing the entire @code{*scratch*} buffer. Keep in mind this default +usage of @code{*scratch*} if you desire any prior manipulation of +@code{*scratch*} from within your Emacs init file. In particular, +anything you insert into @code{*scratch*} from your init file will be +later erased. Also, if you change the mode of the @code{*scratch*} +buffer, be sure that this will not interfere with possible later +insertion of the startup message (e.g. if you put @code{*scratch*} into +a nonstandard mode that has automatic font lock rules, then the startup +message might get fontified in a strange foreign manner, e.g. as code in +some programming language). -@node Q4.1.2, Q4.1.3, Q4.1.1, Subsystems -@unnumberedsubsec Q4.1.2: How do I run W3 from behind a firewall? +@unnumberedsec 3.3: Text Selections -There is a long, well-written, detailed section in the W3 manual that -describes how to do this. Look in the section entitled "Firewalls". +@node Q3.3.1, Q3.3.2, Q3.2.5, Editing +@unnumberedsubsec Q3.3.1: How do I select a rectangular region? -@node Q4.1.3, Q4.2.1, Q4.1.2, Subsystems -@unnumberedsubsec Q4.1.3: Is it true that W3 supports style sheets and tables? +Just select the region normally, then use the rectangle commands (e.g. +@code{kill-rectangle} on it. The region does not highlight as a +rectangle, but the commands work just fine. -Yes, and much more. W3, as distributed with the latest XEmacs is a -full-featured web browser. +To actually sweep out rectangular regions with the mouse you can use +@code{mouse-track-do-rectangle} which is assigned to @kbd{M-button1}. +Then use rectangle commands. -@node Q4.2.1, Q4.2.2, Q4.1.3, Subsystems -@unnumberedsec 4.2: Reading Netnews and Mail with Gnus -@unnumberedsubsec Q4.2.1: GNUS, (ding) Gnus, Gnus 5, September Gnus, Red Gnus, Quassia Gnus, argh! +You can also do the following to change default behavior to sweep out +rectangular regions: -The Gnus numbering issues are not meant for mere mortals to know them. -If you feel you @emph{must} enter the muddy waters of Gnus, visit the -excellent FAQ, maintained by Justin Sheehy, at: +@lisp +(setq mouse-track-rectangle-p t) +@end lisp + +You can also change this with Customize. +Select from the @code{Options} menu +@code{Advanced (Customize)->Emacs->Editing->Mouse->Track Rectangle...} or type +@kbd{M-x customize @key{RET} mouse @key{RET}}. -@example -@uref{http://www.ccs.neu.edu/software/contrib/gnus/} -@end example -See also Gnus home page @example -@uref{http://www.gnus.org/} + mouse-track-do-rectangle: (event) + -- an interactive compiled Lisp function. + Like `mouse-track' but selects rectangles instead of regions. @end example -@node Q4.2.2, Q4.2.3, Q4.2.1, Subsystems -@unnumberedsubsec Q4.2.2: This question intentionally left blank. +@node Q3.3.2, Q3.3.3, Q3.3.1, Editing +@unnumberedsubsec Q3.3.2: How can I turn off or change highlighted selections? + +The @code{zmacs} mode allows for what some might call gratuitous +highlighting for selected regions (either by setting mark or by using +the mouse). This is the default behavior. To turn off, add the +following line to your @file{init.el} file: + +@lisp +(setq zmacs-regions nil) +@end lisp -Obsolete question, left blank to avoid renumbering. +You can also change this with Customize. Select from the +@code{Options} menu +@code{Advanced (Customize)->Emacs->Editing->Basics->Zmacs Regions} +or type @kbd{M-x customize @key{RET} editing-basics @key{RET}}. -@node Q4.2.3, Q4.2.4, Q4.2.2, Subsystems -@unnumberedsubsec Q4.2.3: How do I make Gnus stay within a single frame? +To change the face for selection, look at @code{Options->Advanced (Customize)} +on the menubar. -The toolbar code to start Gnus opens the new frame---and it's a feature -rather than a bug. If you don't like it, but would still like to click -on the seemly icon, use the following code: +@node Q3.3.3, Q3.3.4, Q3.3.2, Editing +@unnumberedsubsec Q3.3.3: How do I cause typing on an active region to remove it? + +I want to change things so that if I select some text and start typing, +the typed text replaces the selected text, similar to Motif. + +You want to use something called @dfn{pending delete}. Pending delete +is what happens when you select a region (with the mouse or keyboard) +and you press a key to replace the selected region by the key you typed. +Usually backspace kills the selected region. + +To get this behavior, ensure that you have the @file{pc} package +installed, and add the following lines to your +@file{init.el}: @lisp -(defun toolbar-news () - (gnus)) +(cond + ((fboundp 'turn-on-pending-delete) + (turn-on-pending-delete)) + ((fboundp 'pending-delete-on) + (pending-delete-on t))) @end lisp -It will redefine the callback function of the icon to just call -@code{gnus}, without all the fancy frame stuff. +Note that this will work with both Backspace and Delete. This code is a +tad more complicated than it has to be for XEmacs in order to make it +more portable. -@node Q4.2.4, Q4.3.1, Q4.2.3, Subsystems -@unnumberedsubsec Q4.2.4: How do I customize the From: line? +@node Q3.3.4, Q3.3.5, Q3.3.3, Editing +@unnumberedsubsec Q3.3.4: Can I turn off the highlight during isearch? -How do I change the @code{From:} line? I have set gnus-user-from-line -to -@example -Gail Gurman <gail.gurman@@sybase.com> -@end example -@noindent , but XEmacs Gnus doesn't use -it. Instead it uses -@example -Gail Mara Gurman @email{gailg@@deall} -@end example -@noindent and then complains -that it's incorrect. Also, as you perhaps can see, my Message-ID is -screwy. How can I change that? +I do not like my text highlighted while I am doing isearch as I am not +able to see what's underneath. How do I turn it off? -@email{larsi@@ifi.uio.no, Lars Magne Ingebrigtsen} writes: +Put the following in your @file{init.el}: -@quotation -Set @code{user-mail-address} to @samp{gail.gurman@@sybase.com} or -@code{mail-host-address} to @samp{sybase.com}. -@end quotation +@lisp +(setq isearch-highlight nil) +@end lisp + +You can also change this with Customize. Type +@kbd{M-x customize-variable @key{RET} isearch-highlight @key{RET}}. + +Note also that isearch-highlight affects query-replace and ispell. +Instead of disabling isearch-highlight you may find that a better +solution consists of customizing the @code{isearch} face. -@node Q4.3.1, Q4.3.2, Q4.2.4, Subsystems -@unnumberedsec 4.3: Other Mail & News -@unnumberedsubsec Q4.3.1: How can I read and/or compose MIME messages? -@c Changed June +@node Q3.3.5, Q3.3.6, Q3.3.4, Editing +@unnumberedsubsec Q3.3.5: Why is killing so slow? + +This actually is an X Windows question, although you'll notice it with +keyboard operations as well as while using the GUI. Basically, there +are four ways to communicate interprogram via the X server: -VM supports MIME natively. +@table @strong +@item Primary selection +a transient selection that gets replaced every time a new selection is made -You probably want to use the Tools for MIME (tm). @xref{Q4.3.2}, for -details. +@item Secondary selection +for "exchanging" with the primary selection -@email{trey@@cs.berkeley.edu, Trey Jackson} has an Emacs & MIME web page at -@iftex -@* -@end iftex -@uref{http://bmrc.berkeley.edu/~trey/emacs/mime.html}. +@item Cut buffers +a clipboard internal to the X server (deprecated) +@item Clipboard selection +a selection with a notification protocol that allows a separate app to +manage the clipboard +@end table -Another possibility is RMIME. You may find RMIME at -@iftex -@* -@end iftex -@uref{http://www.cinti.net/~rmoody/rmime/index.html}. +The cut buffers are deprecated because managing them is even more +inefficient than the clipboard notification protocol. The primary +selection works fine for many users and applications, but is not very +robust under intensive or sophisticated use. +In Motif and MS Windows, a clipboard has become the primary means for +managing cut and paste. These means that "modern" applications tend to +be oriented toward a true clipboard, rather than the primary selection. +(On Windows, there is nothing equivalent to the primary selection.) +It's not that XEmacs doesn't support the simple primary selection +method, it's that more and more other applications don't. -@node Q4.3.2, Q4.3.3, Q4.3.1, Subsystems -@unnumberedsubsec Q4.3.2: What is TM and where do I get it? +So the slowdown occurs because XEmacs now engages in the clipboard +notification protocol on @emph{every} kill. This is especially slow on +Motif. -TM stands for @dfn{Tools for MIME} and not Tiny MIME. TM integrates -with all major XEmacs packages like Gnus (all flavors), VM, MH-E, and -mailcrypt. It provides totally transparent and trouble-free MIME -support. When appropriate a message will be decoded in place in an -XEmacs buffer. +With most people running most clients and server on the same host, and +many of the rest working over very fast communication, you may expect +that the situation is not going to improve. -TM now comes as a package with XEmacs 19.16 and XEmacs 20.2. +There are a number of workarounds. The most effective is to use a +special command to do selection ownership only when you intend to paste +to another application. Useful commands are @code{kill-primary-selection} +and @code{copy-primary-selection}. These work only on text selected +with the mouse (probably; experiment), and are bound by default to the +@kbd{Cut} and @kbd{Copy}, respectively, buttons on the toolbar. +@code{copy-primary-selection} is also bound to @kbd{C-Insert}. You can +yank the clipboard contents with @code{yank-primary-selection}, bound to +the @kbd{Paste} toolbar button and @kbd{Sh-Insert}. -TM was written by @email{morioka@@jaist.ac.jp, MORIOKA Tomohiko} and -@email{shuhei-k@@jaist.ac.jp, KOBAYASHI -Shuhei}. +If you are communicating by cut and paste with applications that use the +primary selection, then you can customize +@code{interprogram-cut-function} to @code{nil}, restoring the XEmacs +version 20 behavior. How can you tell if a program will support this? +Motifly-correct programs require the clipboard; you lose. For others, +only by trying it. You also need to customize the complementary +@code{interprogram-paste-function} to @code{nil}. (Otherwise +XEmacs-to-XEmacs pastes will not work correctly.) -It is based on the work of @email{umerin@@mse.kyutech.ac.jp, UMEDA -Masanobu}, the original writer of GNUS. +You may get some relief on Motif by setting +@code{x-selection-strict-motif-ownership} to nil, but this means you will +only intermittently be able to paste XEmacs kills to Motif applications. -The following information is from the @file{README}: +Thanks to Jeff Mincy and Glynn Clements for corrections. -@dfn{tm} is a MIME package for GNU Emacs. -tm has following functions: +@node Q3.3.6, Q3.4.1, Q3.3.5, Editing +@unnumberedsubsec Q3.3.6: Why does @kbd{M-w} take so long? -@itemize @bullet -@item MIME style multilingual header. -@item MIME message viewer (mime/viewer-mode). -@item MIME message composer (mime/editor-mode). -@item MIME extenders for mh-e, GNUS, RMAIL and VM. -@end itemize +It actually doesn't. It leaves the region visible for a second so that +you can see what area is being yanked. If you start working, though, it +will immediately complete its operation. In other words, it will only +delay for a second if you let it. -tm is available from following anonymous ftp sites: -@itemize @bullet -@comment @item @uref{ftp://ftp.jaist.ac.jp/pub/GNU/elisp/mime/} (Japan). -@comment @item @uref{ftp://ftp.nis.co.jp/pub/gnu/emacs-lisp/tm/} (Japan). -@comment @c The host above is unknown. -@comment @item @uref{ftp://ftp.nisiq.net/pub/gnu/emacs-lisp/tm/} (US). -@comment @item @uref{ftp://ftp.miranova.com/pub/gnus/jaist.ac.jp/} (US). -@item @uref{ftp://ftp.unicamp.br/pub/mail/mime/tm/} (Brasil). -@item @uref{ftp://ftp.th-darmstadt.de/pub/editors/GNU-Emacs/lisp/mime/} (Germany). -@item @uref{ftp://ftp.tnt.uni-hannover.de/pub/editors/xemacs/contrib/} (Germany). -@end itemize +@unnumberedsec 3.4: Editing Source Code -Don't let the installation procedure & instructions stop you from trying -this package out---it's much simpler than it looks, and once installed, -trivial to use. +@node Q3.4.1, Q3.4.2, Q3.3.6, Editing +@unnumberedsubsec Q3.4.1: I do not like cc-mode. How do I use the old c-mode? -@email{youngs@@xemacs.org, Steve Youngs} writes: +Well, first off, consider if you really want to do this. cc-mode is +much more powerful than the old c-mode. If you're having trouble +getting your old offsets to work, try using @code{c-set-offset} instead. +You might also consider using the package @code{cc-compat}. -@quotation -All the major Emacs Lisp based MUAs (Gnus, MH-E, and VM) all do their -own thing when it comes to MIME so you won't need TM to get MIME support -in these packages. -@end quotation +But, if you still insist, add the following lines to your @file{init.el}: -@node Q4.3.3, Q4.3.4, Q4.3.2, Subsystems -@unnumberedsubsec Q4.3.3: Why isn't this @code{movemail} program working? +@lisp +(fmakunbound 'c-mode) +(makunbound 'c-mode-map) +(fmakunbound 'c++-mode) +(makunbound 'c++-mode-map) +(makunbound 'c-style-alist) +(load-library "old-c-mode") +(load-library "old-c++-mode") +@end lisp -Ben Wing @email{ben@@xemacs.org} writes: +This must be done before any other reference is made to either c-mode or +c++-mode. -@quotation -It wasn't chown'ed/chmod'd correctly. -@end quotation +@node Q3.4.2, , Q3.4.1, Editing +@unnumberedsubsec Q3.4.2: How do you make XEmacs indent CL if-clauses correctly? -@node Q4.3.4, Q4.3.5, Q4.3.3, Subsystems -@unnumberedsubsec Q4.3.4: Movemail is also distributed by Netscape? Can that cause problems? +I'd like XEmacs to indent all the clauses of a Common Lisp @code{if} the +same amount instead of indenting the 3rd clause differently from the +first two. -@email{steve@@xemacs.org, Steve Baur} writes: +The package @code{cl-indent} that comes with XEmacs sets up this kind +of indentation by default. @code{cl-indent} also knows about many +other CL-specific forms. To use @code{cl-indent}, one can do this: -@quotation -Yes. Always use the movemail installed with your XEmacs. Failure to do -so can result in lost mail. -@end quotation +@lisp +(setq lisp-indent-function 'common-lisp-indent-function) +@end lisp -Please refer to @email{jwz@@jwz.org, Jamie Zawinski's} notes at -@iftex -@* -@end iftex -@uref{http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/movemail.html}. -In particular, this document will show you how to make Netscape use the -version of movemail configured for your system by the person who built -XEmacs. +One can also customize @file{cl-indent.el} so it mimics the default +@code{if} indentation @code{then} indented more than the @code{else}. +Here's how: -@node Q4.3.5, Q4.4.1, Q4.3.4, Subsystems -@unnumberedsubsec Q4.3.5: Where do I find pstogif (required by tm)? +@lisp +(put 'if 'common-lisp-indent-function '(nil nil &body)) +@end lisp -pstogif is part of the latex2html package. +@node Display, External Subsystems, Editing, Top +@unnumbered 4 Display Functions -@email{vroonhof@@math.ethz.ch, Jan Vroonhof} writes: +This is part 4 of the XEmacs Frequently Asked Questions list. This +section is devoted to the display-related capabilities of XEmacs +(fonts, colors, modeline, menubar, toolbar, scrollbar, etc.) and how +to customize them. -latex2html is best found at the CTAN hosts and their mirrors -in -@iftex -@* -@end iftex -@file{tex-archive/support/latex2html}. +@menu +4.0: Textual Fonts and Colors +* Q4.0.1:: How do I specify a font? +* Q4.0.2:: How do I set the text, menu and modeline fonts? +* Q4.0.3:: How can I set color options from @file{init.el}? +* Q4.0.4:: How can I set the colors when highlighting a region? +* Q4.0.5:: How can I limit color map usage? +* Q4.0.6:: My tty supports color, but XEmacs doesn't use them. +* Q4.0.7:: Can I have pixmap backgrounds in XEmacs? +* Q4.0.8:: How do I display non-ASCII characters? +* Q4.0.9:: Font selections in don't get saved after @code{Save Options}. + +4.1: Syntax Highlighting (Font Lock) +* Q4.1.1:: How can I do source code highlighting using font-lock? +* Q4.1.2:: How do I get @samp{More} Syntax Highlighting on by default? + +4.2: The Modeline +* Q4.2.1:: How can I make the modeline go away? +* Q4.2.2:: How do you have XEmacs display the line number in the modeline? +* Q4.2.3:: How do I get XEmacs to put the time of day on the modeline? +* Q4.2.4:: How can I change the modeline color based on the mode used? + +4.3: The Cursor +* Q4.3.1:: Is there a way to make the bar cursor thicker? +* Q4.3.2:: Is there a way to get back the block cursor? +* Q4.3.3:: Can I make the cursor blink? + +4.4: The Menubar +* Q4.4.1:: How do I get rid of the menubar? +* Q4.4.2:: How can I customize the menubar? +* Q4.4.3:: How do I enable use of the keyboard (@kbd{Alt}) to access menu items? +* Q4.4.4:: How do I control how many buffers are listed in the menu @code{Buffers List}? +* Q4.4.5:: Resources like @code{Emacs*menubar*font} are not working? + +4.5: The Toolbar +* Q4.5.1:: How do I get rid of the toolbar? +* Q4.5.2:: How can I customize the toolbar? +* Q4.5.3:: How can I bind a key to a function to toggle the toolbar? +* Q4.5.4:: @samp{Can't instantiate image error...} in toolbar + +4.6: Scrollbars and Scrolling +* Q4.6.1:: How can I disable the scrollbar? +* Q4.6.2:: How can I change the scrollbar width? +* Q4.6.3:: How can I use resources to change scrollbar colors? +* Q4.6.4:: Moving the scrollbar can move the point; can I disable this? +* Q4.6.5:: Scrolling one line at a time. +* Q4.6.6:: How can I turn off automatic horizontal scrolling in specific modes? +* Q4.6.7:: I find auto-show-mode disconcerting. How do I turn it off? + +4.7: The Gutter Tabs, The Progress Bar, Widgets +* Q4.7.1:: How can I disable the gutter tabs? +* Q4.7.2:: How can I disable the progress bar? +* Q4.7.3:: There are bugs in the gutter or widgets. +* Q4.7.4:: How can I customize the gutter or gutter tabs? +@end menu -CTAN hosts are: +@unnumberedsec 4.0: Textual Fonts and Colors -@itemize @bullet -@item @uref{ftp://ftp.tex.ac.uk/tex-archive/support/latex2html/}. -@item @uref{ftp://ftp.dante.de/tex-archive/support/latex2html/}. -@end itemize +@node Q4.0.1, Q4.0.2, Display, Display +@unnumberedsubsec Q4.0.1: How do I specify a font? -There is a good mirror at ftp.cdrom.com; -@iftex -@* -@end iftex -@uref{ftp://ftp.cdrom.com/pub/tex/ctan/support/latex2html/}. +#### Update me. -@node Q4.4.1, Q4.4.2, Q4.3.5, Subsystems -@unnumberedsec 4.4: Sparcworks, EOS, and WorkShop -@unnumberedsubsec Q4.4.1: What is SPARCworks, EOS, and WorkShop? +In 21.4 and above, you can use the @samp{Options} menu to change the font. +You can also do it in your init file, e.g. like this (for MS Windows): -@email{turner@@lanl.gov, John Turner} writes: +@display + (set-face-font 'default "Lucida Console:Regular:10") + (set-face-font 'modeline "MS Sans Serif:Regular:10") +@end display -@quotation -SPARCworks is SunSoft's development environment, comprising compilers -(C, C++, FORTRAN 77, Fortran 90, Ada, and Pascal), a debugger, and other -tools such as TeamWare (for configuration management), MakeTool, etc. -@end quotation +@node Q4.0.2, Q4.0.3, Q4.0.1, Display +@unnumberedsubsec Q4.0.2: How do I set the text, menu and modeline fonts? -See @uref{http://www.sun.com/software/Developer-products/} -for more info. +#### Update me. -EOS stands for "Era on SPARCworks", but I don't know what Era stands -for. +Note that you should use @samp{Emacs.} and not @samp{Emacs*} when +setting face values. -EOS is the integration of XEmacs with the SPARCworks debugger. It -allows one to use an XEmacs frame to view code (complete with -fontification, etc.), set breakpoints, print variables, etc., while -using the SPARCworks debugger. It works very well and I use it all the -time. +In @file{.Xresources}: -@email{cthomp@@xemacs.org, Chuck Thompson} writes: +@example +Emacs.default.attributeFont: -*-*-medium-r-*-*-*-120-*-*-m-*-*-* +Emacs*menubar*font: fixed +Emacs.modeline.attributeFont: fixed +@end example -@quotation -Era stood for "Emacs Rewritten Again". It was what we were calling the -modified version of Lucid Emacs for Sun when I was dragged, er, allowed -to work on this wonderful editor. -@end quotation +This is confusing because @samp{default} and @samp{modeline} are face +names, and can be found listed with all faces in the current mode by +using @kbd{M-x set-face-font (enter) ?}. They use the face-specific +resource @samp{attributeFont}. -@email{martin@@xemacs.org, Martin Buchholz} writes: +On the other hand, @samp{menubar} is a normal X thing that uses the +resource @samp{font}. With Motif it @emph{may be} necessary to use +@samp{fontList} @emph{instead of} @samp{font}. In @emph{non-Motif} +configurations with Mule it @emph{is} necessary to use @samp{fontSet} +instead of @samp{font}. (Sorry, there just is no simple recipe here.) -@quotation -EOS is being replaced with a new graphical development environment -called Sun WorkShop, which is currently (07/96) in Alpha Test. For more -details, check out -@iftex -@* -@end iftex -@uref{http://www.sun.com/software/Products/Developer-products}. -@end quotation +@node Q4.0.3, Q4.0.4, Q4.0.2, Display +@unnumberedsubsec Q4.0.3: How can I set color options from @file{init.el}? -@node Q4.4.2, Q4.5.1, Q4.4.1, Subsystems -@unnumberedsubsec Q4.4.2: How do I start the Sun Workshop support in XEmacs 21? +How can I set the most commonly used color options from my +@file{init.el} instead of from my @file{.Xresources}? -Add the switch ---with-workshop to the configure command when building -XEmacs and put the following in one of your startup files -(e.g. site-start.el or .emacs): +Like this: @lisp -(when (featurep 'tooltalk) - (load "tooltalk-macros") - (load "tooltalk-util") - (load "tooltalk-init")) -(when (featurep 'sparcworks) - (load "sunpro-init") - (load "ring") - (load "comint") - (load "annotations") - (sunpro-startup)) +(set-face-background 'default "bisque") ; frame background +(set-face-foreground 'default "black") ; normal text +(set-face-background 'zmacs-region "red") ; When selecting w/ + ; mouse +(set-face-foreground 'zmacs-region "yellow") +(set-face-font 'default "*courier-bold-r*120-100-100*") +(set-face-background 'highlight "blue") ; Ie when selecting + ; buffers +(set-face-foreground 'highlight "yellow") +(set-face-background 'modeline "blue") ; Line at bottom + ; of buffer +(set-face-foreground 'modeline "white") +(set-face-font 'modeline "*bold-r-normal*140-100-100*") +(set-face-background 'isearch "yellow") ; When highlighting + ; while searching +(set-face-foreground 'isearch "red") +(setq x-pointer-foreground-color "black") ; Adds to bg color, + ; so keep black +(setq x-pointer-background-color "blue") ; This is color + ; you really + ; want ptr/crsr @end lisp -If you are not using the latest Workshop (5.0) you have to apply the -following patch: +@node Q4.0.4, Q4.0.5, Q4.0.3, Display +@unnumberedsubsec Q4.0.4: How can I set the colors when highlighting a region? -@format ---- /opt/SUNWspro/lib/eserve.el.ORIG Fri May 14 15:23:26 1999 -+++ /opt/SUNWspro/lib/eserve.el Fri May 14 15:24:54 1999 -@@@@ -42,7 +42,7 @@@@ - (defvar running-xemacs nil "t if we're running XEmacs") - (defvar running-emacs nil "t if we're running GNU Emacs 19") +How can I set the background/foreground colors when highlighting a +region? --(if (string-match "^\\(19\\|20\\)\..*\\(XEmacs\\|Lucid\\)" emacs-version) -+(if (string-match "\\(XEmacs\\|Lucid\\)" emacs-version) - (setq running-xemacs t) - (setq running-emacs t)) -@end format +You can change the face @code{zmacs-region} either in your +@file{.Xresources}: +@example +Emacs.zmacs-region.attributeForeground: firebrick +Emacs.zmacs-region.attributeBackground: lightseagreen +@end example +or in your @file{init.el}: -@node Q4.5.1, Q4.6.1, Q4.4.2, Subsystems -@unnumberedsec 4.5: Energize -@unnumberedsubsec Q4.5.1: What is/was Energize? +@lisp +(set-face-background 'zmacs-region "red") +(set-face-foreground 'zmacs-region "yellow") +@end lisp -@email{gray@@meteor.harlequin.com, David N Gray} writes: -@quotation -The files in @file{lisp/energize} are to enable Emacs to interface with -the "Energize Programming System", a C and C++ development environment, -which was a product of Lucid, Inc. Tragically, Lucid went out of -business in 1994, so although Energize is still a great system, if you -don't already have it, there isn't any way to get it now. (Unless you -happen to be in Japan; INS Engineering may still be selling it there. -Tartan bought the rights to sell it in the rest of the world, but never -did so.) -@end quotation +@node Q4.0.5, Q4.0.6, Q4.0.4, Display +@unnumberedsubsec Q4.0.5: How can I limit color map usage? -@node Q4.6.1, Q4.7.1, Q4.5.1, Subsystems -@unnumberedsec 4.6: Infodock -@unnumberedsubsec Q4.6.1: What is Infodock? +I'm using Netscape (or another color grabber like XEmacs); +is there any way to limit the number of available colors in the color map? -@uref{http://sourceforge.net/projects/infodock/, InfoDock} is an -integrated productivity toolset, mainly aimed at technical people, -hosted at SourceForge. +Answer: No, but you can start Netscape before XEmacs, and it will use +the closest available color if the colormap is full. You can also limit +the number of colors Netscape uses, using the flags -mono, -ncols <#> or +-install (for mono, limiting to <#> colors, or for using a private color +map). -InfoDock is built atop the XEmacs variant of GNU Emacs and so has all of -the power of Emacs, but with an easier to use and more comprehensive -menu-based user interface. The bottom portion of this text describes -how it differs from XEmacs and GNU Emacs from the Free Software -Foundation. +If you have the money, another solution would be to use a truecolor or +direct color video. -InfoDock is aimed at people who want a free, turn-key productivity -environment. Although InfoDock is customizable, it is not intended for -people who like basic versions of Emacs which need to be customized -extensively for local use; standard Emacs distributions are better for -such uses. InfoDock is for those people who want a complete, -pre-customized environment in one package, which they need not touch -more than once or twice a year to update to new revisions. +@node Q4.0.6, Q4.0.7, Q4.0.5, Display +@unnumberedsubsec Q4.0.6: My tty supports color, but XEmacs doesn't use them. -InfoDock is pre-built for SPARC SunOS/Solaris systems, PA-RISC HP-UX, -and Intel Linux systems. It is intended for use on a color display, -although most features will work on monochrome monitors. Simply unpack -InfoDock according to the instructions in the ID-INSTALL file and you -are ready to run. +XEmacs tries to automatically determine whether your tty supports color, +but sometimes guesses wrong. In that case, you can make XEmacs Do The +Right Thing using this Lisp code: -The InfoDock Manual is concise, yet sufficient as a user guide for users -who have never used an Emacs-type editor before. For users who are -already familiar with Emacs, it supplements the information in the GNU -Emacs Manual. +@lisp +(if (eq 'tty (device-type)) + (set-device-class nil 'color)) +@end lisp -InfoDock menus are much more extensive and more mature than standard -Emacs menus. Each menu offers a @samp{Manual} item which displays -documentation associated with the menu's functions. +@node Q4.0.7, Q4.0.8, Q4.0.6, Display +@unnumberedsubsec Q4.0.7: Can I have pixmap backgrounds in XEmacs? +@c New +@email{jvillaci@@wahnsinnig.extreme.indiana.edu, Juan Villacis} writes: -@noindent -Four types of menubars are provided: -@enumerate -@item -An extensive menubar providing access to global InfoDock commands. -@item -Mode-specific menubars tailored to the current major mode. -@item -A simple menubar for basic editing to help novices get started with InfoDock. -@item -The standard XEmacs menubar. -@end enumerate +@quotation +There are several ways to do it. For example, you could specify a +default pixmap image to use in your @file{~/.Xresources}, e.g., -Most modes also include mode-specific popup menus. Additionally, region and -rectangle popup menus are included. -@samp{Hyperbole}, the everyday information manager, is a core part of -InfoDock. This provides context-sensitive mouse keys, a rolodex-type -contact manager, programmable hypertext buttons, and an autonumbered -outliner with embedded hyperlink anchors. +@example + Emacs*EmacsFrame.default.attributeBackgroundPixmap: /path/to/image.xpm +@end example -The @samp{OO-Browser}, a multi-language object-oriented code browser, is a -standard part of InfoDock. -InfoDock saves a more extensive set of user options than other Emacs -versions. +and then reload ~/.Xresources and restart XEmacs. Alternatively, +since each face can have its own pixmap background, a better way +would be to set a face's pixmap within your XEmacs init file, e.g., -InfoDock inserts a useful file header in many file types, showing the -author, summary, and last modification time of each file. A summary -program can then be used to summarize all of the files in a directory, -for easy MANIFEST file creation. +@lisp + (set-face-background-pixmap 'default "/path/to/image.xpm") + (set-face-background-pixmap 'bold "/path/to/another_image.xpm") +@end lisp -Your working set of buffers is automatically saved and restored (if you -answer yes to a prompt) between InfoDock sessions. +and so on. You can also do this interactively via @kbd{M-x edit-faces}. -Refined color choices for code highlighting are provided for both dark and -light background display frames. +@end quotation -The @kbd{C-z} key prefix performs frame-based commands which parallel the -@kbd{C-x} key prefix for window-based commands. +@node Q4.0.8, Q4.0.9, Q4.0.7, Display +@unnumberedsubsec Q4.0.8: How do I display non-ASCII characters? +@c New -The Smart Menu system is included for producing command menus on dumb -terminals. +If you're using a Mule-enabled XEmacs, then display is automatic. If +you're not seeing the characters you expect, either (1) you don't have +appropriate fonts available or (2) XEmacs did not correctly detect the +coding system (@pxref{Recognize Coding, , , xemacs}). In case (1), +install fonts as is customary for your platform. In case (2), you +need to tell XEmacs explicitly what coding systems you're using. +@ref{Specify Coding, , , xemacs}. -Lisp libraries are better categorized according to function. +If your XEmacs is not Mule-enabled, and for some reason getting a +Mule-enabled XEmacs seems like the wrong thing to do, all is not lost. +You can arrange it by brute force. In @file{event-Xt.c} (suppress the +urge to look in this file---play Doom instead, because you'll survive +longer), it is written: -Extensions and improvements to many areas of Emacs are included, such as: -paragraph filling, mail reading with Rmail, shell handling, outlining, code -highlighting and browsing, and man page browsing. +@quotation +In a non-Mule world, a user can still have a multi-lingual editor, by +doing @code{(set-face-font "-*-iso8859-2" (current-buffer))} for all +their Latin-2 buffers, etc. +@end quotation -InfoDock questions, answers and discussion should go to the mail list -@iftex -@* -@end iftex -@email{infodock@@infodock.com}. Use -@email{infodock-request@@infodock.com} to be added or removed from the -list. Always include your InfoDock version number when sending help -requests. +For the related problem of @emph{inputting} non-ASCII characters in a +non-Mule XEmacs, @xref{Q3.0.6, How can you type in special characters +in XEmacs?}. -InfoDock is available across the Internet via anonymous FTP. To get -it, first move to a directory into which you want the InfoDock archive -files placed. We will call this <DIST-DIR>. +@node Q4.0.9, Q4.1.1, Q4.0.8, Display +@unnumberedsubsec Q4.0.9: Font selections in don't get saved after @code{Save Options}. -@example - cd <DIST-DIR> -@end example +@email{mannj@@ll.mit.edu, John Mann} writes: + +@quotation +You have to go to @samp{Options->Menubars} and unselect +@samp{Frame-Local Font Menu}. If this option is selected, font changes +are only applied to the @emph{current} frame and do @emph{not} get saved +when you save options. +@end quotation -Ftp to ftp.xemacs.org (Internet Host ID = 128.174.252.16): +Also, set the following in your @file{init.el}: -@example - prompt> ftp ftp.xemacs.org -@end example +@lisp +(setq options-save-faces t) +@end lisp -Login as @samp{anonymous} with your own <user-id>@@<site-name> as a password. +@unnumberedsec 4.1: Syntax Highlighting (Font Lock) -@example - Name (ftp.xemacs.org): anonymous - 331 Guest login ok, send your complete e-mail address as password. - Password: -<your-user-id>@@<your-domain> - 230 Guest login ok, access restrictions apply. -@end example +@node Q4.1.1, Q4.1.2, Q4.0.9, Display +@unnumberedsubsec Q4.1.1: How can I do source code highlighting using font-lock? -Move to the location of the InfoDock archives: +For most modes, font-lock is already set up and just needs to be turned +on. This can be done by adding the line: -@example - ftp> cd pub/infodock -@end example +@lisp +(require 'font-lock) +@end lisp -Set your transfer mode to binary: +to your @file{init.el}. (You can turn it on for the +current buffer and session only by @kbd{M-x font-lock-mode}.) See the +file @file{etc/sample.init.el} (@file{etc/sample.emacs} in XEmacs +versions prior to 21.4) for more information. -@example - ftp> bin - 200 Type set to I. -@end example +@c the old way: +@c (add-hook 'emacs-lisp-mode-hook 'turn-on-font-lock) +@c (add-hook 'dired-mode-hook 'turn-on-font-lock) -Turn off prompting: +See also @code{Syntax Highlighting} from the @code{Options} menu. +Remember to save options. -@example - ftp> prompt - Interactive mode off. -@end example +@node Q4.1.2, Q4.2.1, Q4.1.1, Display +@unnumberedsubsec Q4.1.2: How do I get @samp{More} Syntax Highlighting on by default? -Retrieve the InfoDock archives that you want, either by using a -@samp{get <file>} for each file you want or by using the following to -get a complete distribution, including all binaries: +Use the following code in your @file{init.el}: -@example - ftp> mget ID-INSTALL - ftp> mget id-* -@end example +@lisp +(setq-default font-lock-maximum-decoration t) +@end lisp -Close the FTP connection: +See also @code{Syntax Highlighting} from the @code{Options} menu. +Remember to save options. -@example - ftp> quit - 221 Goodbye. -@end example +@unnumberedsec 4.2: The Modeline -Read the @file{ID-INSTALL} file which you just retrieved for -step-by-step installation instructions. +@node Q4.2.1, Q4.2.2, Q4.1.2, Display +@unnumberedsubsec Q4.2.1: How can I make the modeline go away? -@node Q4.7.1, Q4.7.2, Q4.6.1, Subsystems -@unnumberedsec 4.7: Other Unbundled Packages -@unnumberedsubsec Q4.7.1: What is AUC TeX? Where do you get it? +@lisp +(set-specifier has-modeline-p nil) +@end lisp -AUC TeX is a package written by @email{abraham@@dina.kvl.dk, Per Abrahamsen}. -Starting with XEmacs 19.16, AUC TeX is bundled with XEmacs. The -following information is from the @file{README} and website. +@node Q4.2.2, Q4.2.3, Q4.2.1, Display +@unnumberedsubsec Q4.2.2: How do you have XEmacs display the line number in the modeline? -AUC TeX is an extensible package that supports writing and formatting -TeX files for most variants of GNU Emacs. Many different macro packages -are supported, including AMS TeX, LaTeX, and TeXinfo. +Add the following line to your @file{init.el} file to +display the line number: -The most recent version is always available by ftp at -@iftex -@* -@end iftex -@uref{ftp://sunsite.dk/packages/auctex/auctex.tar.gz}. +@lisp +(line-number-mode 1) +@end lisp + +Use the following to display the column number: -In case you don't have access to anonymous ftp, you can get it by an -email request to @email{ftpmail@@decwrl.dec.com}. +@lisp +(column-number-mode 1) +@end lisp -WWW users may want to check out the AUC TeX page at +Or select from the @code{Options} menu @iftex @* @end iftex -@uref{http://sunsite.dk/auctex/}. - -@node Q4.7.2, Q4.7.3, Q4.7.1, Subsystems -@unnumberedsubsec Q4.7.2: Are there any Emacs Lisp Spreadsheets? - -Yes. Check out @dfn{dismal} (which stands for Dis' Mode Ain't Lotus) at +@code{Advanced (Customize)->Emacs->Editing->Basics->Line Number Mode} +and/or @iftex @* @end iftex -@uref{ftp://cs.nyu.edu/pub/local/fox/dismal/}. - -@node Q4.7.3, Q4.7.4, Q4.7.2, Subsystems -@unnumberedsubsec Q4.7.3: [This question intentionally left blank] - -@node Q4.7.4, Q4.7.5, Q4.7.3, Subsystems -@unnumberedsubsec Q4.7.4: Problems installing AUC TeX. - -@email{vroonhof@@math.ethz.ch, Jan Vroonhof} writes: - -@quotation -AUC TeX works fine on both stock Emacs and XEmacs has been doing so for -a very very long time. This is mostly due to the work of -@email{abraham@@dina.kvl.dk, Per Abrahamsen} (clap clap) in particular his @file{easymenu} -package. Which leads to what is probably the problem... -@end quotation +@code{Advanced (Customize)->Emacs->Editing->Basics->Column Number Mode} -Most problems with AUC TeX are one of two things: +Or type @kbd{M-x customize @key{RET} editing-basics @key{RET}}. -@itemize @bullet -@item -The TeX-lisp-directory in @file{tex-site.el} and the makefile don't -match. +@node Q4.2.3, Q4.2.4, Q4.2.2, Display +@unnumberedsubsec Q4.2.3: How do I get XEmacs to put the time of day on the modeline? -Fix: make sure you configure AUC TeX properly @strong{before} installing. +Add the following line to your @file{init.el} file to +display the time: -@item -You have an old version of easymenu.el in your path. +@lisp +(display-time) +@end lisp -Fix: use @code{locate-library} and remove old versions to make sure it -@strong{only} finds the one that came with XEmacs. -@end itemize +See @code{Customize} from the @code{Options} menu for customization. +@node Q4.2.4, Q4.3.1, Q4.2.3, Display +@unnumberedsubsec Q4.2.4: How can I change the modeline color based on the mode used? -@node Q4.7.5, Q4.7.6, Q4.7.4, Subsystems -@unnumberedsubsec Q4.7.5: Is there a reason for an Emacs package not to be included in XEmacs? +You can use something like the following: -The reason for an Emacs package not to be included in XEmacs is -usually one or more of the following: +@lisp +(add-hook 'lisp-mode-hook + (lambda () + (set-face-background 'modeline "red" (current-buffer)))) +@end lisp -@enumerate -@item -The package has not been ported to XEmacs. This will typically happen -when it uses GNU-Emacs-specific features, which make it fail under -XEmacs. +Then, when editing a Lisp file (i.e. when in Lisp mode), the modeline +colors change from the default set in your @file{init.el}. +The change will only be made in the buffer you just entered (which +contains the Lisp file you are editing) and will not affect the modeline +colors anywhere else. -Porting a package to XEmacs can range from a trivial amount of change to -a partial or full rewrite. Fortunately, the authors of modern packages -usually choose to support both Emacsen themselves. +Notes: -@item -The package has been decided not to be appropriate for XEmacs. It may -have an equivalent or better replacement within XEmacs, in which case -the developers may choose not to burden themselves with supporting an -additional package. +@itemize @bullet -Each package bundled with XEmacs means more work for the maintainers, -whether they want it or not. If you are ready to take over the -maintenance responsibilities for the package you port, be sure to say -so---we will more likely include it. +@item The hook is the mode name plus @code{-hook}. eg. c-mode-hook, +c++-mode-hook, emacs-lisp-mode-hook (used for your +@file{init.el} or a @file{xx.el} file), +lisp-interaction-mode-hook (the @samp{*scratch*} buffer), +text-mode-hook, etc. @item -The package simply hasn't been noted by the XEmacs development. If -that's the case, the messages like yours are very useful for attracting -our attention. +Be sure to use @code{add-hook}, not @code{(setq c-mode-hook xxxx)}, +otherwise you will erase anything that anybody has already put on the +hook. @item -The package was noted by the developers, but they simply haven't yet -gotten around to including/porting it. Wait for the next release or, -even better, offer your help. It will be gladly accepted and -appreciated. -@end enumerate - -@node Q4.7.6, Q4.7.7, Q4.7.5, Subsystems -@unnumberedsubsec Q4.7.5: Is there a MatLab mode? - -Yes, a matlab mode and other items are available at the -@uref{ftp://ftp.mathworks.com/pub/contrib/emacs_add_ons, -MathWorks' emacs_add_ons ftp directory}. - -@node Q4.7.7, , Q4.7.6, Subsystems -@unnumberedsubsec Q4.7.7: Can I edit files on other hosts? - -Yes. Of course XEmacs can use any network file system (such as NFS or -Windows file sharing) you have available, and includes some -optimizations and safety features appropriate to those environments. - -It is also possible to transparently edit files via FTP, ssh, or rsh. That -is, XEmacs makes a local copy using the transport in the background, and -automatically refreshes the remote original from that copy when you save -it. XEmacs also is capable of doing file system manipulations like -creating and removing directories and files. The FTP interface is -provided by the standard @samp{efs} package @ref{Top, EFS, , efs}. The -ssh/rsh interface is provided by the optional @samp{tramp} package -@ref{Top, TRAMP, , tramp}. +You can also do @code{(set-face-font 'modeline @var{font})}, +eg. @code{(set-face-font 'modeline "*bold-r-normal*140-100-100*" +(current-buffer))} if you wish the modeline font to vary based on the +current mode. +@end itemize -@node Miscellaneous, MS Windows, Subsystems, Top -@unnumbered 5 The Miscellaneous Stuff +There are additional modeline faces, @code{modeline-buffer-id}, +@code{modeline-mousable}, and @code{modeline-mousable-minor-mode}, which +you may want to customize. -This is part 5 of the XEmacs Frequently Asked Questions list. This -section is devoted to anything that doesn't fit neatly into the other -sections. +@unnumberedsec 4.3: The Cursor -@menu -Major & Minor Modes: -* Q5.0.1:: How can I do source code highlighting using font-lock? -* Q5.0.2:: I do not like cc-mode. How do I use the old c-mode? -* Q5.0.3:: How do I get @samp{More} Syntax Highlighting on by default? -* Q5.0.4:: How can I enable auto-indent and/or Filladapt? -* Q5.0.5:: How can I get XEmacs to come up in text/auto-fill mode by default? -* Q5.0.6:: How do I start up a second shell buffer? -* Q5.0.7:: Telnet from shell filters too much. -* Q5.0.8:: Why does edt emulation not work? -* Q5.0.9:: How can I emulate VI and use it as my default mode? -* Q5.0.10:: [This question intentionally left blank] -* Q5.0.11:: [This question intentionally left blank] -* Q5.0.12:: How do I disable gnuserv from opening a new frame? -* Q5.0.13:: How do I start gnuserv so that each subsequent XEmacs is a client? -* Q5.0.14:: Strange things are happening in Shell Mode. -* Q5.0.15:: Where do I get the latest CC Mode? -* Q5.0.16:: I find auto-show-mode disconcerting. How do I turn it off? -* Q5.0.17:: How can I get two instances of info? -* Q5.0.18:: [This question intentionally left blank] -* Q5.0.19:: Is there something better than LaTeX mode? -* Q5.0.20:: Is there a way to start a new XEmacs if there's no gnuserv running, and otherwise use gnuclient? - -Emacs Lisp Programming Techniques: -* Q5.1.1:: The difference in key sequences between XEmacs and GNU Emacs? -* Q5.1.2:: Can I generate "fake" keyboard events? -* Q5.1.3:: Could you explain @code{read-kbd-macro} in more detail? -* Q5.1.4:: What is the performance hit of @code{let}? -* Q5.1.5:: What is the recommended use of @code{setq}? -* Q5.1.6:: What is the typical misuse of @code{setq}? -* Q5.1.7:: I like the @code{do} form of cl, does it slow things down? -* Q5.1.8:: I like recursion, does it slow things down? -* Q5.1.9:: How do I put a glyph as annotation in a buffer? -* Q5.1.10:: @code{map-extents} won't traverse all of my extents! -* Q5.1.11:: My elisp program is horribly slow. Is there an easy way to find out where it spends time? - -Sound: -* Q5.2.1:: How do I turn off the sound? -* Q5.2.2:: How do I get funky sounds instead of a boring beep? -* Q5.2.3:: What's NAS, how do I get it? -* Q5.2.4:: Sunsite sounds don't play. - -Miscellaneous: -* Q5.3.1:: How do you make XEmacs indent CL if-clauses correctly? -* Q5.3.2:: [This question intentionally left blank] -* Q5.3.3:: How can I print WYSIWYG a font-locked buffer? -* Q5.3.4:: Getting @kbd{M-x lpr} to work with postscript printer. -* Q5.3.5:: How do I specify the paths that XEmacs uses for finding files? -* Q5.3.6:: [This question intentionally left blank] -* Q5.3.7:: Can I have the end of the buffer delimited in some way? -* Q5.3.8:: How do I insert today's date into a buffer? -* Q5.3.9:: Are only certain syntactic character classes available for abbrevs? -* Q5.3.10:: How can I get those oh-so-neat X-Face lines? -* Q5.3.11:: How do I add new Info directories? -* Q5.3.12:: What do I need to change to make printing work? - -Mathematics: -* Q5.4.1:: What are bignums, ratios, and bigfloats in Lisp? -* Q5.4.2:: XEmacs segfaults when I use very big numbers! -* Q5.4.3:: Bignums are really slow! -* Q5.4.4:: Equal bignums don't compare as equal! What's going on? -@end menu +@node Q4.3.1, Q4.3.2, Q4.2.4, Display +@unnumberedsubsec Q4.3.1: Is there a way to make the bar cursor thicker? -@node Q5.0.1, Q5.0.2, Miscellaneous, Miscellaneous -@unnumberedsec 5.0: Major & Minor Modes -@unnumberedsubsec Q5.0.1: How can I do source code highlighting using font-lock? +I'd like to have the bar cursor a little thicker, as I tend to "lose" it +often. -For most modes, font-lock is already set up and just needs to be turned -on. This can be done by adding the line: +For a 1 pixel bar cursor, use: @lisp -(require 'font-lock) +(setq bar-cursor t) @end lisp -to your @file{init.el}/@file{.emacs}. (You can turn it on for the -current buffer and session only by @kbd{M-x font-lock-mode}.) See the -file @file{etc/sample.init.el} (@file{etc/sample.emacs} in XEmacs -versions prior to 21.4) for more information. +For a 2 pixel bar cursor, use: -@c the old way: -@c (add-hook 'emacs-lisp-mode-hook 'turn-on-font-lock) -@c (add-hook 'dired-mode-hook 'turn-on-font-lock) +@lisp +(setq bar-cursor 'anything-else) +@end lisp -See also @code{Syntax Highlighting} from the @code{Options} menu. -Remember to save options. +You can also change these with Customize. +Select from the @code{Options} menu +@code{Advanced (Customize)->Emacs->Environment->Display->Bar Cursor...} or type +@kbd{M-x customize @key{RET} display @key{RET}}. -@node Q5.0.2, Q5.0.3, Q5.0.1, Miscellaneous -@unnumberedsubsec Q5.0.2: I do not like cc-mode. How do I use the old c-mode? +You can use a color to make it stand out better: -Well, first off, consider if you really want to do this. cc-mode is -much more powerful than the old c-mode. If you're having trouble -getting your old offsets to work, try using @code{c-set-offset} instead. -You might also consider using the package @code{cc-compat}. +@example +Emacs*cursorColor: Red +@end example -But, if you still insist, add the following lines to your @file{init.el}/@file{.emacs}: +@node Q4.3.2, Q4.3.3, Q4.3.1, Display +@unnumberedsubsec Q4.3.2: Is there a way to get back the block cursor? @lisp -(fmakunbound 'c-mode) -(makunbound 'c-mode-map) -(fmakunbound 'c++-mode) -(makunbound 'c++-mode-map) -(makunbound 'c-style-alist) -(load-library "old-c-mode") -(load-library "old-c++-mode") +(setq bar-cursor nil) @end lisp -This must be done before any other reference is made to either c-mode or -c++-mode. +You can also change this with Customize. +Select from the @code{Options} menu +@code{Advanced (Customize)->Emacs->Environment->Display->Bar Cursor...} or type +@kbd{M-x customize @key{RET} display @key{RET}}. -@node Q5.0.3, Q5.0.4, Q5.0.2, Miscellaneous -@unnumberedsubsec Q5.0.3: How do I get @samp{More} Syntax Highlighting on by default? +@node Q4.3.3, Q4.4.1, Q4.3.2, Display +@unnumberedsubsec Q4.3.3: Can I make the cursor blink? -Use the following code in your @file{init.el}/@file{.emacs}: +Yes, like this: @lisp -(setq-default font-lock-maximum-decoration t) +(blink-cursor-mode) @end lisp -@c In versions of XEmacs prior to 19.14, you had to use a kludgy solution -@c like this: -@c -@c @lisp -@c (setq c-font-lock-keywords c-font-lock-keywords-2 -@c c++-font-lock-keywords c++-font-lock-keywords-2 -@c lisp-font-lock-keywords lisp-font-lock-keywords-2) -@c @end lisp -@c -@c It will work for C, C++ and Lisp. -@c -See also @code{Syntax Highlighting} from the @code{Options} menu. -Remember to save options. +This function toggles between a steady cursor and a blinking cursor. +You may also set this mode from the menu bar by selecting +@samp{Options->Display->Blinking Cursor}. Remember to save options. -@node Q5.0.4, Q5.0.5, Q5.0.3, Miscellaneous -@unnumberedsubsec Q5.0.4: How can I enable auto-indent and/or Filladapt? +@unnumberedsec 4.4: The Menubar -Put the following line in your @file{init.el}/@file{.emacs}: +@node Q4.4.1, Q4.4.2, Q4.3.3, Display +@unnumberedsubsec Q4.4.1: How do I get rid of the menubar? @lisp -(setq indent-line-function 'indent-relative-maybe) +(set-specifier menubar-visible-p nil) @end lisp -If you want to get fancy, try the @code{filladapt} package available -standard with XEmacs. Put this into your @file{init.el}/@file{.emacs}: +@node Q4.4.2, Q4.4.3, Q4.4.1, Display +@unnumberedsubsec Q4.4.2: How can I customize the menubar? + +For an extensive menubar, add this line to your @file{init.el}: @lisp -(require 'filladapt) -(setq-default filladapt-mode t) -(add-hook 'c-mode-hook 'turn-off-filladapt-mode) +(load "big-menubar") @end lisp -This will enable Filladapt for all modes except C mode, where it doesn't -work well. To turn Filladapt on only in particular major modes, remove -the @code{(setq-default ...)} line and use -@code{turn-on-filladapt-mode}, like this: +If you'd like to write your own, this file provides as good a set of +examples as any to start from. The file is located in edit-utils +package. + +@node Q4.4.3, Q4.4.4, Q4.4.2, Display +@unnumberedsubsec Q4.4.3: How do I enable use of the keyboard (@kbd{Alt}) to access menu items? + +#### Write me. + +@node Q4.4.4, Q4.4.5, Q4.4.3, Display +@unnumberedsubsec Q4.4.4: How do I control how many buffers are listed in the menu @code{Buffers List}? + +Add the following to your @file{init.el} (suit to fit): @lisp -(add-hook 'text-mode-hook 'turn-on-filladapt-mode) +(setq buffers-menu-max-size 20) @end lisp -You can customize filling and adaptive filling with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Editing->Fill->Fill...} -or type @kbd{M-x customize @key{RET} fill @key{RET}}. +For no limit, use an argument of @samp{nil}. -Note that well-behaving text-lookalike modes will run -@code{text-mode-hook} by default (e.g. that's what Message does). For -the nasty ones, you'll have to provide the @code{add-hook}s yourself. +You can also change this with Customize. Select from the +@code{Options} menu +@code{Advanced (Customize)->Emacs->Environment->Menu->Buffers Menu->Max Size...} +or type @kbd{M-x customize @key{RET} buffers-menu @key{RET}}. -Please note that the @code{fa-extras} package is no longer useful. +@node Q4.4.5, Q4.5.1, Q4.4.4, Display +@unnumberedsubsec Q4.4.5: Resources like @code{Emacs*menubar*font} are not working? -@node Q5.0.5, Q5.0.6, Q5.0.4, Miscellaneous -@unnumberedsubsec Q5.0.5: How can I get XEmacs to come up in text/auto-fill mode by default? +I am trying to use a resource like @code{Emacs*menubar*font} to set the +font of the menubar but it's not working. -Try the following lisp in your @file{init.el}/@file{.emacs}: +In Motif, the use of @samp{font} resources is obsoleted in order to +support internationalization. If you are using the real Motif menubar, +this resource is not recognized at all; you have to say: -@lisp -(setq default-major-mode 'text-mode) -(setq text-mode-hook 'turn-on-auto-fill) -@end lisp +@example +Emacs*menubar*fontList: FONT +@end example -@strong{WARNING}: note that changing the value of -@code{default-major-mode} from @code{fundamental-mode} can break a large -amount of built-in code that expects newly created buffers to be in -@code{fundamental-mode}. (Changing from @code{fundamental-mode} to -@code{text-mode} might not wreak too much havoc, but changing to -something more exotic like a lisp-mode would break many Emacs packages). +If you are using the Lucid menubar, for backward compatibility with +existing user configurations, the @samp{font} resource is recognized. +Since this is not supported by Motif itself, the code is a kludge and +the @samp{font} resource will be recognized only if the @samp{fontList} +resource resource is unset. This means that the resource -Note that Emacs by default starts up in buffer @code{*scratch*} in -@code{initial-major-mode}, which defaults to -@code{lisp-interaction-mode}. Thus adding the following form to your -Emacs init file will cause the initial @code{*scratch*} buffer to be put -into auto-fill'ed @code{text-mode}: +@example +*fontList: FONT +@end example -@lisp -(setq initial-major-mode - (lambda () - (text-mode) - (turn-on-auto-fill))) -@end lisp +will override -Note that after your init file is loaded, if -@code{inhibit-startup-message} is @code{nil} (the default) and the -startup buffer is @code{*scratch*} then the startup message will be -inserted into @code{*scratch*}; it will be removed after a timeout by -erasing the entire @code{*scratch*} buffer. Keep in mind this default -usage of @code{*scratch*} if you desire any prior manipulation of -@code{*scratch*} from within your Emacs init file. In particular, -anything you insert into @code{*scratch*} from your init file will be -later erased. Also, if you change the mode of the @code{*scratch*} -buffer, be sure that this will not interfere with possible later -insertion of the startup message (e.g. if you put @code{*scratch*} into -a nonstandard mode that has automatic font lock rules, then the startup -message might get fontified in a strange foreign manner, e.g. as code in -some programming language). +@example +Emacs*menubar*font: FONT +@end example -@node Q5.0.6, Q5.0.7, Q5.0.5, Miscellaneous -@unnumberedsubsec Q5.0.6: How do I start up a second shell buffer? +even though the latter is more specific. -In the @code{*shell*} buffer: +In non-Motif configurations using @samp{--with-mule} and +@samp{--with-xfs} it @emph{is} necessary to use the @code{fontSet} +resource @emph{instead of} the @code{font} resource. The backward +compatibility kludge was never implemented for non-Motif builds. +Example: -@lisp -M-x rename-buffer @key{RET} *shell-1* @key{RET} -M-x shell RET -@end lisp +@example +*fontSet: FONT +@end example -This will then start a second shell. The key is that no buffer named -@samp{*shell*} can exist. It might be preferable to use @kbd{M-x -rename-uniquely} to rename the @code{*shell*} buffer instead of @kbd{M-x -rename-buffer}. +@unnumberedsec 4.5: The Toolbar -Alternately, you can set the variable @code{shell-multiple-shells}. -If the value of this variable is non-nil, each time shell mode is invoked, -a new shell is made +@node Q4.5.1, Q4.5.2, Q4.4.5, Display +@unnumberedsubsec Q4.5.1: How do I get rid of the toolbar? -@node Q5.0.7, Q5.0.8, Q5.0.6, Miscellaneous -@unnumberedsubsec Q5.0.7: Telnet from shell filters too much +#### Write me. -I'm using the Emacs @kbd{M-x shell} function, and I would like to invoke -and use a telnet session within it. Everything works fine except that -now all @samp{^M}'s are filtered out by Emacs. Fixes? +@node Q4.5.2, Q4.5.3, Q4.5.1, Display +@unnumberedsubsec Q4.5.2: How can I customize the toolbar? -Use @kbd{M-x rsh} or @kbd{M-x telnet} to open remote sessions rather -than doing rsh or telnet within the local shell buffer. Starting with -XEmacs-20.3 you can also use @kbd{M-x ssh} to open secure remote session -if you have @code{ssh} installed. +#### Write me. -@node Q5.0.8, Q5.0.9, Q5.0.7, Miscellaneous -@unnumberedsubsec Q5.0.8: Why does edt emulation not work? +@node Q4.5.3, Q4.5.4, Q4.5.2, Display +@unnumberedsubsec Q4.5.3: How can I bind a key to a function to toggle the toolbar? -We don't know, but you can use tpu-edt emulation instead, which works -fine and is a little fancier than the standard edt emulation. To do -this, add the following line to your @file{init.el}/@file{.emacs}: +Try something like: @lisp -(tpu-edt) +(defun my-toggle-toolbar () + (interactive) + (set-specifier default-toolbar-visible-p + (not (specifier-instance default-toolbar-visible-p)))) +(global-set-key "\C-xT" 'my-toggle-toolbar) @end lisp -If you don't want it to replace @kbd{C-h} with an edt-style help menu -add this as well: +@ignore +@c Probably not relevant any more +There are redisplay bugs in 19.14 that may make the preceding result in +a messed-up display, especially for frames with multiple windows. You +may need to resize the frame before XEmacs completely realizes the +toolbar is really gone. +@end ignore -@lisp -(global-set-key [(control h)] 'help-for-help) -@end lisp +Thanks to @email{martin@@xemacs.org, Martin Buchholz} for the correct +code. -@node Q5.0.9, Q5.0.10, Q5.0.8, Miscellaneous -@unnumberedsubsec Q5.0.9: How can I emulate VI and use it as my default mode? +@node Q4.5.4, Q4.6.1, Q4.5.3, Display +@unnumberedsubsec Q4.5.4: @samp{Can't instantiate image error...} in toolbar -Our recommended VI emulator is viper. To make viper-mode the default, -add this to your @file{init.el}/@file{.emacs}: +@email{expt@@alanine.ram.org, Dr. Ram Samudrala} writes: -@lisp -(viper-mode) -@end lisp +I just installed the XEmacs (20.4-2) RPMS that I downloaded from +@uref{http://www.xemacs.org/}. Everything works fine, except that when +I place my mouse over the toolbar, it beeps and gives me this message: -@email{kifer@@CS.SunySB.EDU, Michael Kifer} writes: +@example + Can't instantiate image (probably cached): + [xbm :mask-file "/usr/include/X11/bitmaps/leftptrmsk :mask-data + (16 16 <strange control characters> ... +@end example +@email{kyle_jones@@wonderworks.com, Kyle Jones} writes: @quotation -This should be added as close to the top of @file{init.el}/@file{.emacs} as you can get -it, otherwise some minor modes may not get viper-ized. +This is problem specific to some Chips and Technologies video +chips, when running XFree86. Putting + +@code{Option "sw_cursor"} + +in @file{XF86Config} gets rid of the problem. @end quotation -@node Q5.0.10, Q5.0.11, Q5.0.9, Miscellaneous -@unnumberedsubsec Q5.0.10: [This question intentionally left blank] +@unnumberedsec 4.6: Scrollbars and Scrolling -Obsolete question, left blank to avoid renumbering +@node Q4.6.1, Q4.6.2, Q4.5.4, Display +@unnumberedsubsec Q4.6.1: How can I disable the scrollbar? -@node Q5.0.11, Q5.0.12, Q5.0.10, Miscellaneous -@unnumberedsubsec Q5.0.11: [This question intentionally left blank] +To disable them for all frames, add the following line to +your @file{.Xresources}: -Obsolete question, left blank to avoid renumbering +@example +Emacs.scrollBarWidth: 0 +@end example -@node Q5.0.12, Q5.0.13, Q5.0.11, Miscellaneous -@unnumberedsubsec Q5.0.12: How do I disable gnuserv from opening a new frame? +Or select @samp{Options->Display->Scrollbars}. +Remember to save options. -If you set the @code{gnuserv-frame} variable to the frame that should be -used to display buffers that are pulled up, a new frame will not be -created. For example, you could put +To turn the scrollbar off on a per-frame basis, use the following +function: @lisp -(setq gnuserv-frame (selected-frame)) +(set-specifier scrollbar-width 0 (selected-frame)) @end lisp -early on in your @file{init.el}/@file{.emacs}, to ensure that the first frame created -is the one used for your gnuserv buffers. +You can actually turn the scrollbars on at any level you want by +substituting for (selected-frame) in the above command. For example, to +turn the scrollbars off only in a single buffer: -There is an option to set the gnuserv target to the current frame. See -@code{Options->Display->"Other Window" Location->Make Current Frame Gnuserv Target} +@lisp +(set-specifier scrollbar-width 0 (current-buffer)) +@end lisp -Starting with XEmacs-20.3 you can also change this with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Environment->Gnuserv->Gnuserv Frame...} -or type @kbd{M-x customize @key{RET} gnuserv @key{RET}}. +@node Q4.6.2, Q4.6.3, Q4.6.1, Display +@unnumberedsubsec Q4.6.2: How can I change the scrollbar width? +#### Write me. -@node Q5.0.13, Q5.0.14, Q5.0.12, Miscellaneous -@unnumberedsubsec Q5.0.13: How do I start gnuserv so that each subsequent XEmacs is a client? +@node Q4.6.3, Q4.6.4, Q4.6.2, Display +@unnumberedsubsec Q4.6.3: How can I use resources to change scrollbar colors? -Put the following in your @file{init.el}/@file{.emacs} file to start the server: +Here's a recap of how to use resources to change your scrollbar colors: -@lisp -(gnuserv-start) -@end lisp +@example +! Motif scrollbars -Start your first XEmacs as usual. After that, you can do: +Emacs*XmScrollBar.Background: skyblue +Emacs*XmScrollBar.troughColor: lightgray -@example -gnuclient randomfilename +! Athena scrollbars + +Emacs*Scrollbar.Foreground: skyblue +Emacs*Scrollbar.Background: lightgray @end example -from the command line to get your existing XEmacs process to open a new -frame and visit randomfilename in that window. When you're done editing -randomfilename, hit @kbd{C-x #} to kill the buffer and get rid of the -frame. +Note the capitalization of @code{Scrollbar} for the Athena widget. -See also man page of gnuclient. +@node Q4.6.4, Q4.6.5, Q4.6.3, Display +@unnumberedsubsec Q4.6.4: Moving the scrollbar can move the point; can I disable this? -@node Q5.0.14, Q5.0.15, Q5.0.13, Miscellaneous -@unnumberedsubsec Q5.0.14: Strange things are happening in Shell Mode. +When I move the scrollbar in an XEmacs window, it moves the point as +well, which should not be the default behavior. Is this a bug or a +feature? Can I disable it? -Sometimes (i.e. it's not repeatable, and I can't work out why it -happens) when I'm typing into shell mode, I hit return and only a -portion of the command is given to the shell, and a blank prompt is -returned. If I hit return again, the rest of the previous command is -given to the shell. +The current behavior is a feature, not a bug. Point remains at the same +buffer position as long as that position does not scroll off the screen. +In that event, point will end up in either the upper-left or lower-left +hand corner. -@email{martin@@xemacs.org, Martin Buchholz} writes: +This cannot be changed. -@quotation -There is a known problem with interaction between @code{csh} and the -@code{filec} option and XEmacs. You should add the following to your -@file{.cshrc}: +@node Q4.6.5, Q4.6.6, Q4.6.4, Display +@unnumberedsubsec Q4.6.5: Scrolling one line at a time. + +Can the cursor keys scroll the screen a line at a time, rather than the +default half page jump? I tend it to find it disorienting. + +Use the following: + +@lisp +(setq scroll-step 1) +@end lisp + +You can also change this with Customize. Select from the +@code{Options} menu +@code{Advanced (Customize)->Emacs->Environment->Windows->Scroll Step...} +or type @kbd{M-x customize @key{RET} windows @key{RET}}. + +@node Q4.6.6, Q4.6.7, Q4.6.5, Display +@unnumberedsubsec Q4.6.6: How can I turn off automatic horizontal scrolling in specific modes? -@example -if ( "$TERM" == emacs || "$TERM" == unknown ) unset filec -@end example -@end quotation +Do @code{(setq truncate-lines t)} in the mode-hooks for any modes +in which you want lines truncated. -@node Q5.0.15, Q5.0.16, Q5.0.14, Miscellaneous -@unnumberedsubsec Q5.0.15: Where do I get the latest CC Mode? +More precisely: If @code{truncate-lines} is nil, horizontal scrollbars +will never appear. Otherwise, they will appear only if the value of +@code{scrollbar-height} for that buffer/window/etc. is non-zero. If you +do -@email{bwarsaw@@cnri.reston.va.us, Barry A. Warsaw} writes: +@lisp +(set-specifier scrollbar-height 0) +@end lisp -@quotation -This can be had from @uref{http://www.python.org/emacs/}. -@end quotation +then horizontal scrollbars will not appear in truncated buffers unless +the package specifically asked for them. -@node Q5.0.16, Q5.0.17, Q5.0.15, Miscellaneous -@unnumberedsubsec Q5.0.16: I find auto-show-mode disconcerting. How do I turn it off? +@node Q4.6.7, Q4.7.1, Q4.6.6, Display +@unnumberedsubsec Q4.6.7: I find auto-show-mode disconcerting. How do I turn it off? @code{auto-show-mode} controls whether or not a horizontal scrollbar magically appears when a line is too long to be displayed. This is enabled by default. To turn it off, put the following in your -@file{init.el}/@file{.emacs}: +@file{init.el}: @lisp (setq auto-show-mode nil) (setq-default auto-show-mode nil) @end lisp -@node Q5.0.17, Q5.0.18, Q5.0.16, Miscellaneous -@unnumberedsubsec Q5.0.17: How can I get two instances of info? +@unnumberedsec 4.7: The Gutter Tabs, The Progress Bar, Widgets -Before 21.4, you can't. The @code{info} package does not provide for -multiple info buffers. In 21.4, this should be fixed. #### how? +@node Q4.7.1, Q4.7.2, Q4.6.7, Display +@unnumberedsubsec Q4.7.1: How can I disable the gutter tabs? -@node Q5.0.18, Q5.0.19, Q5.0.17, Miscellaneous -@unnumberedsubsec Q5.0.18: [This question intentionally left blank] +#### Write me. -@node Q5.0.19, Q5.0.20, Q5.0.18, Miscellaneous -@unnumberedsubsec Q5.0.19: Is there something better than LaTeX mode? +@node Q4.7.2, Q4.7.3, Q4.7.1, Display +@unnumberedsubsec Q4.7.2: How can I disable the progress bar? -@email{dak@@fsnif.neuroinformatik.ruhr-uni-bochum.de, David Kastrup} writes: +#### Write me. -@quotation -The standard TeX modes leave much to be desired, and are somewhat -leniently maintained. Serious TeX users use AUC TeX (@pxref{Q4.7.1}). -@end quotation +@node Q4.7.3, Q4.7.4, Q4.7.2, Display +@unnumberedsubsec Q4.7.3: There are bugs in the gutter or widgets. -@node Q5.0.20, Q5.1.1, Q5.0.19, Miscellaneous -@unnumberedsubsec Q5.0.20: Is there a way to start a new XEmacs if there's no gnuserv running, and otherwise use gnuclient? +#### Write me. -@email{vroonhof@@math.ethz.ch, Jan Vroonhof} writes: -@quotation -Here is one of the solutions, we have this in a script called -@file{etc/editclient.sh}. -@example - #!/bin/sh - if gnuclient -batch -eval t >/dev/null 2>&1 - then - exec gnuclient $@{1+"$@@"@} - else - xemacs -unmapped -f gnuserv-start & - until gnuclient -batch -eval t >/dev/null 2>&1 - do - sleep 1 - done - exec gnuclient $@{1+"$@@"@} - fi -@end example +@node Q4.7.4, , Q4.7.3, Display +@unnumberedsubsec Q4.7.4: How can I customize the gutter or gutter tabs? -Note that there is a known problem when running XEmacs and 'gnuclient --nw' on the same TTY. -@end quotation +#### Write me. -@node Q5.1.1, Q5.1.2, Q5.0.20, Miscellaneous -@unnumberedsec 5.1: Emacs Lisp Programming Techniques -@unnumberedsubsec Q5.1.1: What is the difference in key sequences between XEmacs and GNU Emacs? +@node External Subsystems, Internet, Display, Top +@unnumbered 5 Interfacing with the Operating System and External Devices -@email{clerik@@naggum.no, Erik Naggum} writes; +This is part 5 of the XEmacs Frequently Asked Questions list. This +section is devoted to the various ways that XEmacs interfaces with the +operating system, with other processes and with external devices such +as speakers and the printer. -@quotation -Emacs has a legacy of keyboards that produced characters with modifier -bits, and therefore map a variety of input systems into this scheme even -today. XEmacs is instead optimized for X events. This causes an -incompatibility in the way key sequences are specified, but both Emacs -and XEmacs will accept a key sequence as a vector of lists of modifiers -that ends with a key, e.g., to bind @kbd{M-C-a}, you would say -@code{[(meta control a)]} in both Emacsen. XEmacs has an abbreviated -form for a single key, just (meta control a). Emacs has an abbreviated -form for the Control and the Meta modifiers to string-characters (the -ASCII characters), as in @samp{\M-\C-a}. XEmacs users need to be aware -that the abbreviated form works only for one-character key sequences, -while Emacs users need to be aware that the string-character is rather -limited. Specifically, the string-character can accommodate only 256 -different values, 128 of which have the Meta modifier and 128 of which -have not. In each of these blocks, only 32 characters have the Control -modifier. Whereas @code{[(meta control A)]} differs from @code{[(meta -control a)]} because the case differs, @samp{\M-\C-a} and @samp{\M-\C-A} -do not. Programmers are advised to use the full common form, both -because it is more readable and less error-prone, and because it is -supported by both Emacsen. -@end quotation +@menu +5.0: X Window System and Resources +* Q5.0.1:: Where is a list of X resources? +* Q5.0.2:: How can I detect a color display? +* Q5.0.3:: How can I get the icon to just say @samp{XEmacs}? +* Q5.0.4:: How can I have the window title area display the full path? +* Q5.0.5:: @samp{xemacs -name junk} doesn't work? +* Q5.0.6:: @samp{-iconic} doesn't work. + +5.1: Microsoft Windows +* Q5.1.1:: Does XEmacs rename all the @samp{win32-*} symbols to @samp{w32-*}? +* Q5.1.2:: How do I get Windows Explorer to associate a file type with XEmacs? + +5.2: Printing +* Q5.2.1:: What do I need to change to make printing work? +* Q5.2.2:: How can I print WYSIWYG a font-locked buffer? +* Q5.2.3:: Getting @kbd{M-x lpr} to work with postscript printer. +* Q5.2.4:: Can you print under MS Windows? + +5.3: Sound +* Q5.3.1:: How do I turn off the sound? +* Q5.3.2:: How do I get funky sounds instead of a boring beep? +* Q5.3.3:: What are NAS and ESD (EsounD)? +* Q5.3.4:: Sunsite sounds don't play. + +5.4: Running an Interior Shell, Invoking Subprocesses +* Q5.4.1:: What is an interior shell? +* Q5.4.2:: How do I start up a second shell buffer? +* Q5.4.3:: Telnet from shell filters too much +* Q5.4.4:: Strange things are happening in Shell Mode. +* Q5.4.5:: XEmacs complains "No such file or directory, diff" + +5.5: Multiple Device Support +* Q5.5.1:: How do I open a frame on another screen of my multi-headed display? +* Q5.5.2:: Can I really connect to a running XEmacs after calling up over a modem? How? +* Q5.5.3:: How do I disable gnuserv from opening a new frame? +* Q5.5.4:: How do I start gnuserv so that each subsequent XEmacs is a client? +* Q5.5.5:: Is there a way to start a new XEmacs if there's no gnuserv running, and otherwise use gnuclient? +@end menu -Another (even safer) way to be sure of the key-sequences is to use the -@code{read-kbd-macro} function, which takes a string like @samp{C-c -<up>}, and converts it to the internal key representation of the Emacs -you use. The function is available both on XEmacs and GNU Emacs. +@unnumberedsec 5.0: X Window System and Resources -@node Q5.1.2, Q5.1.3, Q5.1.1, Miscellaneous -@unnumberedsubsec Q5.1.2: Can I generate "fake" keyboard events? +@node Q5.0.1, Q5.0.2, External Subsystems, External Subsystems +@unnumberedsubsec Q5.0.1: Where is a list of X resources? -I wonder if there is an interactive function that can generate -@dfn{fake} keyboard events. This way, I could simply map them inside -XEmacs. +Search through the @file{NEWS} file for @samp{X Resources}. A fairly +comprehensive list is given after it. -This seems to work: +In addition, an @file{app-defaults} file @file{etc/Emacs.ad} is +supplied, listing the defaults. The file @file{etc/sample.Xresources} +gives a different set of defaults that you might consider for +installation in your @file{~/.Xresources} file. It is nearly the same +as @file{etc/Emacs.ad}, but a few entries are altered. Be careful about +installing the contents of this file into your @file{.Xresources} (or +legacy @file{.Xdefaults}) file if you use GNU Emacs under X11 as well. -@lisp -(defun cg--generate-char-event (ch) - "Generate an event, as if ch has been typed" - (dispatch-event (character-to-event ch))) +@node Q5.0.2, Q5.0.3, Q5.0.1, External Subsystems +@unnumberedsubsec Q5.0.2: How can I detect a color display? -;; Backspace and Delete stuff -(global-set-key [backspace] - (lambda () (interactive) (cg--generate-char-event 127))) -(global-set-key [unknown_keysym_0x4] - (lambda () (interactive) (cg--generate-char-event 4))) +You can test the return value of the function @code{(device-class)}, as +in: + +@lisp +(when (eq (device-class) 'color) + (set-face-foreground 'font-lock-comment-face "Grey") + (set-face-foreground 'font-lock-string-face "Red") + .... + ) @end lisp -@node Q5.1.3, Q5.1.4, Q5.1.2, Miscellaneous -@unnumberedsubsec Q5.1.3: Could you explain @code{read-kbd-macro} in more detail? +@node Q5.0.3, Q5.0.4, Q5.0.2, External Subsystems +@unnumberedsubsec Q5.0.3: How can I get the icon to just say @samp{XEmacs}? -The @code{read-kbd-macro} function returns the internal Emacs -representation of a human-readable string (which is its argument). -Thus: +I'd like the icon to just say @samp{XEmacs}, and not include the name of +the current file in it. -@lisp -(read-kbd-macro "C-c C-a") -@result{} [(control ?c) (control ?a)] +Add the following line to your @file{init.el}: -(read-kbd-macro "C-c C-. <up>") -@result{} [(control ?c) (control ?.) up] +@lisp +(setq frame-icon-title-format "XEmacs") @end lisp -In GNU Emacs the same forms will be evaluated to what GNU Emacs -understands internally---the sequences @code{"\C-x\C-c"} and @code{[3 -67108910 up]}, respectively. +@node Q5.0.4, Q5.0.5, Q5.0.3, External Subsystems +@unnumberedsubsec Q5.0.4: How can I have the window title area display the full path? -The exact @dfn{human-readable} syntax is defined in the docstring of -@code{edmacro-mode}. I'll repeat it here, for completeness. +I'd like to have the window title area display the full directory/name +of the current buffer file and not just the name. -@quotation -Format of keyboard macros during editing: +Add the following line to your @file{init.el}: -Text is divided into @dfn{words} separated by whitespace. Except for -the words described below, the characters of each word go directly as -characters of the macro. The whitespace that separates words is -ignored. Whitespace in the macro must be written explicitly, as in -@kbd{foo @key{SPC} bar @key{RET}}. +@lisp +(setq frame-title-format "%S: %f") +@end lisp -@itemize @bullet -@item -The special words @kbd{RET}, @kbd{SPC}, @kbd{TAB}, @kbd{DEL}, @kbd{LFD}, -@kbd{ESC}, and @kbd{NUL} represent special control characters. The -words must be written in uppercase. +A more sophisticated title might be: -@item -A word in angle brackets, e.g., @code{<return>}, @code{<down>}, or -@code{<f1>}, represents a function key. (Note that in the standard -configuration, the function key @code{<return>} and the control key -@key{RET} are synonymous.) You can use angle brackets on the words -@key{RET}, @key{SPC}, etc., but they are not required there. +@lisp +(setq frame-title-format + '("%S: " (buffer-file-name "%f" + (dired-directory dired-directory "%b")))) +@end lisp -@item -Keys can be written by their @sc{ascii} code, using a backslash followed -by up to six octal digits. This is the only way to represent keys with -codes above \377. +That is, use the file name, or the dired-directory, or the buffer name. -@item -One or more prefixes @kbd{M-} (meta), @kbd{C-} (control), @kbd{S-} -(shift), @kbd{A-} (alt), @kbd{H-} (hyper), and @kbd{s-} (super) may -precede a character or key notation. For function keys, the prefixes -may go inside or outside of the brackets: @code{C-<down>} @equiv{} -@code{<C-down>}. The prefixes may be written in any order: @kbd{M-C-x} -@equiv{} @kbd{C-M-x}. +@node Q5.0.5, Q5.0.6, Q5.0.4, External Subsystems +@unnumberedsubsec Q5.0.5: @samp{xemacs -name junk} doesn't work? -Prefixes are not allowed on multi-key words, e.g., @kbd{C-abc}, except -that the Meta prefix is allowed on a sequence of digits and optional -minus sign: @kbd{M--123} @equiv{} @kbd{M-- M-1 M-2 M-3}. +When I run @samp{xterm -name junk}, I get an xterm whose class name +according to xprop, is @samp{junk}. This is the way it's supposed to +work, I think. When I run @samp{xemacs -name junk} the class name is +not set to @samp{junk}. It's still @samp{emacs}. What does +@samp{xemacs -name} really do? The reason I ask is that my window +manager (fvwm) will make a window sticky and I use XEmacs to read my +mail. I want that XEmacs window to be sticky, without having to use the +window manager's function to set the window sticky. What gives? -@item -The @code{^} notation for control characters also works: @kbd{^M} -@equiv{} @kbd{C-m}. +@samp{xemacs -name} sets the application name for the program (that is, +the thing which normally comes from @samp{argv[0]}). Using @samp{-name} +is the same as making a copy of the executable with that new name. The +@code{WM_CLASS} property on each frame is set to the frame-name, and the +application-class. So, if you did @samp{xemacs -name FOO} and then +created a frame named @var{BAR}, you'd get an X window with WM_CLASS = +@code{( "BAR", "Emacs")}. However, the resource hierarchy for this +widget would be: -@item -Double angle brackets enclose command names: @code{<<next-line>>} is -shorthand for @kbd{M-x next-line @key{RET}}. +@example +Name: FOO .shell .container .BAR +Class: Emacs .TopLevelEmacsShell.EmacsManager.EmacsFrame +@end example -@item -Finally, @code{REM} or @code{;;} causes the rest of the line to be -ignored as a comment. -@end itemize +instead of the default -Any word may be prefixed by a multiplier in the form of a decimal number -and @code{*}: @code{3*<right>} @equiv{} @code{<right> <right> <right>}, -and @code{10*foo} @equiv{} -@iftex -@* -@end iftex -@code{foofoofoofoofoofoofoofoofoofoo}. +@example +Name: xemacs.shell .container .emacs +Class: Emacs .TopLevelEmacsShell.EmacsManager.EmacsFrame +@end example -Multiple text keys can normally be strung together to form a word, but -you may need to add whitespace if the word would look like one of the -above notations: @code{; ; ;} is a keyboard macro with three semicolons, -but @code{;;;} is a comment. Likewise, @code{\ 1 2 3} is four keys but -@code{\123} is a single key written in octal, and @code{< right >} is -seven keys but @code{<right>} is a single function key. When in doubt, -use whitespace. -@end quotation -@node Q5.1.4, Q5.1.5, Q5.1.3, Miscellaneous -@unnumberedsubsec Q5.1.4: What is the performance hit of @code{let}? +It is arguable that the first element of WM_CLASS should be set to the +application-name instead of the frame-name, but I think that's less +flexible, since it does not give you the ability to have multiple frames +with different WM_CLASS properties. Another possibility would be for +the default frame name to come from the application name instead of +simply being @samp{emacs}. However, at this point, making that change +would be troublesome: it would mean that many users would have to make +yet another change to their resource files (since the default frame name +would suddenly change from @samp{emacs} to @samp{xemacs}, or whatever +the executable happened to be named), so we'd rather avoid it. + +To make a frame with a particular name use: -In most cases, not noticeable. Besides, there's no avoiding -@code{let}---you have to bind your local variables, after all. Some -pose a question whether to nest @code{let}s, or use one @code{let} per -function. I think because of clarity and maintenance (and possible -future implementation), @code{let}-s should be used (nested) in a way to -provide the clearest code. +@lisp +(make-frame '((name . "the-name"))) +@end lisp -@node Q5.1.5, Q5.1.6, Q5.1.4, Miscellaneous -@unnumberedsubsec Q5.1.5: What is the recommended use of @code{setq}? +@node Q5.0.6, Q5.1.1, Q5.0.5, External Subsystems +@unnumberedsubsec Q5.0.6: @samp{-iconic} doesn't work. -@itemize @bullet -@item Global variables +When I start up XEmacs using @samp{-iconic} it doesn't work right. +Using @samp{-unmapped} on the command line, and setting the +@code{initiallyUnmapped} X Resource don't seem to help much either... -You will typically @code{defvar} your global variable to a default -value, and use @code{setq} to set it later. +@email{ben@@xemacs.org, Ben Wing} writes: -It is never a good practice to @code{setq} user variables (like -@code{case-fold-search}, etc.), as it ignores the user's choice -unconditionally. Note that @code{defvar} doesn't change the value of a -variable if it was bound previously. If you wish to change a -user-variable temporarily, use @code{let}: +@quotation +Ugh, this stuff is such an incredible mess that I've about given up +getting it to work. The principal problem is numerous window-manager +bugs... +@end quotation + +@unnumberedsec 5.1: Microsoft Windows -@lisp -(let ((case-fold-search nil)) - ... ; code with searches that must be case-sensitive - ...) -@end lisp +@node Q5.1.1, Q5.1.2, Q5.0.6, External Subsystems +@unnumberedsubsec Q5.1.1: Does XEmacs rename all the @samp{win32-*} symbols to @samp{w32-*}? -You will notice the user-variables by their docstrings beginning with an -asterisk (a convention). +In his flavor of Emacs 20, Richard Stallman has renamed all the @samp{win32-*} +symbols to @samp{w32-*}. Does XEmacs do the same? -@item Local variables +We consider such a move counter-productive, thus we do not use the +@samp{w32} prefix. (His rather questionable justification was that he +did not consider Windows to be a "winning" platform.) However, the name +@samp{Win32} is not particularly descriptive outside the Windows world, +and using just @samp{windows-} would be too generic. So we chose a +compromise, the prefix @samp{mswindows-} for Windows-related variables +and functions. -Bind them with @code{let}, which will unbind them (or restore their -previous value, if they were bound) after exiting from the @code{let} -form. Change the value of local variables with @code{setq} or whatever -you like (e.g. @code{incf}, @code{setf} and such). The @code{let} form -can even return one of its local variables. +Thus all the XEmacs variables and functions directly related to either +the Windows GUI or OS are prefixed @samp{mswindows-} (except for a +couple of debugging variables, prefixed @samp{debug-mswindows-}). From +an architectural perspective, however, we believe that this is mostly a +non-issue because there should be a very small number of +window-systems-specific variables anyway. Whenever possible, we try to +provide generic interfaces that apply to all window systems. -Typical usage: +@c not true: +@c The user variables +@c that share functionality with existing NT Emacs variables are be named +@c with our convention, but we provide the GNU Emacs names as +@c compatibility aliases. -@lisp -;; iterate through the elements of the list returned by -;; `hairy-function-that-returns-list' -(let ((l (hairy-function-that-returns-list))) - (while l - ... do something with (car l) ... - (setq l (cdr l)))) -@end lisp +@node Q5.1.2, Q5.2.1, Q5.1.1, External Subsystems +@unnumberedsubsec Q5.1.2: How do I get Windows Explorer to associate a file type with XEmacs? -Another typical usage includes building a value simply to work with it. +@unnumberedsubsubsec Associating a new file type with XEmacs. -@lisp -;; Build the mode keymap out of the key-translation-alist -(let ((inbox (file-truename (expand-file-name box))) - (i 0)) - ... code dealing with inbox ... - inbox) -@end lisp +In Explorer select @samp{View->Options->File Types}, press @samp{[New +Type...]} and fill in the dialog box, e.g.: -This piece of code uses the local variable @code{inbox}, which becomes -unbound (or regains old value) after exiting the form. The form also -returns the value of @code{inbox}, which can be reused, for instance: +@example + Description of type: Emacs Lisp source + Associated extension: el + Content Type (MIME): text/plain +@end example -@lisp -(setq foo-processed-inbox - (let .....)) -@end lisp -@end itemize +then press @samp{[New...]} and fill in the @samp{Action} dialog box as +follows: -@node Q5.1.6, Q5.1.7, Q5.1.5, Miscellaneous -@unnumberedsubsec Q5.1.6: What is the typical misuse of @code{setq} ? +@example + Action: + Open -A typical misuse is probably @code{setq}ing a variable that was meant to -be local. Such a variable will remain bound forever, never to be -garbage-collected. For example, the code doing: + Application used to perform action: + D:\Full\path\for\xemacs.exe "%1" -@lisp -(defun my-function (whatever) - (setq a nil) - ... build a large list ... - ... and exit ...) -@end lisp + [x] Use DDE -does a bad thing, as @code{a} will keep consuming memory, never to be -unbound. The correct thing is to do it like this: + DDE Message: + open("%1") -@lisp -(defun my-function (whatever) - (let (a) ; default initialization is to nil - ... build a large list ... - ... and exit, unbinding `a' in the process ...) -@end lisp + Application: + <leave blank> -Not only is this prettier syntactically, but it makes it possible for -Emacs to garbage-collect the objects which @code{a} used to reference. + DDE Application Not Running: + <leave blank> -Note that even global variables should not be @code{setq}ed without -@code{defvar}ing them first, because the byte-compiler issues warnings. -The reason for the warning is the following: + Topic: + <leave blank> +@end example -@lisp -(defun flurgoze nil) ; ok, global internal variable -... +@unnumberedsubsubsec Associating an existing file type with XEmacs. -(setq flurghoze t) ; ops! a typo, but semantically correct. - ; however, the byte-compiler warns. +In Explorer select @samp{View->Options->File Types}. Click on the file +type in the list and press @samp{[Edit...]}. If the file type already +has an @samp{Open} action, double click on it and fill in the +@samp{Action} dialog box as described above; otherwise create a new +action. -While compiling toplevel forms: -** assignment to free variable flurghoze -@end lisp +If the file type has more than one action listed, you probably want to +make the @samp{Open} action that you just edited the default by clicking on +it and pressing @samp{Set Default}. -@node Q5.1.7, Q5.1.8, Q5.1.6, Miscellaneous -@unnumberedsubsec Q5.1.7: I like the @code{do} form of cl, does it slow things down? +Note for Windows 2000 users: Under Windows 2000, get to @samp{File Types} +using @samp{Control Panel->Folder Options->File Types}. -It shouldn't. Here is what Dave Gillespie has to say about cl.el -performance: +@unnumberedsec 5.2: Printing -@quotation -Many of the advanced features of this package, such as @code{defun*}, -@code{loop}, and @code{setf}, are implemented as Lisp macros. In -byte-compiled code, these complex notations will be expanded into -equivalent Lisp code which is simple and efficient. For example, the -forms +@node Q5.2.1, Q5.2.2, Q5.1.2, External Subsystems +@unnumberedsubsec Q5.2.1: What do I need to change to make printing work? -@lisp -(incf i n) -(push x (car p)) -@end lisp +For regular printing there are two variables that can be customized. -are expanded at compile-time to the Lisp forms +@table @code +@item lpr-command +This should be set to a command that takes standard input and sends +it to a printer. Something like: @lisp -(setq i (+ i n)) -(setcar p (cons x (car p))) +(setq lpr-command "lp") @end lisp -which are the most efficient ways of doing these respective operations -in Lisp. Thus, there is no performance penalty for using the more -readable @code{incf} and @code{push} forms in your compiled code. - -@emph{Interpreted} code, on the other hand, must expand these macros -every time they are executed. For this reason it is strongly -recommended that code making heavy use of macros be compiled. (The -features labelled @dfn{Special Form} instead of @dfn{Function} in this -manual are macros.) A loop using @code{incf} a hundred times will -execute considerably faster if compiled, and will also garbage-collect -less because the macro expansion will not have to be generated, used, -and thrown away a hundred times. +@item lpr-switches +This should be set to a list that contains whatever the print command +requires to do its job. Something like: -You can find out how a macro expands by using the @code{cl-prettyexpand} -function. -@end quotation +@lisp +(setq lpr-switches '("-depson")) +@end lisp +@end table -@node Q5.1.8, Q5.1.9, Q5.1.7, Miscellaneous -@unnumberedsubsec Q5.1.8: I like recursion, does it slow things down? +For postscript printing there are three analogous variables to +customize. -Yes. Emacs byte-compiler cannot do much to optimize recursion. But -think well whether this is a real concern in Emacs. Much of the Emacs -slowness comes from internal mechanisms such as redisplay, or from the -fact that it is an interpreter. +@table @code +@item ps-lpr-command +This should be set to a command that takes postscript on standard input +and directs it to a postscript printer. -Please try not to make your code much uglier to gain a very small speed -gain. It's not usually worth it. +@item ps-lpr-switches +This should be set to a list of switches required for +@code{ps-lpr-command} to do its job. -@node Q5.1.9, Q5.1.10, Q5.1.8, Miscellaneous -@unnumberedsubsec Q5.1.9: How do I put a glyph as annotation in a buffer? +@item ps-print-color-p +This boolean variable should be set @code{t} if printing will be done in +color, otherwise it should be set to @code{nil}. +@end table -Here is a solution that will insert the glyph annotation at the -beginning of buffer: +NOTE: It is an undocumented limitation in XEmacs that postscript +printing (the @code{Pretty Print Buffer} menu item) @strong{requires} a +window system environment. It cannot be used outside of X11. -@lisp -(make-annotation (make-glyph '([FORMAT :file FILE] - [string :data "fallback-text"])) - (point-min) - 'text - (current-buffer)) -@end lisp +@node Q5.2.2, Q5.2.3, Q5.2.1, External Subsystems +@unnumberedsubsec Q5.2.2: How can I print WYSIWYG a font-locked buffer? -Replace @samp{FORMAT} with an unquoted symbol representing the format of -the image (e.g. @code{xpm}, @code{xbm}, @code{gif}, @code{jpeg}, etc.) -Instead of @samp{FILE}, use the image file name -(e.g. -@iftex -@* -@end iftex -@file{/usr/local/lib/xemacs-21.4/etc/recycle.xpm}). +Font-lock looks nice. How can I print (WYSIWYG) the highlighted +document? -You can turn this to a function (that optionally prompts you for a file -name), and inserts the glyph at @code{(point)} instead of -@code{(point-min)}. +The package @code{ps-print}, which is now included with XEmacs, provides +the ability to do this. The source code contains complete instructions +on its use, in +@file{$prefix/lib/xemacs/xemacs-packages/lisp/ps-print/ps-print.el}, +being the default location of an installed ps-print package. -@node Q5.1.10, Q5.1.11, Q5.1.9, Miscellaneous -@unnumberedsubsec Q5.1.10: @code{map-extents} won't traverse all of my extents! +@node Q5.2.3, Q5.2.4, Q5.2.2, External Subsystems +@unnumberedsubsec Q5.2.3: Getting @kbd{M-x lpr} to work with postscript printer. -I tried to use @code{map-extents} to do an operation on all the extents -in a region. However, it seems to quit after processing a random number -of extents. Is it buggy? +My printer is a Postscript printer and @code{lpr} only works for +Postscript files, so how do I get @kbd{M-x lpr-region} and @kbd{M-x +lpr-buffer} to work? -No. The documentation of @code{map-extents} states that it will iterate -across the extents as long as @var{function} returns @code{nil}. -Unexperienced programmers often forget to return @code{nil} explicitly, -which results in buggy code. For instance, the following code is -supposed to delete all the extents in a buffer, and issue as many -@samp{fubar!} messages. +Put something like this in your @file{init.el}: @lisp -(map-extents (lambda (ext ignore) - (delete-extent ext) - (message "fubar!"))) +(setq lpr-command "a2ps") +(setq lpr-switches '("-p" "-1")) @end lisp -Instead, it will delete only the first extent, and stop right there -- -because @code{message} will return a non-nil value. The correct code -is: +If you don't use a2ps to convert ASCII to postscript (why not, it's +free?), replace with the command you do use. Note also that some +versions of a2ps require a @samp{-Pprinter} to ensure spooling. -@lisp -(map-extents (lambda (ext ignore) - (delete-extent ext) - (message "fubar!") - nil)) -@end lisp +@node Q5.2.4, Q5.3.1, Q5.2.3, External Subsystems +@unnumberedsubsec Q5.2.4: Can you print under MS Windows? -@node Q5.1.11, Q5.2.1, Q5.1.10, Miscellaneous -@unnumberedsubsec Q5.1.11: My elisp program is horribly slow. Is there -an easy way to find out where it spends time? -@c New +As of 21.4, printing works on Windows, using simply +@samp{File->Print BUFFER...}, and can be configured with +@samp{File->Page Setup...}. -@email{hniksic@@xemacs.org, Hrvoje Niksic} writes: -@quotation -Under XEmacs 20.4 and later you can use @kbd{M-x profile-key-sequence}, -press a key (say @key{RET} in the Gnus Group buffer), and get the -results using @kbd{M-x profile-results}. It should give you an idea of -where the time is being spent. -@end quotation +Prior to 21.4, there is no built-in support, but there are some clever +hacks out there. If you know how, please let us know and we'll put it +here. -@node Q5.2.1, Q5.2.2, Q5.1.11, Miscellaneous -@unnumberedsec 5.2: Sound -@unnumberedsubsec Q5.2.1: How do I turn off the sound? +@unnumberedsec 5.3: Sound -Add the following line to your @file{init.el}/@file{.emacs}: +@node Q5.3.1, Q5.3.2, Q5.2.4, External Subsystems +@unnumberedsubsec Q5.3.1: How do I turn off the sound? + +Add the following line to your @file{init.el}: @lisp (setq bell-volume 0) @@ -5826,32 +6416,41 @@ That will make your XEmacs totally silent---even the default ding sound (TTY beep on TTY-s) will be gone. -Starting with XEmacs 20.2 you can also change these with Customize. -Select from the @code{Options} menu -@code{Advanced (Customize)->Emacs->Environment->Sound->Sound...} or type -@kbd{M-x customize @key{RET} sound @key{RET}}. +You can also change these with Customize. Select from the +@code{Options} menu @code{Advanced +(Customize)->Emacs->Environment->Sound->Sound...} or type @kbd{M-x +customize @key{RET} sound @key{RET}}. -@node Q5.2.2, Q5.2.3, Q5.2.1, Miscellaneous -@unnumberedsubsec Q5.2.2: How do I get funky sounds instead of a boring beep? +@node Q5.3.2, Q5.3.3, Q5.3.1, External Subsystems +@unnumberedsubsec Q5.3.2: How do I get funky sounds instead of a boring beep? Make sure your XEmacs was compiled with sound support, and then put this -in your @file{init.el}/@file{.emacs}: +in your @file{init.el}: @lisp (load-default-sounds) @end lisp -@c The sound support in XEmacs 19.14 was greatly improved over previous -@c versions. -@c -@node Q5.2.3, Q5.2.4, Q5.2.2, Miscellaneous -@unnumberedsubsec Q5.2.3: What's NAS, how do I get it? +@node Q5.3.3, Q5.3.4, Q5.3.2, External Subsystems +@unnumberedsubsec Q5.3.3: What are NAS and ESD (EsounD)? + +@dfn{Network Audio System} (NAS) is a client-server sound library for X. + +@uref{http://radscan.com/nas.html}. + +To build XEmacs with it, use the @file{configure} flag @samp{--with-sound=nas}. -@xref{Q2.0.3}, for an explanation of the @dfn{Network Audio System}. +@dfn{Enlightened Sound Daemon} (ESD or EsounD) is yet another sound system. -@node Q5.2.4, Q5.3.1, Q5.2.3, Miscellaneous -@unnumberedsubsec Q5.2.4: Sunsite sounds don't play. +@uref{http://www.tux.org/~ricdude/EsounD.html}. + +To build XEmacs with it, use the @file{configure} flag @samp{--with-sound=esd}. + +You can specify support for both with a flag like @samp{--with-sound=nas,esd}. + +@node Q5.3.4, Q5.4.1, Q5.3.3, External Subsystems +@unnumberedsubsec Q5.3.4: Sunsite sounds don't play. I'm having some trouble with sounds I've downloaded from sunsite. They play when I run them through @code{showaudio} or cat them directly to @@ -5869,195 +6468,468 @@ need to perform a 'null' conversion from SunAudio to SunAudio. @end quotation -@node Q5.3.1, Q5.3.2, Q5.2.4, Miscellaneous -@unnumberedsec 5.3: Miscellaneous -@unnumberedsubsec Q5.3.1: How do you make XEmacs indent CL if-clauses correctly? +@unnumberedsec 5.4: Running an Interior Shell, Invoking Subprocesses -I'd like XEmacs to indent all the clauses of a Common Lisp @code{if} the -same amount instead of indenting the 3rd clause differently from the -first two. +@node Q5.4.1, Q5.4.2, Q5.3.4, External Subsystems +@unnumberedsubsec Q5.4.1: What is an interior shell? -One way is to add, to @file{init.el}/@file{.emacs}: +#### Write me. -@lisp -(put 'if 'lisp-indent-function nil) -@end lisp +@node Q5.4.2, Q5.4.3, Q5.4.1, External Subsystems +@unnumberedsubsec Q5.4.2: How do I start up a second shell buffer? -However, note that the package @code{cl-indent} that comes with -XEmacs sets up this kind of indentation by default. @code{cl-indent} -also knows about many other CL-specific forms. To use @code{cl-indent}, -one can do this: +In the @code{*shell*} buffer: @lisp -(load "cl-indent") -(setq lisp-indent-function (function common-lisp-indent-function)) +M-x rename-buffer @key{RET} *shell-1* @key{RET} +M-x shell RET @end lisp -One can also customize @file{cl-indent.el} so it mimics the default -@code{if} indentation @code{then} indented more than the @code{else}. -Here's how: +This will then start a second shell. The key is that no buffer named +@samp{*shell*} can exist. It might be preferable to use @kbd{M-x +rename-uniquely} to rename the @code{*shell*} buffer instead of @kbd{M-x +rename-buffer}. -@lisp -(put 'if 'common-lisp-indent-function '(nil nil &body)) -@end lisp +Alternately, you can set the variable @code{shell-multiple-shells}. +If the value of this variable is non-nil, each time shell mode is invoked, +a new shell is made -Also, a new version (1.2) of @file{cl-indent.el} was posted to -comp.emacs.xemacs on 12/9/94. This version includes more documentation -than previous versions. This may prove useful if you need to customize -any indent-functions. +@node Q5.4.3, Q5.4.4, Q5.4.2, External Subsystems +@unnumberedsubsec Q5.4.3: Telnet from shell filters too much -@node Q5.3.2, Q5.3.3, Q5.3.1, Miscellaneous -@unnumberedsubsec Q5.3.2: [This question intentionally left blank] +I'm using the Emacs @kbd{M-x shell} function, and I would like to invoke +and use a telnet session within it. Everything works fine except that +now all @samp{^M}'s are filtered out by Emacs. Fixes? -Obsolete question, left blank to avoid renumbering. +Use @kbd{M-x rsh} or @kbd{M-x telnet} to open remote sessions rather +than doing rsh or telnet within the local shell buffer. You can also +use @kbd{M-x ssh} to open secure remote session if you have @code{ssh} +installed. -@node Q5.3.3, Q5.3.4, Q5.3.2, Miscellaneous -@unnumberedsubsec Q5.3.3: How can I print WYSIWYG a font-locked buffer? +@node Q5.4.4, Q5.4.5, Q5.4.3, External Subsystems +@unnumberedsubsec Q5.4.4: Strange things are happening in Shell Mode. -Font-lock looks nice. How can I print (WYSIWYG) the highlighted -document? +Sometimes (i.e. it's not repeatable, and I can't work out why it +happens) when I'm typing into shell mode, I hit return and only a +portion of the command is given to the shell, and a blank prompt is +returned. If I hit return again, the rest of the previous command is +given to the shell. -The package @code{ps-print}, which is now included with XEmacs, provides -the ability to do this. The source code contains complete instructions -on its use, in -@file{$prefix/lib/xemacs/xemacs-packages/lisp/ps-print/ps-print.el}, -being the default location of an installed ps-print package. +@email{martin@@xemacs.org, Martin Buchholz} writes: -@node Q5.3.4, Q5.3.5, Q5.3.3, Miscellaneous -@unnumberedsubsec Q5.3.4: Getting @kbd{M-x lpr} to work with postscript printer. +@quotation +There is a known problem with interaction between @code{csh} and the +@code{filec} option and XEmacs. You should add the following to your +@file{.cshrc}: -My printer is a Postscript printer and @code{lpr} only works for -Postscript files, so how do I get @kbd{M-x lpr-region} and @kbd{M-x -lpr-buffer} to work? +@example +if ( "$TERM" == emacs || "$TERM" == unknown ) unset filec +@end example +@end quotation -Put something like this in your @file{init.el}/@file{.emacs}: +@node Q5.4.5, Q5.5.1, Q5.4.4, External Subsystems +@unnumberedsubsec Q5.4.5: XEmacs complains "No such file or directory, diff" -@lisp -(setq lpr-command "a2ps") -(setq lpr-switches '("-p" "-1")) -@end lisp +or "ispell" or other commands that seem related to whatever you just +tried to do (M-x ediff or M-$, for example). -If you don't use a2ps to convert ASCII to postscript (why not, it's -free?), replace with the command you do use. Note also that some -versions of a2ps require a @samp{-Pprinter} to ensure spooling. +There are a large number of common (in the sense that "everyone has +these, they really do") Unix utilities that are not provided with +XEmacs. The GNU Project's implementations are available for Windows in +the the Cygwin distribution (@uref{http://www.cygwin.com/}), which also +provides a complete Unix emulation environment (and thus makes ports of +Unix utilities nearly trivial). Another implementation is that from +MinGW (@uref{http://www.mingw.org/msys.shtml}). If you know of others, +please let us know! -@node Q5.3.5, Q5.3.6, Q5.3.4, Miscellaneous -@unnumberedsubsec Q5.3.5: How do I specify the paths that XEmacs uses for finding files? +@unnumberedsec 5.5: Multiple Device Support -You can specify what paths to use by using a number of different flags -when running configure. See the section MAKE VARIABLES in the top-level -file INSTALL in the XEmacs distribution for a listing of those flags. +@node Q5.5.1, Q5.5.2, Q5.4.5, External Subsystems +@unnumberedsubsec Q5.5.1: How do I open a frame on another screen of my multi-headed display? -Most of the time, however, the simplest fix is: @strong{do not} specify -paths as you might for GNU Emacs. XEmacs can generally determine the -necessary paths dynamically at run time. The only path that generally -needs to be specified is the root directory to install into. That can -be specified by passing the @code{--prefix} flag to configure. For a -description of the XEmacs install tree, please consult the @file{NEWS} -file. +Use the command @kbd{M-x make-frame-on-display}. This command is also +on the File menu in the menubar. + +The command @code{make-frame-on-tty} also exists, which will establish a +connection to any tty-like device. Opening the TTY devices should be +left to @code{gnuclient}, though. -@node Q5.3.6, Q5.3.7, Q5.3.5, Miscellaneous -@unnumberedsubsec Q5.3.6: [This question intentionally left blank] +@node Q5.5.2, Q5.5.3, Q5.5.1, External Subsystems +@unnumberedsubsec Q5.5.2: Can I really connect to a running XEmacs after calling up over a modem? How? -Obsolete question, left blank to avoid renumbering. +Yes. Use @code{gnuclient -nw}. -@node Q5.3.7, Q5.3.8, Q5.3.6, Miscellaneous -@unnumberedsubsec Q5.3.7: Can I have the end of the buffer delimited in some way? +Also see @ref{Q5.5.3, How do I disable gnuserv from opening a new frame?}. -Say, with: @samp{[END]}? +@node Q5.5.3, Q5.5.4, Q5.5.2, External Subsystems +@unnumberedsubsec Q5.5.3: How do I disable gnuserv from opening a new frame? -Try this: +If you set the @code{gnuserv-frame} variable to the frame that should be +used to display buffers that are pulled up, a new frame will not be +created. For example, you could put @lisp -(let ((ext (make-extent (point-min) (point-max)))) - (set-extent-property ext 'start-closed t) - (set-extent-property ext 'end-closed t) - (set-extent-property ext 'detachable nil) - (set-extent-end-glyph ext (make-glyph [string :data "[END]"]))) +(setq gnuserv-frame (selected-frame)) @end lisp -Since this is XEmacs, you can specify an icon to be shown on -window-system devices. To do so, change the @code{make-glyph} call to -something like this: +early on in your @file{init.el}, to ensure that the first frame created +is the one used for your gnuserv buffers. + +There is an option to set the gnuserv target to the current frame. See +@code{Options->Display->"Other Window" Location->Make Current Frame Gnuserv Target} + +You can also change this with Customize. Select from the +@code{Options} menu @code{Advanced +(Customize)->Emacs->Environment->Gnuserv->Gnuserv Frame...} or type +@kbd{M-x customize @key{RET} gnuserv @key{RET}}. + + +@node Q5.5.4, Q5.5.5, Q5.5.3, External Subsystems +@unnumberedsubsec Q5.5.4: How do I start gnuserv so that each subsequent XEmacs is a client? + +Put the following in your @file{init.el} file to start the server: @lisp -(make-glyph '([xpm :file "~/something.xpm"] - [string :data "[END]"])) +(gnuserv-start) @end lisp -You can inline the @sc{xpm} definition yourself by specifying -@code{:data} instead of @code{:file}. Here is such a full-featured -version that works on both X and TTY devices: +Start your first XEmacs as usual. After that, you can do: + +@example +gnuclient randomfilename +@end example + +from the command line to get your existing XEmacs process to open a new +frame and visit randomfilename in that window. When you're done editing +randomfilename, hit @kbd{C-x #} to kill the buffer and get rid of the +frame. + +See also man page of gnuclient. + +@node Q5.5.5, , Q5.5.4, External Subsystems +@unnumberedsubsec Q5.5.5: Is there a way to start a new XEmacs if there's no gnuserv running, and otherwise use gnuclient? + +@email{vroonhof@@math.ethz.ch, Jan Vroonhof} writes: +@quotation +Here is one of the solutions, we have this in a script called +@file{etc/editclient.sh}. +@example + #!/bin/sh + if gnuclient -batch -eval t >/dev/null 2>&1 + then + exec gnuclient $@{1+"$@@"@} + else + xemacs -unmapped -f gnuserv-start & + until gnuclient -batch -eval t >/dev/null 2>&1 + do + sleep 1 + done + exec gnuclient $@{1+"$@@"@} + fi +@end example + +Note that there is a known problem when running XEmacs and 'gnuclient +-nw' on the same TTY. +@end quotation + +@node Internet, Advanced, External Subsystems, Top +@unnumbered 6 Connecting to the Internet + +This is part 6 of the XEmacs Frequently Asked Questions list. This +section is devoted connecting to the Internet. + +@menu +6.0: General Mail and News +* Q6.0.1:: What are the various packages for reading mail? +* Q6.0.2:: How can I send mail? +* Q6.0.3:: How do I get my outgoing mail archived? +* Q6.0.4:: How can I read and/or compose MIME messages? +* Q6.0.5:: How do I customize the From line? +* Q6.0.6:: How do I get my MUA to filter mail for me? +* Q6.0.7:: Remote mail reading with an MUA. +* Q6.0.8:: An MUA gets an error incorporating new mail. +* Q6.0.9:: Why isn't @file{movemail} working? +* Q6.0.10:: How do I make my MUA display graphical smilies? +* Q6.0.11:: How can I get those oh-so-neat X-Face lines? + +6.1: Reading Mail with VM +* Q6.1.1:: How do I set up VM to retrieve mail from a remote site using POP? +* Q6.1.2:: How can I get VM to automatically check for new mail? +* Q6.1.3:: I have various addresses at which I receive mail. How can I tell VM to ignore them when doing a "reply-all"? +* Q6.1.4:: Is there a mailing list or FAQ for VM? +* Q6.1.5:: How do I make VM stay in a single frame? +* Q6.1.6:: Customization of VM not covered in the manual, or here. + +6.2: Reading Netnews and Mail with Gnus +* Q6.2.1:: GNUS, (ding) Gnus, Gnus 5, September Gnus, Red Gnus, Quassia Gnus, argh! +* Q6.2.2:: How do I make Gnus stay within a single frame? + +6.3: FTP Access +* Q6.3.1:: Can I edit files on other hosts? +* Q6.3.2:: What is EFS? + +6.4: Web Browsing with W3 +* Q6.4.1:: What is W3? +* Q6.4.2:: How do I run W3 from behind a firewall? +* Q6.4.3:: Is it true that W3 supports style sheets and tables? +@end menu + +@unnumberedsec 6.0: General Mail and News + +@node Q6.0.1, Q6.0.2, Internet, Internet +@unnumberedsubsec Q6.0.1: What are the various packages for reading mail? + +#### Write me. + +@node Q6.0.2, Q6.0.3, Q6.0.1, Internet +@unnumberedsubsec Q6.0.2: How can I send mail? + +Under Unix and Mac OS X, the @samp{sendmail} package is normally used +for this. +#### Write me. + +Under Windows, you need to use @samp{smtpmail}, which communicates +directly with the mail server, as there is no @file{sendmail} program +running. To get it working, use code like the following in your +@file{init.el} file: + +@lisp + ;; Get mail working under Windows. + (setq message-send-mail-function 'smtpmail-send-it) ; for message/Gnus + (setq send-mail-function 'smtpmail-send-it) ; for C-x m, etc. + ;; the following ensures that mail problems can be debugged: it logs a trace + ;; of the SMTP conversation to *trace of SMTP session to <somewhere>*. + (setq smtpmail-debug-info t) + ;; Substitute your info here. + ;(setq user-mail-address "ben@@xemacs.org") + ;(setq user-full-name "Ben Wing") + ;(setq smtpmail-default-smtp-server "smtp.myserver.myisp.com") + ;; The following two aren't completely necessary but may help. + ;(setq smtpmail-local-domain "666.com") + ;(setq smtpmail-sendto-domain "666.com") + ;; If your SMTP server requires a username/password to authenticate, as + ;; many do nowadays, set them like this: + ;(setq smtpmail-auth-credentials ; or use ~/.authinfo + ; '(("smtp.myserver.myisp.com" 25 "USER@@SOMEWHERE" "PASSWORD"))) + + ;; Other possibilities for getting smtpmail to work: + ;; + ;; If for some reason you need to authenticate using the STARTTLS protocol + ;; (don't look into this unless you know what it is), use + ;; (setq smtpmail-starttls-credentials + ;; '(("YOUR SMTP HOST" 25 "~/.my_smtp_tls.key" "~/.my_smtp_tls.cert"))) + ;; Requires external program + ;; ftp://ftp.opaopa.org/pub/elisp/starttls-*.tar.gz. + ;; See http://www.ietf.org/rfc/rfc2246.txt, + ;; http://www.ietf.org/rfc/rfc2487.txt +@end lisp + +The lines you need to care about are those that set +@code{user-mail-address}, @code{user-full-name}, +@code{smtpmail-default-smtp-server}, and +@code{smtpmail-auth-credentials}. You need to set these with, +respectively, your email address, your full name, the SMTP server you +use for outgoing mail, and the username and password you need to log +in to your SMTP server. (If for some reason your SMTP server doesn't +require logging in to send mail, don't uncomment this last line.) + +The other settings may be useful in specific cases, but you should know what +you're doing before enabling them. + +@node Q6.0.3, Q6.0.4, Q6.0.2, Internet +@unnumberedsubsec Q6.0.3: How do I get my outgoing mail archived? @lisp -(let ((ext (make-extent (point-min) (point-max)))) - (set-extent-property ext 'start-closed t) - (set-extent-property ext 'end-closed t) - (set-extent-property ext 'detachable nil) - (set-extent-end-glyph ext (make-glyph '([xpm :data "\ -/* XPM */ -static char* eye = @{ -\"20 11 7 2\", -\"__ c None\" -\"_` c #7f7f7f\", -\"_a c #fefefe\", -\"_b c #7f0000\", -\"_c c #fefe00\", -\"_d c #fe0000\", -\"_e c #bfbfbf\", -\"___________`_`_`___b_b_b_b_________`____\", -\"_________`_`_`___b_c_c_c_b_b____________\", -\"_____`_`_`_e___b_b_c_c_c___b___b_______`\", -\"___`_`_e_a___b_b_d___b___b___b___b______\", -\"_`_`_e_a_e___b_b_d_b___b___b___b___b____\", -\"_`_`_a_e_a___b_b_d___b___b___b___b___b__\", -\"_`_`_e_a_e___b_b_d_b___b___b___b___b_b__\", -\"___`_`_e_a___b_b_b_d_c___b___b___d_b____\", -\"_____`_`_e_e___b_b_b_d_c___b_b_d_b______\", -\"_`_____`_`_`_`___b_b_b_d_d_d_d_b________\", -\"___`_____`_`_`_`___b_b_b_b_b_b__________\", -@} ;"] - [string :data "[END]"])))) +(setq mail-archive-file-name "~/outbox") @end lisp -Note that you might want to make this a function, and put it to a hook. -We leave that as an exercise for the reader. +@node Q6.0.4, Q6.0.5, Q6.0.3, Internet +@unnumberedsubsec Q6.0.4: How can I read and/or compose MIME messages? + +VM, MH-E and GNUS support MIME natively. Other MUAs may or may not +have MIME support; refer to their documentation and other resources, +such as web pages and mailing lists. Packages like SEMI/WEMI may be +useful in connection with MUAs like mew and Wanderlust. + +@node Q6.0.5, Q6.0.6, Q6.0.4, Internet +@unnumberedsubsec Q6.0.5: How do I customize the From line? + +How do I change the @samp{From:} line? I have set gnus-user-from-line +to +@example +Gail Gurman <gail.gurman@@sybase.com> +@end example +@noindent , but XEmacs Gnus doesn't use +it. [This should apply to all MUA's. --ed] Instead it uses +@example +Gail Mara Gurman @email{gailg@@deall} +@end example +@noindent and then complains +that it's incorrect. Also, as you perhaps can see, my Message-ID is +screwy. How can I change that? + +@email{larsi@@ifi.uio.no, Lars Magne Ingebrigtsen} writes: + +@quotation +Set @code{user-mail-address} to @samp{gail.gurman@@sybase.com} or +@code{mail-host-address} to @samp{sybase.com}. +@end quotation + +@node Q6.0.6, Q6.0.7, Q6.0.5, Internet +@unnumberedsubsec Q6.0.6: How do I get my MUA to filter mail for me? + +One possibility is to use procmail to split your mail before it gets to +the MUA. I prefer this personally, since there are many strange and +wonderful things one can do with procmail. Procmail may be found at +@uref{http://www.procmail.org/}. + +Also see the Mail Filtering FAQ at: +@iftex +@* +@end iftex +@uref{http://www.faqs.org/faqs/mail/filtering-faq/}. + +@node Q6.0.7, Q6.0.8, Q6.0.6, Internet +@unnumberedsubsec Q6.0.7: Remote mail reading with an MUA. + +My mailbox lives at the office on a big honkin server. My regular INBOX +lives on my honkin desktop machine. I now can PPP to the office from +home which is far from honking... I'd like to be able to read mail at +home without storing it here and I'd like to use xemacs and the MUA at +home... Is there a recommended setup? + +@email{nuspl@@nvwls.cc.purdue.edu, Joseph J. Nuspl Jr.} writes: + +@quotation +There are several ways to do this. + +@enumerate +@item +Set your display to your home machine and run dxpc or one of the other X +compressors. + +@item +NFS mount your desktop machine on your home machine and modify your pop +command on your home machine to rsh to your desktop machine and actually +do the pop get's. + +@item +Run a POP server on your desktop machine as well and do a sort of two +tiered POP get. +@end enumerate +@end quotation + +@email{wmperry@@monolith.spry.com, William Perry} adds: + +@quotation +Or you could run a pop script periodically on your desktop machine, and +just use ange-ftp or NFS to get to your mailbox. I used to do this all +the time back at IU. +@end quotation + +@node Q6.0.8, Q6.0.9, Q6.0.7, Internet +@unnumberedsubsec Q6.0.8: An MUA gets an error incorporating new mail. -@node Q5.3.8, Q5.3.9, Q5.3.7, Miscellaneous -@unnumberedsubsec Q5.3.8: How do I insert today's date into a buffer? +rmail and VM, and probably other MUA's as well, get new mail from +your mailbox (called @file{/var/mail/$USER} or @file{/var/spool/mail/$USER} +or something similar) using a program called @code{movemail}. +This program interlocks with @code{/bin/mail} using the protocol +defined by @code{/bin/mail}. + +There are various different protocols in general use, which you need to +specify using the @samp{--mail-locking} option to @file{configure}: + +@table @samp +@item lockf +POSIX file locking with @code{lockf()} +@item flock +BSD file locking with @code{flock()} +@item dot +To manipulate mail file @file{foo}, first create file @file{foo.lock} +@item locking +Use @code{locking()}, Microsoft's renamed @code{flock()} +@item mmdf +Use @code{lk_open()} and @code{lk_close()} as defined by the Multi-channel +Memo Distribution Facility +@item pop +Retrieve mail using POP (the Post Office Protocol). This is the +default for Cygwin/MinGW. +@end table -Like this: +@strong{IF YOU DON'T USE THE FORM OF INTERLOCKING THAT IS NORMAL ON YOUR +SYSTEM, YOU CAN LOSE MAIL!} -@lisp -(insert (current-time-string)) -@end lisp +Usually the value is correctly determined automatically: +@file{configure} tries to detect the method in use, and defaults exist +on systems for which this doesn't work. + +However, if you run into problems incorporating new mail, it may be +because an incorrect method is being used. + +If your system uses the lock file protocol, and permissions are set +so that ordinary users cannot write lock files in the mail spool +directory, you may need to make @file{movemail} setgid to a +suitable group such as @samp{mail}. You can use these commands (as +root): + +@example +chgrp mail movemail +chmod 2755 movemail +@end example -@node Q5.3.9, Q5.3.10, Q5.3.8, Miscellaneous -@unnumberedsubsec Q5.3.9: Are only certain syntactic character classes available for abbrevs? +If you are using the @samp{pop} locking method, @file{movemail} must +be setuid root. -@email{gutschk@@uni-muenster.de, Markus Gutschke} writes: +Installation normally copies movemail from the build directory to an +installation directory which is usually under @file{/usr/local/lib}. +The installed copy of @file{movemail} is usually in the directory +@file{/usr/local/lib/xemacs-VERSION/TARGET} (for example, +@file{/usr/local/lib/xemacs-21.4.15/i686-pc-cygwin}). You must change +the group and mode of the installed copy; changing the group and mode +of the build directory copy is ineffective. + +@node Q6.0.9, Q6.0.10, Q6.0.8, Internet +@unnumberedsubsec Q6.0.9: Why isn't @file{movemail} working? + +@xref{Q6.0.8}. + +Note also that older versions of Mozilla came with a @file{movemail} +program that is @strong{not} compatible with XEmacs. Do not use it. +Always use the @file{movemail} installed with your XEmacs. Failure to +do so can result in lost mail. -@quotation -Yes, abbrevs only expands word-syntax strings. While XEmacs does not -prevent you from defining (e.g. with @kbd{C-x a g} or @kbd{C-x a l}) -abbrevs that contain special characters, it will refuse to expand -them. So you need to ensure, that the abbreviation contains letters and -digits only. This means that @samp{xd}, @samp{d5}, and @samp{5d} are -valid abbrevs, but @samp{&d}, and @samp{x d} are not. - -If this sounds confusing to you, (re-)read the online documentation for -abbrevs (@kbd{C-h i m XEmacs @key{RET} m Abbrevs @key{RET}}), and then come back and -read this question/answer again. -@end quotation +@node Q6.0.10, Q6.0.11, Q6.0.9, Internet +@unnumberedsubsec Q6.0.10: How do I make my MUA display graphical smilies? +For mh-e use the following: + +@lisp +(add-hook 'mh-show-mode-hook '(lambda () + (smiley-region (point-min) + (point-max)))) +@end lisp + +@email{bill@@carpenter.ORG, WJCarpenter} writes: +For VM use the following: +@lisp + (autoload 'smiley-region "smiley" nil t) + (add-hook 'vm-select-message-hook + '(lambda () + (smiley-region (point-min) + (point-max)))) +@end lisp -Starting with XEmacs 20.3 this restriction has been lifted. +For tm use the following: +@lisp +(autoload 'smiley-buffer "smiley" nil t) +(add-hook 'mime-viewer/plain-text-preview-hook 'smiley-buffer) +@end lisp -@node Q5.3.10, Q5.3.11, Q5.3.9, Miscellaneous -@unnumberedsubsec Q5.3.10: How can I get those oh-so-neat X-Face lines? +@node Q6.0.11, Q6.1.1, Q6.0.10, Internet +@unnumberedsubsec Q6.0.11: How can I get those oh-so-neat X-Face lines? Firstly there is an ftp site which describes X-faces and has the associated tools mentioned below, at -@uref{ftp://ftp.cs.indiana.edu:/pub/faces/}. +@uref{http://ftp.cs.indiana.edu/pub/faces/}. Then the steps are @@ -6123,10 +6995,8 @@ method, one should NOT quote the face string using the sed script . It might also be helpful to use @email{stig@@hackvan.com, Stig's} script -(included in the compface distribution at XEmacs.org) to do the +xbm2face (included in the compface distribution at XEmacs.org) to do the conversion. -@comment For convenience xbm2xface is available for anonymous FTP at -@comment @uref{ftp://ftp.miranova.com/pub/xemacs/xbm2xface.pl}. Contributors for this item: @@ -6139,922 +7009,1160 @@ Paul Harrison, and Vegard Vesterheim -@node Q5.3.11, Q5.3.12, Q5.3.10, Miscellaneous -@unnumberedsubsec Q5.3.11: How do I add new Info directories? +@unnumberedsec 6.1: Reading Mail with VM -You use something like: +@node Q6.1.1, Q6.1.2, Q6.0.11, Internet +@unnumberedsubsec Q6.1.1: How do I set up VM to retrieve mail from a remote site using POP? + +Use @code{vm-spool-files}, like this for example: @lisp -(setq Info-directory-list (cons - (expand-file-name "~/info") - Info-default-directory-list)) +(setq vm-spool-files '("/var/spool/mail/wing" + "netcom23.netcom.com:110:pass:wing:MYPASS")) @end lisp -@email{davidm@@prism.kla.com, David Masterson} writes: +Of course substitute your actual password for MYPASS. + +@node Q6.1.2, Q6.1.3, Q6.1.1, Internet +@unnumberedsubsec Q6.1.2: How can I get VM to automatically check for new mail? + +@email{turner@@lanl.gov, John Turner} writes: @quotation -Emacs Info and XEmacs Info do many things differently. If you're trying to -support a number of versions of Emacs, here are some notes to remember: +Use the following: -@enumerate -@item -Emacs Info scans @code{Info-directory-list} from right-to-left while -XEmacs Info reads it from left-to-right, so append to the @emph{correct} -end of the list. +@lisp +(setq vm-auto-get-new-mail 60) +@end lisp +@end quotation -@item -Use @code{Info-default-directory-list} to initialize -@code{Info-directory-list} @emph{if} it is available at startup, but not -all Emacsen define it. +@node Q6.1.3, Q6.1.4, Q6.1.2, Internet +@unnumberedsubsec Q6.1.3: I have various addresses at which I receive mail. How can I tell VM to ignore them when doing a "reply-all"? -@item -Emacs Info looks for a standard @file{dir} file in each of the -directories scanned from #1 and magically concatenates them together. +Set @code{vm-reply-ignored-addresses} to a list, like -@item -XEmacs Info looks for a @file{localdir} file (which consists of just the -menu entries from a @file{dir} file) in each of the directories scanned -from #1 (except the first), does a simple concatenation of them, and -magically attaches the resulting list to the end of the menu in the -@file{dir} file in the first directory. -@end enumerate +@lisp +(setq vm-reply-ignored-addresses + '("wing@@nuspl@@nvwls.cc.purdue.edu,netcom[0-9]*.netcom.com" + "wing@@netcom.com" "wing@@xemacs.org")) +@end lisp -Another alternative is to convert the documentation to HTML with -texi2html and read it from a web browser like Lynx or W3. +Note that each string is a regular expression. + +@node Q6.1.4, Q6.1.5, Q6.1.3, Internet +@unnumberedsubsec Q6.1.4: Is there a mailing list or FAQ for VM? + +A FAQ for VM exists at @uref{http://www.wonderworks.com/vm/FAQ.html}. + +VM has its own newsgroups gnu.emacs.vm.info and gnu.emacs.vm.bug. + +@node Q6.1.5, Q6.1.6, Q6.1.4, Internet +@unnumberedsubsec Q6.1.5: How do I make VM stay in a single frame? + +John.@email{Cooper@@Eng.Sun.COM, John S Cooper} writes: + +@quotation +@lisp + ; Don't use multiple frames +(setq vm-frame-per-composition nil) +(setq vm-frame-per-folder nil) +(setq vm-frame-per-edit nil) +(setq vm-frame-per-summary nil) +@end lisp @end quotation -@node Q5.3.12, Q5.4.1, Q5.3.11, Miscellaneous -@unnumberedsubsec Q5.3.12: What do I need to change to make printing work? +@node Q6.1.6, Q6.2.1, Q6.1.5, Internet +@unnumberedsubsec Q6.1.6: Customization of VM not covered in the manual, or here. -For regular printing there are two variables that can be customized. +@email{boffi@@hp735.stru.polimi.it, giacomo boffi} writes: -@table @code -@item lpr-command -This should be set to a command that takes standard input and sends -it to a printer. Something like: +@quotation +The meta-answer is to look into the file @file{vm-vars.el}, in the vm +directory of the lisp library. + +@file{vm-vars.el} contains, initializes and carefully describes, with +examples of usage, the plethora of user options that @emph{fully} +control VM's behavior. + +Enter vm-vars, @code{forward-search} for toolbar, find the variables +that control the toolbar placement, appearance, existence, copy to your +@file{init.el} or @file{.vm} and modify according to the +detailed instructions. + +The above also applies to all the various features of VM: search for +some keywords, maybe the first you conjure isn't appropriate, find the +appropriate variables, copy and experiment. +@end quotation + +@unnumberedsec 6.2: Reading Netnews and Mail with Gnus + +@node Q6.2.1, Q6.2.2, Q6.1.6, Internet +@unnumberedsubsec Q6.2.1: GNUS, (ding) Gnus, Gnus 5, September Gnus, Red Gnus, Quassia Gnus, argh! + +The Gnus numbering issues are not meant for mere mortals to know them. +If you feel you @emph{must} enter the muddy waters of Gnus, visit the +excellent FAQ, maintained by Justin Sheehy, at: + +@example +@uref{http://my.gnus.org/FAQ/} +@end example + +See also Gnus home page +@example +@uref{http://www.gnus.org/} +@end example + +@node Q6.2.2, Q6.3.1, Q6.2.1, Internet +@unnumberedsubsec Q6.2.2: How do I make Gnus stay within a single frame? + +The toolbar code to start Gnus opens the new frame---and it's a feature +rather than a bug. If you don't like it, but would still like to click +on the seemly icon, use the following code: @lisp -(setq lpr-command "lp") +(defun toolbar-news () + (gnus)) @end lisp -@item lpr-switches -This should be set to a list that contains whatever the print command -requires to do its job. Something like: +It will redefine the callback function of the icon to just call +@code{gnus}, without all the fancy frame stuff. + +@unnumberedsec 6.3: FTP Access + +@node Q6.3.1, Q6.3.2, Q6.2.2, Internet +@unnumberedsubsec Q6.3.1: Can I edit files on other hosts? + +Yes. Of course XEmacs can use any network file system (such as NFS or +Windows file sharing) you have available, and includes some +optimizations and safety features appropriate to those environments. + +It is also possible to transparently edit files via FTP, ssh, or rsh. That +is, XEmacs makes a local copy using the transport in the background, and +automatically refreshes the remote original from that copy when you save +it. XEmacs also is capable of doing file system manipulations like +creating and removing directories and files. The FTP interface is +provided by the standard @samp{efs} package @ref{Top, EFS, , efs}. The +ssh/rsh interface is provided by the optional @samp{tramp} package +@ref{Top, TRAMP, , tramp}. + +@node Q6.3.2, Q6.4.1, Q6.3.1, Internet +@unnumberedsubsec Q6.3.2: What is EFS? + +#### Write me. + +@unnumberedsec 6.4: Web Browsing with W3 + +@node Q6.4.1, Q6.4.2, Q6.3.2, Internet +@unnumberedsubsec Q6.4.1: What is W3? + +W3 is an advanced graphical browser written in Emacs lisp that runs on +XEmacs. It has full support for cascaded style sheets, and more... + +It has a home web page at +@uref{http://www.cs.indiana.edu/elisp/w3/docs.html}. + +@node Q6.4.2, Q6.4.3, Q6.4.1, Internet +@unnumberedsubsec Q6.4.2: How do I run W3 from behind a firewall? + +There is a long, well-written, detailed section in the W3 manual that +describes how to do this. Look in the section entitled "Firewalls". + +@node Q6.4.3, , Q6.4.2, Internet +@unnumberedsubsec Q6.4.3: Is it true that W3 supports style sheets and tables? + +Yes, and much more. W3, as distributed with the latest XEmacs is a +full-featured web browser. + +@node Advanced, Other Packages, Internet, Top +@unnumbered 7 Advanced Customization Using XEmacs Lisp + +This is part 7 of the XEmacs Frequently Asked Questions list. This +section is devoted to advanced customization using XEmacs Lisp. + +@menu +7.0: Emacs Lisp and @file{init.el} +* Q7.0.1:: What version of Emacs am I running? +* Q7.0.2:: How can I evaluate Emacs-Lisp expressions? +* Q7.0.3:: @code{(setq tab-width 6)} behaves oddly. +* Q7.0.4:: How can I add directories to the @code{load-path}? +* Q7.0.5:: How to check if a lisp function is defined? +* Q7.0.6:: Can I force the output of @code{(face-list)} to a buffer? + +7.1: Emacs Lisp Programming Techniques +* Q7.1.1:: What is the difference in key sequences between XEmacs and GNU Emacs? +* Q7.1.2:: Can I generate "fake" keyboard events? +* Q7.1.3:: Could you explain @code{read-kbd-macro} in more detail? +* Q7.1.4:: What is the performance hit of @code{let}? +* Q7.1.5:: What is the recommended use of @code{setq}? +* Q7.1.6:: What is the typical misuse of @code{setq}? +* Q7.1.7:: I like the @code{do} form of cl, does it slow things down? +* Q7.1.8:: I like recursion, does it slow things down? +* Q7.1.9:: How do I put a glyph as annotation in a buffer? +* Q7.1.10:: @code{map-extents} won't traverse all of my extents! +* Q7.1.11:: My elisp program is horribly slow. Is there an easy way to find out where it spends time? + +7.2: Mathematics +* Q7.2.1:: What are bignums, ratios, and bigfloats in Lisp? +* Q7.2.2:: XEmacs segfaults when I use very big numbers! +* Q7.2.3:: Bignums are really slow! +* Q7.2.4:: Equal bignums don't compare as equal! What gives? +@end menu + +@unnumberedsec 7.0: Emacs Lisp and @file{init.el} + +@node Q7.0.1, Q7.0.2, Advanced, Advanced +@unnumberedsubsec Q7.0.1: What version of Emacs am I running? + +How can @file{init.el} determine which of the family of +Emacsen I am using? + +To determine if you are currently running GNU Emacs 18, GNU Emacs 19, +XEmacs 19, XEmacs 20, or Epoch, and use appropriate code, check out the +example given in @file{etc/sample.init.el} (@file{etc/sample.emacs} in +XEmacs versions prior to 21.4). There are other nifty things in there +as well! + +For all new code, all you really need to do is: @lisp -(setq lpr-switches '("-depson")) +(defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version)) @end lisp -@end table -For postscript printing there are three analogous variables to -customize. +@node Q7.0.2, Q7.0.3, Q7.0.1, Advanced +@unnumberedsubsec Q7.0.2: How can I evaluate Emacs-Lisp expressions? -@table @code -@item ps-lpr-command -This should be set to a command that takes postscript on standard input -and directs it to a postscript printer. +I know I can evaluate Elisp expressions from @code{*scratch*} buffer +with @kbd{C-j} after the expression. How do I do it from another +buffer? -@item ps-lpr-switches -This should be set to a list of switches required for -@code{ps-lpr-command} to do its job. +Press @kbd{M-:} (the default binding of @code{eval-expression}), and +enter the expression to the minibuffer. -@item ps-print-color-p -This boolean variable should be set @code{t} if printing will be done in -color, otherwise it should be set to @code{nil}. -@end table +@node Q7.0.3, Q7.0.4, Q7.0.2, Advanced +@unnumberedsubsec Q7.0.3: @code{(setq tab-width 6)} behaves oddly. -NOTE: It is an undocumented limitation in XEmacs that postscript -printing (the @code{Pretty Print Buffer} menu item) @strong{requires} a -window system environment. It cannot be used outside of X11. +If you put @code{(setq tab-width 6)} in your +@file{init.el} file it does not work! Is there a reason +for this? If you do it at the EVAL prompt it works fine!! How strange. +Use @code{setq-default} instead, since @code{tab-width} is +all-buffer-local. -@node Q5.4.1, Q5.4.2, Q5.3.12, Miscellaneous -@unnumberedsec 5.4: Mathematics -@unnumberedsubsec Q5.4.1: What are bignums, ratios, and bigfloats in Lisp? +@node Q7.0.4, Q7.0.5, Q7.0.3, Advanced +@unnumberedsubsec Q7.0.4: How can I add directories to the @code{load-path}? -Thanks to @email{james@@xemacs.org, Jerry James}, XEmacs 21.5.18 and -later can use the capabilities of multiple-precision libraries that may -be available for your platform. The GNU Multiple Precision (GMP) and -BSD Multiple Precision (MP) libraries are partially supported. GMP -gives you @dfn{bignums} (arbitrary precision integers), @dfn{ratios} -(arbitrary precision fractions), and @dfn{bigfloats} (arbitrary -precision floating point numbers). GNU MP is better-supported by XEmacs -at the time of writing (2004-04-06). BSD MP support does not include -ratios or bigfloats, and it throws errors that aren't understood. +Here are two ways to do that, one that puts your directories at the +front of the load-path, the other at the end: + +@lisp +;;; Add things at the beginning of the load-path, do not add +;;; duplicate directories: +(pushnew "bar" load-path :test 'equal) + +(pushnew "foo" load-path :test 'equal) -In most cases, bignum support should be transparent to users and Lisp -programmers. A bignum-enabled XEmacs will automatically convert from -fixnums to bignums and back in pure integer arithmetic, and for GNU MP, -from floats to bigfloats. (Bigfloats must be explicitly coerced to -other types, even if they are exactly representable by less precise -types.) The Lisp reader and printer have been enhanced to handle -bignums, as have the mathematical functions. Rationals (fixnums, -bignums, and ratios) are printed using the @samp{%d}, @samp{%o}, -@samp{%x}, and @samp{%u} format conversions. The read syntax for ratios -is @samp{3/5}. +;;; Add things at the end, unconditionally +(setq load-path (nconc load-path '("foo" "bar"))) +@end lisp -User-visible changes in behavior include (in probable order of annoyance) +@email{keithh@@nortel.ca, keith (k.p.) hanlan} writes: -@itemize -@item -Arithmetic can cause a segfault, depending on your MP library -@ref{Q5.4.2}. +@quotation +To add directories using Unix shell metacharacters use +@file{expand-file-name} like this: -@item -Terminology is not Common-Lisp-conforming. For example, ``integer'' for -Emacs Lisp means what Common Lisp calls ``fixnum''. This issue is being -investigated, but the use of ``integer'' for fixnum is pervasive and may -cause backward-compatibility and GNU-Emacs-compatibility problems. +@lisp +(push (expand-file-name "~keithh/.emacsdir") load-path) +@end lisp +@end quotation -@item -Many operations that used to cause a range error now succeed, with -intermediate results and return values coerced to bignums as needed. +@node Q7.0.5, Q7.0.6, Q7.0.4, Advanced +@unnumberedsubsec Q7.0.5: How to check if a lisp function is defined? -@item -An atom with ratio read syntax now returns a number, not a symbol. +Use the following elisp: -@item -The @samp{%u} format conversion will now give an error if its argument -is negative. (Without MP, it prints a number which Lisp can't read.) -@end itemize +@lisp +(fboundp 'foo) +@end lisp -@emph{Surgeon General's Warning}: The automatic conversions cannot be -disabled at runtime. New functions have been added which produce -ratios, so there should be few surprises with type conflicts, but they -can't be ruled out. ``Arbitrary'' precision means precisely what it -says. If you work with extremely large numbers, your machine may -arbitrarily decide to hand you an unpleasant surprise rather than a -bignum @ref{Q5.4.2}. +It's almost always a mistake to test @code{emacs-version} or any similar +variables. -To configure with GNU MP, add -@samp{--use-number-lib=gmp} -to your invocation of @file{configure}. For BSD MP, use -@samp{--use-number-lib=mp}. +Instead, use feature-tests, such as @code{featurep}, @code{boundp}, +@code{fboundp}, or even simple behavioral tests, eg.: -If you would like to help with bignum support, especially on BSD MP, -please subscribe to the @uref{http://www.xemacs.org/Lists/#xemacs-beta, -XEmacs Beta mailing list}, and book up on @file{number-gmp.h} and -@file{number-mp.h}. Jerry has promised to write internals documentation -eventually, but if your skills run more to analysis and documentation -than to writing new code, feel free to fill in the gap! +@lisp +(defvar foo-old-losing-code-p + (condition-case nil (progn (losing-code t) nil) + (wrong-number-of-arguments t))) +@end lisp +There is an incredible amount of broken code out there which could work +much better more often in more places if it did the above instead of +trying to divine its environment from the value of one variable. -@node Q5.4.2, Q5.4.3, Q5.4.1, Miscellaneous -@unnumberedsubsec Q5.4.2: XEmacs segfaults when I use very big numbers! +@node Q7.0.6, Q7.1.1, Q7.0.5, Advanced +@unnumberedsubsec Q7.0.6: Can I force the output of @code{(face-list)} to a buffer? -GMP by default allocates temporaries on the stack. If you run out of -stack space, you're dead; there is no way that we know of to reliably -detect this condition, because @samp{alloca} is typically implemented to -be @emph{fast} rather than robust. If you just need a little more -oomph, use a bigger stack (@emph{e.g.}, the @file{ulimit -s} command in -bash(1)). If you want robustness at the cost of speed, configure GMP -with @samp{--disable-alloca} and rebuild the GMP library. +It would be good having it in a buffer, as the output of +@code{(face-list)} is too wide to fit to a minibuffer. -We do not know whether BSD MP uses @samp{alloca} or not. Please send -any information you have as a bug report (@kbd{M-x report-xemacs-bug -@key{RET}}), which will give us platform information. (We do know that -BSD MP implementations vary across vendors, but how much, we do not know -yet.) +Evaluate the expression in the @samp{*scratch*} buffer with point after +the rightmost paren and typing @kbd{C-j}. +If the minibuffer smallness is the only problem you encounter, you can +simply press @kbd{C-h l} to get the former minibuffer contents in a +buffer. -@node Q5.4.3, Q5.4.4, Q5.4.2, Miscellaneous -@unnumberedsubsec Q5.4.3: Bignums are really slow! +@unnumberedsec 7.1: Emacs Lisp Programming Techniques -Many Linux distributions compile all their packages for the i386, and -this is costly. An optimized version can give you two or three orders -of magnitude better performance for a Pentium III or IV. (Yes, really. -See @uref{http://www.swox.com/gmp/gmp-speed.html}.) +@node Q7.1.1, Q7.1.2, Q7.0.6, Advanced +@unnumberedsubsec Q7.1.1: What is the difference in key sequences between XEmacs and GNU Emacs? +@email{clerik@@naggum.no, Erik Naggum} writes; -@node Q5.4.4, , Q5.4.3, Miscellaneous -@unnumberedsubsec Q5.4.4: Equal bignums don't compare as equal! What gives? +@quotation +Emacs has a legacy of keyboards that produced characters with modifier +bits, and therefore map a variety of input systems into this scheme even +today. XEmacs is instead optimized for X events. This causes an +incompatibility in the way key sequences are specified, but both Emacs +and XEmacs will accept a key sequence as a vector of lists of modifiers +that ends with a key, e.g., to bind @kbd{M-C-a}, you would say +@code{[(meta control a)]} in both Emacsen. XEmacs has an abbreviated +form for a single key, just (meta control a). Emacs has an abbreviated +form for the Control and the Meta modifiers to string-characters (the +ASCII characters), as in @samp{\M-\C-a}. XEmacs users need to be aware +that the abbreviated form works only for one-character key sequences, +while Emacs users need to be aware that the string-character is rather +limited. Specifically, the string-character can accommodate only 256 +different values, 128 of which have the Meta modifier and 128 of which +have not. In each of these blocks, only 32 characters have the Control +modifier. Whereas @code{[(meta control A)]} differs from @code{[(meta +control a)]} because the case differs, @samp{\M-\C-a} and @samp{\M-\C-A} +do not. Programmers are advised to use the full common form, both +because it is more readable and less error-prone, and because it is +supported by both Emacsen. +@end quotation -Ah, Grasshopper, I see you are using @code{(eq x y)}. The Bodhisattva -CLTL2 warned of the illusion that equal numbers would be @samp{eq}! -Meditate on the deeper truths of @samp{eql}, in which numbers of the same -type which have equal values compare equal, and @samp{=}, which does any -necessary type coercions before comparing for equality. +Another (even safer) way to be sure of the key-sequences is to use the +@code{read-kbd-macro} function, which takes a string like @samp{C-c +<up>}, and converts it to the internal key representation of the Emacs +you use. The function is available both on XEmacs and GNU Emacs. -Yeah, yeah, it has always worked for integer types, because fixnums and -characters have an immediate representation. Sorry about that; -arbitrary precision obviously requires consing new objects because the -objects are ``large'' and of variable size, and the definition of -@samp{eq} does not permit different objects to compare as equal. +@node Q7.1.2, Q7.1.3, Q7.1.1, Advanced +@unnumberedsubsec Q7.1.2: Can I generate "fake" keyboard events? +I wonder if there is an interactive function that can generate +@dfn{fake} keyboard events. This way, I could simply map them inside +XEmacs. -@node MS Windows, Current Events, Miscellaneous, Top -@unnumbered 6 XEmacs on MS Windows +This seems to work: -This is part 6 of the XEmacs Frequently Asked Questions list, written by -Hrvoje Niksic and others. This section is devoted to the MS Windows -port of XEmacs. +@lisp +(defun cg--generate-char-event (ch) + "Generate an event, as if ch has been typed" + (dispatch-event (character-to-event ch))) -@menu -General Info -* Q6.0.1:: What is the status of the XEmacs port to Windows? -* Q6.0.2:: What flavors of MS Windows are supported? The list name implies NT only. -* Q6.0.3:: Are binaries available? -* Q6.0.4:: Can I build XEmacs on MS Windows with X support? Do I need to? -* Q6.0.5:: I'd like to help out. What do I do? -* Q6.0.6:: What are Cygwin and MinGW, and do I need them to run XEmacs? -* Q6.0.7:: What exactly are all the different ways to build XEmacs under Windows? - -Building XEmacs on MS Windows: -* Q6.1.1:: What compiler/libraries do I need to compile XEmacs? -* Q6.1.2:: How do I compile the native port? -* Q6.1.3:: What do I need for Cygwin? -* Q6.1.4:: How do I compile under Cygwin? -* Q6.1.5:: How do I compile using MinGW (aka @samp{the -mno-cygwin flag to gcc})? -* Q6.1.6:: I decided to run with X. Where do I get an X server? -* Q6.1.7:: How do I compile with X support? - -Customization and User Interface: -* Q6.2.1:: How does the port cope with differences in the Windows user interface? -* Q6.2.2:: How do I change fonts in XEmacs on MS Windows? -* Q6.2.3:: Where do I put my @file{init.el}/@file{.emacs} file? -* Q6.2.4:: How do I get Windows Explorer to associate a file type with XEmacs? -* Q6.2.5:: Is it possible to print from XEmacs? - -Miscellaneous: -* Q6.3.1:: Does XEmacs rename all the @samp{win32-*} symbols to @samp{w32-*}? -* Q6.3.2:: What are the differences between the various MS Windows emacsen? -* Q6.3.3:: XEmacs 21.1 on Windows used to spawn an ugly console window on every startup. Has that been fixed? -* Q6.3.4:: What is the porting team doing at the moment? - -Troubleshooting: -* Q6.4.1:: XEmacs won't start on Windows. -* Q6.4.2:: Why do I get a blank toolbar on Windows 95? -* Q6.4.3:: XEmacs complains "No such file or directory, diff" -@end menu +;; Backspace and Delete stuff +(global-set-key [backspace] + (lambda () (interactive) (cg--generate-char-event 127))) +(global-set-key [unknown_keysym_0x4] + (lambda () (interactive) (cg--generate-char-event 4))) +@end lisp -@node Q6.0.1, Q6.0.2, MS Windows, MS Windows -@unnumberedsec 6.0: General Info -@unnumberedsubsec Q6.0.1: What is the status of the XEmacs port to Windows? - -Is XEmacs really ported to MS Windows? What is the status of the port? - -Beginning with release 21.0, XEmacs has worked under MS Windows. A -group of dedicated developers actively maintains and improves the -Windows-specific portions of the code. The mailing list at -@email{xemacs-nt@@xemacs.org} is dedicated to that effort (please use -the -request address to subscribe). (Despite its name, XEmacs actually -works on all versions of Windows.) - -As of May 2001, XEmacs on MS Windows is stable and full-featured, and -has been so for a year or more -- in fact, some features, such as -printing, actually work better on Windows than native Unix. However, -the internationalization (Mule) support does not work -- although this -is being actively worked on. +@node Q7.1.3, Q7.1.4, Q7.1.2, Advanced +@unnumberedsubsec Q7.1.3: Could you explain @code{read-kbd-macro} in more detail? +The @code{read-kbd-macro} function returns the internal Emacs +representation of a human-readable string (which is its argument). +Thus: -@node Q6.0.2, Q6.0.3, Q6.0.1, MS Windows -@unnumberedsubsec Q6.0.2: What flavors of MS Windows are supported? The list name implies NT only. +@lisp +(read-kbd-macro "C-c C-a") +@result{} [(control ?c) (control ?a)] -The list name is misleading, as XEmacs supports and has been compiled on -Windows 95, Windows 98, Windows NT, Windows 2000, Windows ME, Windows -XP, and all newer versions of Windows. The MS Windows-specific code is -based on Microsoft Win32 API, and will not work on MS Windows 3.x or on -MS-DOS. +(read-kbd-macro "C-c C-. <up>") +@result{} [(control ?c) (control ?.) up] +@end lisp -XEmacs also supports the Cygwin and MinGW development and runtime -environments, where it also uses native Windows code for graphical -features. +In GNU Emacs the same forms will be evaluated to what GNU Emacs +understands internally---the sequences @code{"\C-x\C-c"} and @code{[3 +67108910 up]}, respectively. +The exact @dfn{human-readable} syntax is defined in the docstring of +@code{edmacro-mode}. I'll repeat it here, for completeness. -@node Q6.0.3, Q6.0.4, Q6.0.2, MS Windows -@unnumberedsubsec Q6.0.3: Are binaries available? +@quotation +Format of keyboard macros during editing: -Binaries are available at @uref{http://www.xemacs.org/Download/win32/} -for the native and Cygwin MS Windows versions of 21.4, and the native -version of 21.1. +Text is divided into @dfn{words} separated by whitespace. Except for +the words described below, the characters of each word go directly as +characters of the macro. The whitespace that separates words is +ignored. Whitespace in the macro must be written explicitly, as in +@kbd{foo @key{SPC} bar @key{RET}}. -The 21.4 binaries use a modified version of the Cygwin installer. Run -the provided @file{setup.exe}, and follow the instructions. +@itemize @bullet +@item +The special words @kbd{RET}, @kbd{SPC}, @kbd{TAB}, @kbd{DEL}, @kbd{LFD}, +@kbd{ESC}, and @kbd{NUL} represent special control characters. The +words must be written in uppercase. +@item +A word in angle brackets, e.g., @code{<return>}, @code{<down>}, or +@code{<f1>}, represents a function key. (Note that in the standard +configuration, the function key @code{<return>} and the control key +@key{RET} are synonymous.) You can use angle brackets on the words +@key{RET}, @key{SPC}, etc., but they are not required there. -@node Q6.0.4, Q6.0.5, Q6.0.3, MS Windows -@unnumberedsubsec Q6.0.4: Can I build XEmacs on MS Windows with X support? Do I need to? +@item +Keys can be written by their @sc{ascii} code, using a backslash followed +by up to six octal digits. This is the only way to represent keys with +codes above \377. -Yes, you can, but no you do not need to. In fact, we recommend that you -use a native-GUI version unless you have a specific need for an X -version. +@item +One or more prefixes @kbd{M-} (meta), @kbd{C-} (control), @kbd{S-} +(shift), @kbd{A-} (alt), @kbd{H-} (hyper), and @kbd{s-} (super) may +precede a character or key notation. For function keys, the prefixes +may go inside or outside of the brackets: @code{C-<down>} @equiv{} +@code{<C-down>}. The prefixes may be written in any order: @kbd{M-C-x} +@equiv{} @kbd{C-M-x}. -@node Q6.0.5, Q6.0.6, Q6.0.4, MS Windows -@unnumberedsubsec Q6.0.5: I'd like to help out. What do I do? +Prefixes are not allowed on multi-key words, e.g., @kbd{C-abc}, except +that the Meta prefix is allowed on a sequence of digits and optional +minus sign: @kbd{M--123} @equiv{} @kbd{M-- M-1 M-2 M-3}. -It depends on the knowledge and time you possess. If you are a -programmer, try to build XEmacs and see if you can improve it. -Windows-specific improvements like integration with established -Windows environments are especially sought after. +@item +The @code{^} notation for control characters also works: @kbd{^M} +@equiv{} @kbd{C-m}. + +@item +Double angle brackets enclose command names: @code{<<next-line>>} is +shorthand for @kbd{M-x next-line @key{RET}}. -Otherwise, you can still help by downloading the binaries, using -XEmacs as your everyday editor and reporting bugs you find to the -mailing list. +@item +Finally, @code{REM} or @code{;;} causes the rest of the line to be +ignored as a comment. +@end itemize -Another area where we need help is the documentation: We need good -documentation for building XEmacs and for using it. This FAQ is a -small step in that direction. +Any word may be prefixed by a multiplier in the form of a decimal number +and @code{*}: @code{3*<right>} @equiv{} @code{<right> <right> <right>}, +and @code{10*foo} @equiv{} +@iftex +@* +@end iftex +@code{foofoofoofoofoofoofoofoofoofoo}. -@node Q6.0.6, Q6.0.7, Q6.0.5, MS Windows -@unnumberedsubsec Q6.0.6: What are Cygwin and MinGW, and do I need them to run XEmacs? +Multiple text keys can normally be strung together to form a word, but +you may need to add whitespace if the word would look like one of the +above notations: @code{; ; ;} is a keyboard macro with three semicolons, +but @code{;;;} is a comment. Likewise, @code{\ 1 2 3} is four keys but +@code{\123} is a single key written in octal, and @code{< right >} is +seven keys but @code{<right>} is a single function key. When in doubt, +use whitespace. +@end quotation -To answer the second part of the question: No, you, you don't need -Cygwin or MinGW to build or to run XEmacs. But if you have them and -want to use them, XEmacs supports these environments. +@node Q7.1.4, Q7.1.5, Q7.1.3, Advanced +@unnumberedsubsec Q7.1.4: What is the performance hit of @code{let}? -(One important reason to support Cygwin is that it lets the MS Windows -developers test out their code in a Unix environment without actually -having to have a Unix machine around. For this reason alone, Cygwin -support is likely to remain supported for a long time in XEmacs. Same -goes for the X support under Cygwin, for the same reasons. MinGW -support, on the other hand, depends on volunteers to keep it up to date; -but this is generally not hard.) +In most cases, not noticeable. Besides, there's no avoiding +@code{let}---you have to bind your local variables, after all. Some +pose a question whether to nest @code{let}s, or use one @code{let} per +function. I think because of clarity and maintenance (and possible +future implementation), @code{let}-s should be used (nested) in a way to +provide the clearest code. -Cygwin is a set of tools providing Unix-like API on top of Win32. -It makes it easy to port large Unix programs without significant -changes to their source code. It is a development environment as well -as a runtime environment. +@node Q7.1.5, Q7.1.6, Q7.1.4, Advanced +@unnumberedsubsec Q7.1.5: What is the recommended use of @code{setq}? + +@itemize @bullet +@item Global variables -When built with Cygwin, XEmacs supports all display types -- TTY, X & -Win32 GUI, and can be built with support for all three simultaneously. -If you build with Win32 GUI support then the Cygwin version uses the -majority of the Windows-specific code, which is mostly related to -display. If you want to build with X support you need X libraries (and -an X server to display XEmacs on); see @ref{Q6.1.4}. TTY and Win32 GUI -require no additional libraries beyond what comes standard with Cygwin. +You will typically @code{defvar} your global variable to a default +value, and use @code{setq} to set it later. -The advantages of the Cygwin version are that it integrates well with -the Cygwin environment for existing Cygwin users; uses configure so -building with different features is very easy; and actively supports X & -TTY. Furthermore, the entire Cygwin environment and compiler are free, -whereas Visual C++ costs money. +It is never a good practice to @code{setq} user variables (like +@code{case-fold-search}, etc.), as it ignores the user's choice +unconditionally. Note that @code{defvar} doesn't change the value of a +variable if it was bound previously. If you wish to change a +user-variable temporarily, use @code{let}: -The disadvantage is that it requires the whole Cygwin environment, -whereas the native port requires only a suitable MS Windows compiler. -Also, it follows the Unix filesystem and process model very closely -(some will undoubtedly view this as an advantage). +@lisp +(let ((case-fold-search nil)) + ... ; code with searches that must be case-sensitive + ...) +@end lisp -See @uref{http://sources.redhat.com/cygwin/} for more information on -Cygwin. +You will notice the user-variables by their docstrings beginning with an +asterisk (a convention). -MinGW is a collection of header files and import libraries that allow -one to use GCC under the Cygwin environment to compile and produce -exactly the same native Win32 programs that you can using Visual C++. -Programs compiled with MinGW make use of the standard Microsoft runtime -library @file{MSVCRT.DLL}, present on all Windows systems, and look, -feel, and act like a standard Visual-C-produced application. (The only -difference is the compiler.) This means that, unlike a -standardly-compiled Cygwin application, no extra runtime support -(e.g. Cygwin's @file{cygwin1.dll}) is required. This, along with the -fact that GCC is free (and works in a nice Unix-y way in a nice Unix-y -environment, for those die-hard Unix hackers out there), is the main -advantage of MinGW. It is also potentially faster than Cygwin because -it has less overhead when calling Windows, but you lose the POSIX -emulation layer, which makes Unix programs harder to port. (But this is -irrelevant for XEmacs since it's already ported to Win32.) +@item Local variables -See @uref{http://www.mingw.org/} for more information on MinGW. +Bind them with @code{let}, which will unbind them (or restore their +previous value, if they were bound) after exiting from the @code{let} +form. Change the value of local variables with @code{setq} or whatever +you like (e.g. @code{incf}, @code{setf} and such). The @code{let} form +can even return one of its local variables. -@node Q6.0.7, Q6.1.1, Q6.0.6, MS Windows -@unnumberedsubsec Q6.0.7: What exactly are all the different ways to build XEmacs under Windows? +Typical usage: -XEmacs can be built in several ways in the MS Windows environment. +@lisp +;; iterate through the elements of the list returned by +;; `hairy-function-that-returns-list' +(let ((l (hairy-function-that-returns-list))) + (while l + ... do something with (car l) ... + (setq l (cdr l)))) +@end lisp -The standard way is what we call the "native" port. It uses the Win32 -API and has no connection with X whatsoever -- it does not require X -libraries to build, nor does it require an X server to run. The native -port is the most reliable version and provides the best graphical -support. Almost all development is geared towards this version, and -there is little reason not to use it. +Another typical usage includes building a value simply to work with it. -The second way to build is the Cygwin port. It takes advantage of -Cygnus emulation library under Win32. @xref{Q6.0.6}, for more -information. +@lisp +;; Build the mode keymap out of the key-translation-alist +(let ((inbox (file-truename (expand-file-name box))) + (i 0)) + ... code dealing with inbox ... + inbox) +@end lisp -A third way is the MinGW port. It uses the Cygwin environment to build -but does not require it at runtime. @xref{Q6.0.6}, for more -information. +This piece of code uses the local variable @code{inbox}, which becomes +unbound (or regains old value) after exiting the form. The form also +returns the value of @code{inbox}, which can be reused, for instance: -Finally, you might also be able to build the non-Cygwin, non-MinGW "X" -port. This was actually the first version of XEmacs that ran under MS -Windows, and although the code is still in XEmacs, it's essentially -orphaned and it's unlikely it will compile without a lot of work. If -you want an MS Windows versin of XEmacs that supports X, use the Cygwin -version. (The X support there is actively maintained, so that Windows -developers can test the X support in XEmacs.) +@lisp +(setq foo-processed-inbox + (let .....)) +@end lisp +@end itemize +@node Q7.1.6, Q7.1.7, Q7.1.5, Advanced +@unnumberedsubsec Q7.1.6: What is the typical misuse of @code{setq}? -@node Q6.1.1, Q6.1.2, Q6.0.7, MS Windows -@unnumberedsec 6.1: Building XEmacs on MS Windows -@unnumberedsubsec Q6.1.1: What compiler/libraries do I need to compile XEmacs? +A typical misuse is probably @code{setq}ing a variable that was meant to +be local. Such a variable will remain bound forever, never to be +garbage-collected. For example, the code doing: -You need Visual C++ 4.2, 5.0, or 6.0 for the native version. (We have -some beta testers currently trying to compile with VC.NET, aka version -7.0, but we can't yet report complete success.) For the Cygwin and MinGW -versions, you need the Cygwin environment, which comes with GCC, the -compiler used for those versions. @xref{Q6.0.6}, for more information -on Cygwin and MinGW. +@lisp +(defun my-function (whatever) + (setq a nil) + ... build a large list ... + ... and exit ...) +@end lisp -@node Q6.1.2, Q6.1.3, Q6.1.1, MS Windows -@unnumberedsubsec Q6.1.2: How do I compile the native port? +does a bad thing, as @code{a} will keep consuming memory, never to be +unbound. The correct thing is to do it like this: -Please read the file @file{nt/README} in the XEmacs distribution, which -contains the full description. +@lisp +(defun my-function (whatever) + (let (a) ; default initialization is to nil + ... build a large list ... + ... and exit, unbinding `a' in the process ...) +@end lisp -@node Q6.1.3, Q6.1.4, Q6.1.2, MS Windows -@unnumberedsubsec Q6.1.3: What do I need for Cygwin? +Not only is this prettier syntactically, but it makes it possible for +Emacs to garbage-collect the objects which @code{a} used to reference. -You can find the Cygwin tools and compiler at: +Note that even global variables should not be @code{setq}ed without +@code{defvar}ing them first, because the byte-compiler issues warnings. +The reason for the warning is the following: -@uref{http://sources.redhat.com/cygwin/} +@lisp +(defun flurgoze nil) ; ok, global internal variable +... -Click on the @samp{Install now!} link, which will download a file -@file{setup.exe}, which you can use to download everything else. (You -will need to pick a mirror site; @samp{mirrors.rcn.net} is probably the -best.) You should go ahead and install everything -- you'll get various -ancillary libraries that XEmacs needs or likes, e.g. XPM, PNG, JPEG, -TIFF, etc. +(setq flurghoze t) ; ops! a typo, but semantically correct. + ; however, the byte-compiler warns. -If you want to compile under X, you will also need the X libraries; see -@ref{Q6.1.6}. +While compiling toplevel forms: +** assignment to free variable flurghoze +@end lisp -If you want to compile without X, you will need the @file{xpm-nox} -library, which must be specifically selected in the Cygwin netinstaller; -it is not selected by default. The package has had various names. -Currently it is called @file{cygXpm-noX4.dll}. +@node Q7.1.7, Q7.1.8, Q7.1.6, Advanced +@unnumberedsubsec Q7.1.7: I like the @code{do} form of cl, does it slow things down? +It shouldn't. Here is what Dave Gillespie has to say about cl.el +performance: -@node Q6.1.4, Q6.1.5, Q6.1.3, MS Windows -@unnumberedsubsec Q6.1.4: How do I compile under Cygwin? +@quotation +Many of the advanced features of this package, such as @code{defun*}, +@code{loop}, and @code{setf}, are implemented as Lisp macros. In +byte-compiled code, these complex notations will be expanded into +equivalent Lisp code which is simple and efficient. For example, the +forms -Similar as on Unix; use the usual `configure' and `make' process. -Some problems to watch out for: +@lisp +(incf i n) +(push x (car p)) +@end lisp -@itemize @bullet -@item -make sure HOME is set. This controls where you -@file{init.el}/@file{.emacs} file comes from; +are expanded at compile-time to the Lisp forms -@item -CYGWIN needs to be set to tty for process support to work, e.g. CYGWIN=tty; +@lisp +(setq i (+ i n)) +(setcar p (cons x (car p))) +@end lisp -@item -picking up some other grep or other UNIX-like tools can kill configure; +which are the most efficient ways of doing these respective operations +in Lisp. Thus, there is no performance penalty for using the more +readable @code{incf} and @code{push} forms in your compiled code. -@item -static heap too small, adjust @file{src/sheap-adjust.h} to a more positive -number; +@emph{Interpreted} code, on the other hand, must expand these macros +every time they are executed. For this reason it is strongly +recommended that code making heavy use of macros be compiled. (The +features labelled @dfn{Special Form} instead of @dfn{Function} in this +manual are macros.) A loop using @code{incf} a hundred times will +execute considerably faster if compiled, and will also garbage-collect +less because the macro expansion will not have to be generated, used, +and thrown away a hundred times. -@item -(Unconfirmed) The Cygwin version doesn't understand -@file{//machine/path} type paths so you will need to manually mount a -directory of this form under a unix style directory for a build to work -on the directory; +You can find out how a macro expands by using the @code{cl-prettyexpand} +function. +@end quotation -@item -If you're building @strong{WITHOUT} X11, don't forget to change symlinks -@file{/usr/lib/libXpm.a} and @file{/usr/lib/libXpm.dll.a} to point to -the non-X versions of these libraries. By default they point to the X -versions. So: +@node Q7.1.8, Q7.1.9, Q7.1.7, Advanced +@unnumberedsubsec Q7.1.8: I like recursion, does it slow things down? -@example -/usr/lib/libXpm.a -> /usr/lib/libXpm-noX.a -/usr/lib/libXpm.dll.a -> /usr/lib/libXpm-noX.dll.a -@end example +Yes. The Emacs byte-compiler cannot do much to optimize recursion. But +think well whether this is a real concern in Emacs. Much of the Emacs +slowness comes from internal mechanisms such as redisplay, or from the +fact that it is an interpreter. -(This advice may now be obsolete because of the availability of the -cygXpm-noX4.dll package from Cygwin. Send confirmation to -@email{faq@@xemacs.org}.) +Please try not to make your code much uglier to gain a very small speed +gain. It's not usually worth it. -@item -Other problems are listed in the @file{PROBLEMS} file, in the top-level -directory of the XEmacs sources. +@node Q7.1.9, Q7.1.10, Q7.1.8, Advanced +@unnumberedsubsec Q7.1.9: How do I put a glyph as annotation in a buffer? -@end itemize +Here is a solution that will insert the glyph annotation at the +beginning of buffer: +@lisp +(make-annotation (make-glyph '([FORMAT :file FILE] + [string :data "fallback-text"])) + (point-min) + 'text + (current-buffer)) +@end lisp -@node Q6.1.5, Q6.1.6, Q6.1.4, MS Windows -@unnumberedsubsec Q6.1.5: How do I compile using MinGW (aka @samp{the -mno-cygwin flag to gcc})? +Replace @samp{FORMAT} with an unquoted symbol representing the format of +the image (e.g. @code{xpm}, @code{xbm}, @code{gif}, @code{jpeg}, etc.) +Instead of @samp{FILE}, use the image file name +(e.g. +@iftex +@* +@end iftex +@file{/usr/local/lib/xemacs-21.4/etc/recycle.xpm}). -Similar to the method for Unix. Things to remember: +You can turn this to a function (that optionally prompts you for a file +name), and inserts the glyph at @code{(point)} instead of +@code{(point-min)}. -@itemize @bullet -@item -Specify the target host on the command line for @file{./configure}, e.g. -@samp{./configure i586-pc-mingw32}. +@node Q7.1.10, Q7.1.11, Q7.1.9, Advanced +@unnumberedsubsec Q7.1.10: @code{map-extents} won't traverse all of my extents! -@item -Be sure that your build directory is mounted such that it has the -same path either as a cygwin path (@file{/build/xemacs}) or as a Windows -path (@file{c:\build\xemacs}). +I tried to use @code{map-extents} to do an operation on all the extents +in a region. However, it seems to quit after processing a random number +of extents. Is it buggy? -@item -Build @samp{gcc -mno-cygwin} versions of the extra libs, i.e. @file{libpng}, -@file{compface}, etc. +No. The documentation of @code{map-extents} states that it will iterate +across the extents as long as @var{function} returns @code{nil}. +Unexperienced programmers often forget to return @code{nil} explicitly, +which results in buggy code. For instance, the following code is +supposed to delete all the extents in a buffer, and issue as many +@samp{fubar!} messages. -@item -Specify the target location of the extra libs on the command line -to @file{configure}, e.g. -@samp{./configure --site-prefixes=/build/libs i586-pc-mingw32}. -@end itemize +@lisp +(map-extents (lambda (ext ignore) + (delete-extent ext) + (message "fubar!"))) +@end lisp +Instead, it will delete only the first extent, and stop right there -- +because @code{message} will return a non-nil value. The correct code +is: -@node Q6.1.6, Q6.1.7, Q6.1.5, MS Windows -@unnumberedsubsec Q6.1.6: I decided to run with X. Where do I get an X server? +@lisp +(map-extents (lambda (ext ignore) + (delete-extent ext) + (message "fubar!") + nil)) +@end lisp -As of May 2001, we are recommending that you use the port of XFree86 to -Cygwin. This has recently stabilized, and will undoubtedly soon make -most other MS Windows X servers obsolete. It is what the Windows -developers use to test the MS Windows X support. - -To install, go to @uref{http://xfree86.cygwin.com/}. There is a -detailed description on that site of exactly how to install it. This -installation also provides the libraries, include files, and other stuff -needed for development; a large collection of internationalized fonts; -the standard X utilities (xterm, twm, etc.) -- in a word, the works. - -NOTE: As of late May 2001, there is a bug in the file -@file{startxwin.bat}, used to start X Windows. It passes the option -@samp{-engine -4} to the X server, which is bogus -- you need to edit -the file and change it to @samp{-engine 4}. - - -@node Q6.1.7, Q6.2.1, Q6.1.6, MS Windows -@unnumberedsubsec Q6.1.7: How do I compile with X support? - -To compile under Cygwin, all you need to do is install XFree86 -(@pxref{Q6.1.6}). Once installed, @file{configure} should automatically -find the X libraries and compile with X support. +@node Q7.1.11, Q7.2.1, Q7.1.10, Advanced +@unnumberedsubsec Q7.1.11: My elisp program is horribly slow. Is there an easy way to find out where it spends time? +@c New -As noted above, the non-Cygwin X support is basically orphaned, and -probably won't work. But if it want to try, it's described in -@file{nt/README} in some detail. Basically, you need to get X11 -libraries from ftp.x.org, and compile them. If the precompiled versions -are available somewhere, we don't know of it. +@email{hniksic@@xemacs.org, Hrvoje Niksic} writes: +@quotation +Under XEmacs 20.4 and later you can use @kbd{M-x profile-key-sequence}, +press a key (say @key{RET} in the Gnus Group buffer), and get the +results using @kbd{M-x profile-results}. It should give you an idea of +where the time is being spent. +@end quotation +@unnumberedsec 7.2: Mathematics -@node Q6.2.1, Q6.2.2, Q6.1.7, MS Windows -@unnumberedsec 6.2: Customization and User Interface -@unnumberedsubsec Q6.2.1: How does the port cope with differences in the Windows user interface? +@node Q7.2.1, Q7.2.2, Q7.1.11, Advanced +@unnumberedsubsec Q7.2.1: What are bignums, ratios, and bigfloats in Lisp? -The XEmacs (and Emacs in general) user interface is pretty different -from what is expected of a typical MS Windows program. How does the MS -Windows port cope with it? +Thanks to @email{james@@xemacs.org, Jerry James}, XEmacs 21.5.18 and +later can use the capabilities of multiple-precision libraries that may +be available for your platform. The GNU Multiple Precision (GMP) and +BSD Multiple Precision (MP) libraries are partially supported. GMP +gives you @dfn{bignums} (arbitrary precision integers), @dfn{ratios} +(arbitrary precision fractions), and @dfn{bigfloats} (arbitrary +precision floating point numbers). GNU MP is better-supported by XEmacs +at the time of writing (2004-04-06). BSD MP support does not include +ratios or bigfloats, and it throws errors that aren't understood. -As a general rule, we follow native MS Windows conventions as much as -possible. 21.4 is a fairly complete Windows application, supporting -native printing, system file dialog boxes, tool tips, etc. In cases -where there's a clear UI conflict, we currently use normal Unix XEmacs -behavior by default, but make sure the MS Windows "look and feel" (mark -via shift-arrow, self-inserting deletes region, Alt selects menu items, -etc.) is easily configurable (respectively: using the variable -@code{shifted-motion-keys-select-region} in 21.4 and above [it's in fact -the default in these versions], or the @file{pc-select} package; using -the @file{pending-del} package; and setting the variable -@code{menu-accelerator-enabled} to @code{menu-force} in 21.4 and above). -In fact, if you use the sample @file{init.el} file as your init file, -you will get all these behaviors automatically turned on. +In most cases, bignum support should be transparent to users and Lisp +programmers. A bignum-enabled XEmacs will automatically convert from +fixnums to bignums and back in pure integer arithmetic, and for GNU MP, +from floats to bigfloats. (Bigfloats must be explicitly coerced to +other types, even if they are exactly representable by less precise +types.) The Lisp reader and printer have been enhanced to handle +bignums, as have the mathematical functions. Rationals (fixnums, +bignums, and ratios) are printed using the @samp{%d}, @samp{%o}, +@samp{%x}, and @samp{%u} format conversions. The read syntax for ratios +is @samp{3/5}. -In future versions, some of these features might be turned on by -default in the MS Windows environment. +User-visible changes in behavior include (in probable order of annoyance) +@itemize +@item +Arithmetic can cause a segfault, depending on your MP library +@ref{Q7.2.2, XEmacs segfaults when I use very big numbers!}. -@node Q6.2.2, Q6.2.3, Q6.2.1, MS Windows -@unnumberedsubsec Q6.2.2: How do I change fonts in XEmacs on MS Windows? +@item +Terminology is not Common-Lisp-conforming. For example, ``integer'' for +Emacs Lisp means what Common Lisp calls ``fixnum''. This issue is being +investigated, but the use of ``integer'' for fixnum is pervasive and may +cause backward-compatibility and GNU-Emacs-compatibility problems. -In 21.4 and above, you can use the "Options" menu to change the font. -You can also do it in your init file, e.g. like this: +@item +Many operations that used to cause a range error now succeed, with +intermediate results and return values coerced to bignums as needed. -@display - (set-face-font 'default "Lucida Console:Regular:10") - (set-face-font 'modeline "MS Sans Serif:Regular:10") -@end display +@item +An atom with ratio read syntax now returns a number, not a symbol. +@item +The @samp{%u} format conversion will now give an error if its argument +is negative. (Without MP, it prints a number which Lisp can't read.) +@end itemize -@node Q6.2.3, Q6.2.4, Q6.2.2, MS Windows -@unnumberedsubsec Q6.2.3: Where do I put my @file{init.el}/@file{.emacs} file? +@emph{Surgeon General's Warning}: The automatic conversions cannot be +disabled at runtime. New functions have been added which produce +ratios, so there should be few surprises with type conflicts, but they +can't be ruled out. ``Arbitrary'' precision means precisely what it +says. If you work with extremely large numbers, your machine may +arbitrarily decide to hand you an unpleasant surprise rather than a +bignum @ref{Q7.2.2, XEmacs segfaults when I use very big numbers!}. -@file{init.el} is the name of the init file starting with 21.4, and is -located in the subdirectory @file{.xemacs/} of your home directory. In -prior versions, the init file is called @file{.emacs} and is located in -your home directory. Your home directory under Windows is determined by -the @samp{HOME} environment variable. If this is not set, it defaults to -@samp{C:\}. +To configure with GNU MP, add +@samp{--use-number-lib=gmp} +to your invocation of @file{configure}. For BSD MP, use +@samp{--use-number-lib=mp}. -To set this variable, modify @file{AUTOEXEC.BAT} under Windows 95/98, or -select @samp{Control Panel->System->Advanced->Environment Variables...} -under Windows NT/2000. +If you would like to help with bignum support, especially on BSD MP, +please subscribe to the @uref{http://www.xemacs.org/Lists/#xemacs-beta, +XEmacs Beta mailing list}, and book up on @file{number-gmp.h} and +@file{number-mp.h}. Jerry has promised to write internals documentation +eventually, but if your skills run more to analysis and documentation +than to writing new code, feel free to fill in the gap! -@node Q6.2.4, Q6.2.5, Q6.2.3, MS Windows -@unnumberedsubsec Q6.2.4: How do I get Windows Explorer to associate a file type with XEmacs? +@node Q7.2.2, Q7.2.3, Q7.2.1, Advanced +@unnumberedsubsec Q7.2.2: XEmacs segfaults when I use very big numbers! -@unnumberedsubsubsec Associating a new file type with XEmacs. +GMP by default allocates temporaries on the stack. If you run out of +stack space, you're dead; there is no way that we know of to reliably +detect this condition, because @samp{alloca} is typically implemented to +be @emph{fast} rather than robust. If you just need a little more +oomph, use a bigger stack (@emph{e.g.}, the @file{ulimit -s} command in +bash(1)). If you want robustness at the cost of speed, configure GMP +with @samp{--disable-alloca} and rebuild the GMP library. -In Explorer select @samp{View/Options/File Types}, press @samp{[New -Type...]} and fill in the dialog box, e.g.: +We do not know whether BSD MP uses @samp{alloca} or not. Please send +any information you have as a bug report (@kbd{M-x report-xemacs-bug +@key{RET}}), which will give us platform information. (We do know that +BSD MP implementations vary across vendors, but how much, we do not know +yet.) -@example - Description of type: Emacs Lisp source - Associated extension: el - Content Type (MIME): text/plain -@end example -then press @samp{[New...]} and fill in the @samp{Action} dialog box as -follows: +@node Q7.2.3, Q7.2.4, Q7.2.2, Advanced +@unnumberedsubsec Q7.2.3: Bignums are really slow! -@example - Action: - Open +Many Linux distributions compile all their packages for the i386, and +this is costly. An optimized version can give you two or three orders +of magnitude better performance for a Pentium III or IV. (Yes, really. +See @uref{http://www.swox.com/gmp/gmp-speed.html}.) - Application used to perform action: - D:\Full\path\for\xemacs.exe "%1" - [x] Use DDE +@node Q7.2.4, , Q7.2.3, Advanced +@unnumberedsubsec Q7.2.4: Equal bignums don't compare as equal! What gives? - DDE Message: - open("%1") +Ah, Grasshopper, I see you are using @code{(eq x y)}. The Bodhisattva +CLTL2 warned of the illusion that equal numbers would be @samp{eq}! +Meditate on the deeper truths of @samp{eql}, in which numbers of the same +type which have equal values compare equal, and @samp{=}, which does any +necessary type coercions before comparing for equality. - Application: - <leave blank> +Yeah, yeah, it has always worked for integer types, because fixnums and +characters have an immediate representation. Sorry about that; +arbitrary precision obviously requires consing new objects because the +objects are ``large'' and of variable size, and the definition of +@samp{eq} does not permit different objects to compare as equal. - DDE Application Not Running: - <leave blank> +@node Other Packages, Current Events, Advanced, Top +@unnumbered 8 Other External Packages - Topic: - <leave blank> -@end example +This is part 8 of the XEmacs Frequently Asked Questions list. This +section is devoted to miscellaneous external packages not covered +elsewhere in XEmacs. -@unnumberedsubsubsec Associating an existing file type with XEmacs. +@menu +8.0: TeX +* Q8.0.1:: Is there something better than LaTeX mode? +* Q8.0.2:: What is AUCTeX? Where do you get it? +* Q8.0.3:: Problems installing AUCTeX. +* Q8.0.4:: How do I turn off current chapter from AUCTeX modeline? + +8.1: Other Unbundled Packages +* Q8.1.1:: Is there a reason for an Emacs package not to be included in XEmacs? +* Q8.1.2:: Are there any Emacs Lisp Spreadsheets? +* Q8.1.3:: Is there a MatLab mode? + +8.2: Environments Built Around XEmacs +* Q8.2.1:: What are SPARCworks, EOS, and WorkShop? +* Q8.2.2:: How do I start the Sun Workshop support in XEmacs 21? +* Q8.2.3:: What is/was Energize? +* Q8.2.4:: What is Infodock? +@end menu -In Explorer select @samp{View/Options/File Types}. Click on the file -type in the list and press @samp{[Edit...]}. If the file type already -has an @samp{Open} action, double click on it and fill in the -@samp{Action} dialog box as described above; otherwise create a new -action. +@unnumberedsec 8.0: TeX -If the file type has more than one action listed, you probably want to -make the @samp{Open} action that you just edited the default by clicking on -it and pressing @samp{Set Default}. +@node Q8.0.1, Q8.0.2, Other Packages, Other Packages +@unnumberedsubsec Q8.0.1: Is there something better than LaTeX mode? -Note for Windows 2000 users: Under Windows 2000, get to @samp{File Types} -using @samp{Control Panel->Folder Options->File Types}. +@email{dak@@fsnif.neuroinformatik.ruhr-uni-bochum.de, David Kastrup} writes: +@quotation +The standard TeX modes leave much to be desired, and are somewhat +leniently maintained. Serious TeX users use AUCTeX (@pxref{Q8.0.2, +What is AUCTeX? Where do you get it?}). +@end quotation -@node Q6.2.5, Q6.3.1, Q6.2.4, MS Windows -@unnumberedsubsec Q6.2.5: Is it possible to print from XEmacs? +@node Q8.0.2, Q8.0.3, Q8.0.1, Other Packages +@unnumberedsubsec Q8.0.2: What is AUCTeX? Where do you get it? -As of 21.4, printing works on Windows, using simply @samp{File->Print}, -and can be configured with @samp{File->Page Setup}. +AUCTeX is a complex and sophisticated editing package dedicated to TeX +and related text formatting languages, including LaTeX and Texinfo. +It provides support for running TeX on a file or part of a file, +include files, and of course shortcuts for entering common TeX macros, +LaTeX environments, etc, and for fontlock. + +AUCTeX is a standard package provided by XEmacs. You can get it as +usual through the @kbd{M-x list-packages} interface. It is also +included in the (non-Mule) SUMO package. The AUCTeX XEmacs package is +maintained by Uwe Brauer <GET MAIL ADDRESS>. + +AUCTeX is extremely complicated, and its developers primarily +use GNU Emacs. Not all features of the bleeding edge version +of AUCTeX are immediately ported to XEmacs; if you need +these, you may be better off getting the most recent versions +from the GNU AUCTeX project on @uref{http://savannah.gnu.org}. + +@node Q8.0.3, Q8.0.4, Q8.0.2, Other Packages +@unnumberedsubsec Q8.0.3: Problems installing AUCTeX. -Prior to 21.4, there is no built-in support, but there are some clever -hacks out there. If you know how, please let us know and we'll put it -here. +@email{vroonhof@@math.ethz.ch, Jan Vroonhof} writes: +@quotation +AUCTeX works fine on both stock Emacs and XEmacs has been doing so for +a very very long time. This is mostly due to the work of +@email{abraham@@dina.kvl.dk, Per Abrahamsen} (clap clap) in particular his @file{easymenu} +package. Which leads to what is probably the problem... +@end quotation -@node Q6.3.1, Q6.3.2, Q6.2.5, MS Windows -@unnumberedsec 6.3: Miscellaneous -@unnumberedsubsec Q6.3.1: Does XEmacs rename all the @samp{win32-*} symbols to @samp{w32-*}? +Most problems with AUCTeX are one of two things: -In his flavor of Emacs 20, Richard Stallman has renamed all the @samp{win32-*} -symbols to @samp{w32-*}. Does XEmacs do the same? +@itemize @bullet +@item +The TeX-lisp-directory in @file{tex-site.el} and the makefile don't +match. -We consider such a move counter-productive, thus we do not use the -@samp{w32} prefix. (His rather questionable justification was that he -did not consider Windows to be a "winning" platform.) However, the name -@samp{Win32} is not particularly descriptive outside the Windows world, -and using just @samp{windows-} would be too generic. So we chose a -compromise, the prefix @samp{mswindows-} for Windows-related variables -and functions. +Fix: make sure you configure AUCTeX properly @strong{before} installing. -Thus all the XEmacs variables and functions directly related to either -the Windows GUI or OS are prefixed @samp{mswindows-} (except for a -couple of debugging variables, prefixed @samp{debug-mswindows-}). From -an architectural perspective, however, we believe that this is mostly a -non-issue because there should be a very small number of -window-systems-specific variables anyway. Whenever possible, we try to -provide generic interfaces that apply to all window systems. +@item +You have an old version of easymenu.el in your path. -@c not true: -@c The user variables -@c that share functionality with existing NT Emacs variables are be named -@c with our convention, but we provide the GNU Emacs names as -@c compatibility aliases. +Fix: use @code{locate-library} and remove old versions to make sure it +@strong{only} finds the one that came with XEmacs. +@end itemize +@node Q8.0.4, Q8.1.1, Q8.0.3, Other Packages +@unnumberedsubsec Q8.0.4: How do I turn off current chapter from AUCTeX modeline? -@node Q6.3.2, Q6.3.3, Q6.3.1, MS Windows -@unnumberedsubsec Q6.3.2: What are the differences between the various MS Windows emacsen? +With AUCTeX, fast typing is hard because the current chapter, section +etc. are given in the modeline. How can I turn this off? -XEmacs, Win-Emacs, DOS Emacs, NT Emacs, this is all very confusing. -Could you briefly explain the differences between them? +It's not AUCTeX, it comes from @code{func-menu} in @file{func-menu.el}. -Here is a recount of various Emacs versions running on MS Windows: +@c Add this code to your @file{init.el} to turn it off: +@c +@c @lisp +@c (setq fume-display-in-modeline-p nil) +@c @end lisp +@c +@c Or just add a hook to @code{TeX-mode-hook} to turn it off only for TeX +@c mode: +@c +@c @lisp +@c (add-hook 'TeX-mode-hook +@c '(lambda () (setq fume-display-in-modeline-p nil))) +@c @end lisp +@c +@email{dhughes@@origin-at.co.uk, David Hughes} writes: -@itemize @bullet +@quotation +Try this; you'll still get the function name displayed in the modeline, +but it won't attempt to keep track when you modify the file. To refresh +when it gets out of synch, you simply need click on the @samp{Rescan +Buffer} option in the function-menu. -@item -XEmacs +@lisp +(setq-default fume-auto-rescan-buffer-p nil) +@end lisp +@end quotation -@itemize @minus +@unnumberedsec 8.1: Other Unbundled Packages -@item -Beginning with XEmacs 19.12, XEmacs' architecture was redesigned -in such a way to allow clean support of multiple window systems. At -this time the TTY support was added, making X and TTY the first two -"window systems" supported by XEmacs. The 19.12 design is the basis for -the current native MS Windows code. +@node Q8.1.1, Q8.1.2, Q8.0.4, Other Packages +@unnumberedsubsec Q8.1.1: Is there a reason for an Emacs package not to be included in XEmacs? -@item -Some time during 1997, David Hobley (soon joined by Marc Paquette) -imported some of the NT-specific portions of GNU Emacs, making XEmacs -with X support compile under Windows NT, and creating the "X" port. +The reason for an Emacs package not to be included in XEmacs is +usually one or more of the following: -@item -Several months later, Jonathan Harris sent out initial patches to use -the Win32 API, thus creating the native port. Since then, various -people have contributed, including Kirill M. Katsnelson (contributed -support for menubars, subprocesses and network, as well as loads of -other code), Andy Piper (ported XEmacs to Cygwin environment, -contributed Windows unexec, Windows-specific glyphs and toolbars code, -and more), Ben Wing (loads of improvements; primary MS Windows developer -since 2000), Jeff Sparkes (contributed scrollbars support) and many -others. -@end itemize +@enumerate +@item +The package has not been ported to XEmacs. This will typically happen +when it uses GNU-Emacs-specific features, which make it fail under +XEmacs. + +Porting a package to XEmacs can range from a trivial amount of change to +a partial or full rewrite. Fortunately, the authors of modern packages +usually choose to support both Emacsen themselves. @item -NT Emacs +The package has been decided not to be appropriate for XEmacs. It may +have an equivalent or better replacement within XEmacs, in which case +the developers may choose not to burden themselves with supporting an +additional package. -@itemize @minus +Each package bundled with XEmacs means more work for the maintainers, +whether they want it or not. If you are ready to take over the +maintenance responsibilities for the package you port, be sure to say +so---we will more likely include it. @item -NT Emacs is a version of GNU Emacs modified to compile and run under MS -Windows 95 and NT using the native Win32 API. As such, it is close in -spirit to the XEmacs "native" port. +The package simply hasn't been noted by the XEmacs development. If +that's the case, the messages like yours are very useful for attracting +our attention. @item -NT Emacs has been written by Geoff Voelker, and more information can be -found at +The package was noted by the developers, but they simply haven't yet +gotten around to including/porting it. Wait for the next release or, +even better, offer your help. It will be gladly accepted and +appreciated. +@end enumerate + +@node Q8.1.2, Q8.1.3, Q8.1.1, Other Packages +@unnumberedsubsec Q8.1.2: Are there any Emacs Lisp Spreadsheets? + +Yes. Check out @dfn{dismal} (which stands for Dis' Mode Ain't Lotus) at @iftex @* @end iftex -@uref{http://www.gnu.org/software/emacs/windows/ntemacs.html}. -@end itemize +@uref{http://acs.ist.psu.edu/dismal/dismal.html}. -@item -Win-Emacs +@node Q8.1.3, Q8.2.1, Q8.1.2, Other Packages +@unnumberedsubsec Q8.1.3: Is there a MatLab mode? -@itemize @minus +Yes, a matlab mode and other items are available at the +@uref{http://www.mathworks.com/matlabcentral/files/104/matlab.el}. -@item -Win-Emacs was a port of Lucid Emacs 19.6 to MS Windows using X -compatibility libraries. Win-Emacs was written by Ben Wing. The MS -Windows code never made it back to Lucid Emacs, and its creator (Pearl -Software) has long since gone out of business. -@end itemize +@unnumberedsec 8.2: Environments Built Around XEmacs -@item -GNU Emacs for DOS +@node Q8.2.1, Q8.2.2, Q8.1.3, Other Packages +@unnumberedsubsec Q8.2.1: What are SPARCworks, EOS, and WorkShop? -@itemize @minus +SPARCworks was a development environment from Sun (circa 1993-1996) +and consisted of compilers (C, C++, FORTRAN 77, Fortran 90, Ada, and +Pascal), a debugger, and other tools such as TeamWare (for +configuration management), MakeTool, etc. -@item -GNU Emacs features support for MS-DOS and DJGPP (D.J. Delorie's DOS -port of GCC). Such an Emacs is heavily underfeatured, because it does -not support long file names, lacks proper subprocesses support, and -is far too big compared with typical DOS editors. -@end itemize +EOS is the integration of XEmacs with the SPARCworks debugger. It +allows one to use an XEmacs frame to view code (complete with +fontification, etc.), set breakpoints, print variables, etc., while +using the SPARCworks debugger. -@item -GNU Emacs compiled with Win32 +EOS stands for "Era on SPARCworks"; Era stood for "Emacs Rewritten +Again" and was the name used by Sun for its modified version of Lucid +Emacs (later XEmacs) in the early-mid 90's. This is documented in +more detail in the history section of the XEmacs About page. + +EOS was replaced around 1996 with a newer graphical development +environment called Sun WorkShop. The current status of this is +unknown. -@itemize @minus +@node Q8.2.2, Q8.2.3, Q8.2.1, Other Packages +@unnumberedsubsec Q8.2.2: How do I start the Sun Workshop support in XEmacs 21? -@item -Starting with version 19.30, it has been possible to compile GNU Emacs -under MS Windows using the DJGPP compiler and X libraries. The result -is very similar to GNU Emacs compiled under MS DOS, only it works -somewhat better because it runs in 32-bit mode, makes use of all the -system memory, supports long file names, etc. -@end itemize +Add the switch ---with-workshop to the configure command when building +XEmacs and put the following in one of your startup files +(e.g. site-start.el or .emacs): -@end itemize +@lisp +(when (featurep 'tooltalk) + (load "tooltalk-macros") + (load "tooltalk-util") + (load "tooltalk-init")) +(when (featurep 'sparcworks) + (load "sunpro-init") + (load "ring") + (load "comint") + (load "annotations") + (sunpro-startup)) +@end lisp +If you are not using the latest Workshop (5.0) you have to apply the +following patch: -@node Q6.3.3, Q6.3.4, Q6.3.2, MS Windows -@unnumberedsubsec Q6.3.3: XEmacs 21.1 on Windows used to spawn an ugly console window on every startup. Has that been fixed? +@format +--- /opt/SUNWspro/lib/eserve.el.ORIG Fri May 14 15:23:26 1999 ++++ /opt/SUNWspro/lib/eserve.el Fri May 14 15:24:54 1999 +@@@@ -42,7 +42,7 @@@@ + (defvar running-xemacs nil "t if we're running XEmacs") + (defvar running-emacs nil "t if we're running GNU Emacs 19") -Yes. +-(if (string-match "^\\(19\\|20\\)\..*\\(XEmacs\\|Lucid\\)" emacs-version) ++(if (string-match "\\(XEmacs\\|Lucid\\)" emacs-version) + (setq running-xemacs t) + (setq running-emacs t)) +@end format -The console was there because @file{temacs} (and in turn, @file{xemacs}) -was a console application, and Windows typically creates a new -console for a console process unless the creating process requests that -one isn't created. This used to be fixed with @file{runemacs}, a small -Windows application that existed merely to start @file{xemacs}, stating -that it didn't want a console. +@node Q8.2.3, Q8.2.4, Q8.2.2, Other Packages +@unnumberedsubsec Q8.2.3: What is/was Energize? -XEmacs 21.4 fixes this cleanly by the virtue of being a true "GUI" -application. The explanation of what that means is included for -educational value. +The "Energize Programming System" was a C and C++ development environment +sold by Lucid, Inc. It was the reason why Lucid Emacs, now XEmacs, was +created in the first place. Unfortunately, Lucid went out of business in +1994. The rights to sell it in Japan were purchased by INS +Engineering (which briefly employed Stig Hackvan aka Jonathan +Stigelman to work on Japanese support for XEmacs, in late 1994 and +early 1995) and Tartan bought the rights to sell it in the rest of the +world. However, INS is not selling Energize at this point and may or +may not have ever done so; Tartan certainly never did. -When building an application to be run in a Win32 environment, you must -state which sub-system it is to run in. Valid subsystems include -"console" and "gui". The subsystem you use affects the run time -libraries linked into your application, the start up function that is -run before control is handed over to your application, the entry point -to your program, and how Windows normally invokes your program. (Console -programs automatically get a console created for them at startup if -their stdin/stdout don't point anywhere useful, which is the case when -run from the GUI. This is a stupid design, of course -- instead, the -console should get created only when the first I/O actually occurs! -GUI programs have an equally stupid design: When called from -@file{CMD.EXE}/@file{COMMAND.COM}, their stdin/stdout will be set to -point nowhere useful, even though the command shell has its own -stdin/stdout. It's as if someone who had learned a bit about stdio but -had no actual knowledge of interprocess communication designed the -scheme; unfortunately, the whole process-communication aspect of the -Win32 API is equally badly designed.) For example, the entry point for a -console app is "main" (which is what you'd expect for a C/C++ program), -but the entry point for a "gui" app is "WinMain". This confuses and -annoys a lot of programmers who've grown up on Unix systems, where the -kernel doesn't really care whether your application is a gui program or -not. +@node Q8.2.4, , Q8.2.3, Other Packages +@unnumberedsubsec Q8.2.4: What is Infodock? -For reasons not altogether clear, and are lost in the mists of time and -tradition, XEmacs on Win32 started out as a console application, and -therefore a console was automatically created for it. (It may have been -made a console application partly because a console is needed in some -circumstances, especially under Win95, to interrupt, terminate, or send -signals to a child process, and because of the bogosity mentioned above -with GUI programs and the standard command shell. Currently, XEmacs -just creates and immediately hides a console when necessary, and -works around the "no useful stdio" problem by creating its own console -window as necessary to display messages in.) +@uref{http://sourceforge.net/projects/infodock/, InfoDock} is an +integrated productivity toolset, mainly aimed at technical people, +hosted at SourceForge. +InfoDock is built atop the XEmacs variant of GNU Emacs and so has all of +the power of Emacs, but with an easier to use and more comprehensive +menu-based user interface. The bottom portion of this text describes +how it differs from XEmacs and GNU Emacs from the Free Software +Foundation. -@node Q6.3.4, Q6.4.1, Q6.3.3, MS Windows -@unnumberedsubsec Q6.3.4: What is the porting team doing at the moment? +InfoDock is aimed at people who want a free, turn-key productivity +environment. Although InfoDock is customizable, it is not intended for +people who like basic versions of Emacs which need to be customized +extensively for local use; standard Emacs distributions are better for +such uses. InfoDock is for those people who want a complete, +pre-customized environment in one package, which they need not touch +more than once or twice a year to update to new revisions. -(as of June 2001) +InfoDock is pre-built for SPARC SunOS/Solaris systems, PA-RISC HP-UX, +and Intel Linux systems. It is intended for use on a color display, +although most features will work on monochrome monitors. Simply unpack +InfoDock according to the instructions in the ID-INSTALL file and you +are ready to run. -The porting team is continuing work on the MS Windows-specific code. -Major projects are the development of Mule (internationalization) -support for Windows and the improvement of the widget support (better -support for dialog boxes, buttons, edit fields, and similar UI -elements). +The InfoDock Manual is concise, yet sufficient as a user guide for users +who have never used an Emacs-type editor before. For users who are +already familiar with Emacs, it supplements the information in the GNU +Emacs Manual. +InfoDock menus are much more extensive and more mature than standard +Emacs menus. Each menu offers a @samp{Manual} item which displays +documentation associated with the menu's functions. +@noindent +Four types of menubars are provided: +@enumerate +@item +An extensive menubar providing access to global InfoDock commands. +@item +Mode-specific menubars tailored to the current major mode. +@item +A simple menubar for basic editing to help novices get started with InfoDock. +@item +The standard XEmacs menubar. +@end enumerate -@node Q6.4.1, Q6.4.2, Q6.3.4, MS Windows -@unnumberedsec 6.4: Troubleshooting -@unnumberedsubsec Q6.4.1 XEmacs won't start on Windows. +Most modes also include mode-specific popup menus. Additionally, region and +rectangle popup menus are included. -XEmacs relies on a process called "dumping" to generate a working -executable. Under MS-Windows this process effectively fixes the memory -addresses of information in the executable. When XEmacs starts up it tries -to reserve these memory addresses so that the dumping process can be -reversed -- putting the information back at the correct addresses. -Unfortunately some .DLLs (for instance the soundblaster driver) occupy -memory addresses that can conflict with those needed by the dumped XEmacs -executable. In this instance XEmacs will fail to start without any -explanation. Note that this is extremely machine specific. +@samp{Hyperbole}, the everyday information manager, is a core part of +InfoDock. This provides context-sensitive mouse keys, a rolodex-type +contact manager, programmable hypertext buttons, and an autonumbered +outliner with embedded hyperlink anchors. -21.1.10 includes a fix for this that makes more intelligent guesses -about which memory addresses will be free, and this should cure the -problem for most people. 21.4 implements "portable dumping", which -eliminates the problem altogether. We recommend you use the 21.4 -binaries, but you can use the 21.1 binaries if you are very paranoid -about stability. @xref{Q6.0.3}. +The @samp{OO-Browser}, a multi-language object-oriented code browser, is a +standard part of InfoDock. -@node Q6.4.2, Q6.4.3, Q6.4.1, MS Windows -@unnumberedsubsec Q6.4.2 Why do I get a blank toolbar on Windows 95? +InfoDock saves a more extensive set of user options than other Emacs +versions. -You need at least version 4.71 of the system file @file{comctl32.dll}. -The updated version is supplied with Internet Explorer 4 and later but if -you are avoiding IE you can also download it from the Microsoft web -site. Go into support and search for @file{comctl32.dll}. The download -is a self-installing executable. +InfoDock inserts a useful file header in many file types, showing the +author, summary, and last modification time of each file. A summary +program can then be used to summarize all of the files in a directory, +for easy MANIFEST file creation. -@node Q6.4.3, , Q6.4.2, MS Windows -@unnumberedsubsec Q6.4.3 XEmacs complains "No such file or directory, diff" +Your working set of buffers is automatically saved and restored (if you +answer yes to a prompt) between InfoDock sessions. -or "ispell" or other commands that seem related to whatever you just -tried to do (M-x ediff or M-$, for example). +Refined color choices for code highlighting are provided for both dark and +light background display frames. -There are a large number of common (in the sense that "everyone has -these, they really do") Unix utilities that are not provided with -XEmacs. The GNU Project's implementations are available for Windows in -the the Cygwin distribution (@uref{http://www.cygwin.com/}), which also -provides a complete Unix emulation environment (and thus makes ports of -Unix utilities nearly trivial). Another implementation is that from -MinGW (@uref{http://www.mingw.org/msys.shtml}). If you know of others, -please let us know! +The @kbd{C-z} key prefix performs frame-based commands which parallel the +@kbd{C-x} key prefix for window-based commands. +The Smart Menu system is included for producing command menus on dumb +terminals. +Lisp libraries are better categorized according to function. -@node Current Events, Legacy Versions, MS Windows, Top -@unnumbered 7 What the Future Holds +Extensions and improvements to many areas of Emacs are included, such as: +paragraph filling, mail reading with Rmail, shell handling, outlining, code +highlighting and browsing, and man page browsing. -This is part 7 of the XEmacs Frequently Asked Questions list. This +InfoDock questions, answers and discussion should go to the mail list +@iftex +@* +@end iftex +@email{infodock@@infodock.com}. Use +@email{infodock-request@@infodock.com} to be added or removed from the +list. Always include your InfoDock version number when sending help +requests. + +@node Current Events, Legacy Versions, Other Packages, Top +@unnumbered 9 What the Future Holds + +This is part 9 of the XEmacs Frequently Asked Questions list. This section will change frequently, and (in theory) should contain any interesting items that have transpired recently. (But in practice it's not getting updated like this.) @@ -7069,24 +8177,25 @@ Information on older versions of XEmacs can be find in @file{ONEWS} in the same directory, or @file{OONEWS} for really old versions. - @menu -* Q7.0.1:: What new features will be in XEmacs soon? -* Q7.0.2:: What's new in XEmacs 21.4? -* Q7.0.3:: What's new in XEmacs 21.1? -* Q7.0.4:: What's new in XEmacs 20.4? -* Q7.0.5:: What's new in XEmacs 20.3? -* Q7.0.6:: What's new in XEmacs 20.2? +9.0: Changes +* Q9.0.1:: What new features will be in XEmacs soon? +* Q9.0.2:: What's new in XEmacs 21.4? +* Q9.0.3:: What's new in XEmacs 21.1? +* Q9.0.4:: What's new in XEmacs 20.4? +* Q9.0.5:: What's new in XEmacs 20.3? +* Q9.0.6:: What's new in XEmacs 20.2? @end menu -@node Q7.0.1, Q7.0.2, Current Events, Current Events -@unnumberedsec 7.0: Changes -@unnumberedsubsec Q7.0.1: What new features will be in XEmacs soon? +@unnumberedsec 9.0: Changes -Not yet written. +@node Q9.0.1, Q9.0.2, Current Events, Current Events +@unnumberedsubsec Q9.0.1: What new features will be in XEmacs soon? + +#### Write me. -@node Q7.0.2, Q7.0.3, Q7.0.1, Current Events -@unnumberedsubsec Q7.0.2: What's new in XEmacs 21.4? +@node Q9.0.2, Q9.0.3, Q9.0.1, Current Events +@unnumberedsubsec Q9.0.2: What's new in XEmacs 21.4? 21.4 was the "stable" version of the 21.2 series, which was considered "experimental" throughout its life; thus there were no "official" @@ -7131,7 +8240,11 @@ Default menubar improvements. (Default menubar has many new commands and better organization. The font-menu is now available under MS Windows.) @item -Dialog box improvements, including a real file dialog box. (XEmacs now has a proper file dialog box under MS Windows (and GTK)! The old clunky file dialog box is improved. Keyboard traversal now works correctly in MS Windows dialog boxes. There is a Search dialog box available from Edit->Find...) +Dialog box improvements, including a real file dialog box. (XEmacs now +has a proper file dialog box under MS Windows (and GTK)! The old +clunky file dialog box is improved. Keyboard traversal now works +correctly in MS Windows dialog boxes. There is a Search dialog box +available from @samp{Edit->Find...}) @item New buffer tabs. @item @@ -7203,11 +8316,11 @@ @c @itemize @bullet @c @end itemize -@node Q7.0.3, Q7.0.4, Q7.0.2, Current Events -@unnumberedsubsec Q7.0.3: What's new in XEmacs 21.1? +@node Q9.0.3, Q9.0.4, Q9.0.2, Current Events +@unnumberedsubsec Q9.0.3: What's new in XEmacs 21.1? 21.1 was the "stable" version of "experimental" 21.0 series. -@xref{Q7.0.2}. +@xref{Q9.0.2, What's new in XEmacs 21.4?}. The following lists summarizes the essential changes made in this version. For a fuller list, see the @file{NEWS} in the @file{etc} @@ -7219,9 +8332,10 @@ @itemize @bullet @item -XEmacs is now supported under Microsoft Windows 95/98 and Windows NT -operating systems. To discuss Windows-specific issues, subscribe to the -mailing list at @email{xemacs-nt-request@@xemacs.org}. +XEmacs is now supported under Microsoft Windows 95/98 and Windows +NT/2000/XP operating systems. To discuss Windows-specific issues, +subscribe to the mailing list at +@email{xemacs-winnt-request@@xemacs.org}. @item XEmacs has been unbundled into constituent installable packages. @@ -7341,14 +8455,14 @@ @end itemize -@node Q7.0.4, Q7.0.5, Q7.0.3, Current Events -@unnumberedsubsec Q7.0.4: What's new in XEmacs 20.4? +@node Q9.0.4, Q9.0.5, Q9.0.3, Current Events +@unnumberedsubsec Q9.0.4: What's new in XEmacs 20.4? XEmacs 20.4 is a bugfix release with no user-visible changes. @c Filled in from NEWS file of 20.5-b33 -@node Q7.0.5, Q7.0.6, Q7.0.4, Current Events -@unnumberedsubsec Q7.0.5: What's new in XEmacs 20.3? +@node Q9.0.5, Q9.0.6, Q9.0.4, Current Events +@unnumberedsubsec Q9.0.5: What's new in XEmacs 20.3? XEmacs 20.3 was released in November 1997. It contains many bugfixes, and a number of new features, including Autoconf 2 based configuration, @@ -7367,8 +8481,8 @@ XEmacs 20.3 is the first non-beta v20 release, and will be the basis for all further development. -@node Q7.0.6, , Q7.0.5, Current Events -@unnumberedsubsec Q7.0.6: What's new in XEmacs 20.2? +@node Q9.0.6, , Q9.0.5, Current Events +@unnumberedsubsec Q9.0.6: What's new in XEmacs 20.2? The biggest changes in 20.2 include integration of EFS (the next generation of ange-ftp) and AUC Tex (the Emacs subsystem that includes a @@ -7383,26 +8497,26 @@ For older news, see the file @file{ONEWS} in the @file{etc} directory of the XEmacs distribution. +@node Legacy Versions, , Current Events, Top +@unnumbered 10 New information about old XEmacsen - -@node Legacy Versions, , Current Events, Top -@unnumbered 8 New information about old XEmacsen - -This is part 8 of the XEmacs Frequently Asked Questions list. It will +This is part 10 of the XEmacs Frequently Asked Questions list. It will occasionally be updated to reflect new information about versions which are no longer being revised by the XEmacs Project. The primary purpose is advice on compatibility of older XEmacsen with new packages and updated versions of packages, but bug fixes (which will not be applied to released XEmacsen, but users can apply themselves) are also accepted. - @menu -* Q8.0.1:: Gnus 5.10 won't display smileys in XEmacs 21.1. +10.0: XEmacs 21.1 +* Q10.0.1:: Gnus 5.10 won't display smileys in XEmacs 21.1. +* Q10.0.2:: XEmacs won't start on Windows in XEmacs 21.1. @end menu -@node Q8.0.1, , , Legacy Versions -@unnumberedsec 8.0 XEmacs 21.1 -@unnumberedsubsec Q8.0.1: Gnus 5.10 won't display smileys in XEmacs 21.1. +@unnumberedsec 10.0: XEmacs 21.1 + +@node Q10.0.1, Q10.0.2, Legacy Versions, Legacy Versions +@unnumberedsubsec Q10.0.1: Gnus 5.10 won't display smileys in XEmacs 21.1. @email{eeide@@cs.utah.edu, Eric Eide} wrote: @@ -7439,5 +8553,24 @@ branch, praise be. @end quotation +@node Q10.0.2, , Q10.0.1, Legacy Versions +@unnumberedsubsec Q10.0.2: XEmacs won't start on Windows in XEmacs 21.1. + +XEmacs relies on a process called "dumping" to generate a working +executable. Under MS-Windows this process effectively fixes the memory +addresses of information in the executable. When XEmacs starts up it tries +to reserve these memory addresses so that the dumping process can be +reversed -- putting the information back at the correct addresses. +Unfortunately some .DLLs (for instance the soundblaster driver) occupy +memory addresses that can conflict with those needed by the dumped XEmacs +executable. In this instance XEmacs will fail to start without any +explanation. Note that this is extremely machine specific. + +21.1.10 includes a fix for this that makes more intelligent guesses +about which memory addresses will be free, and this should cure the +problem for most people. 21.4 implements "portable dumping", which +eliminates the problem altogether. We recommend you use the 21.4 +binaries, but you can use the 21.1 binaries if you are very paranoid +about stability. @xref{Q1.1.2, Are binaries available?}. @bye diff --text -u 'xemacs-21.5.18/man/xemacs/help.texi' 'xemacs-21.5.19/man/xemacs/help.texi' Index: ./man/xemacs/help.texi --- ./man/xemacs/help.texi Fri Aug 13 18:47:57 2004 +++ ./man/xemacs/help.texi Tue Feb 1 05:08:50 2005 @@ -442,13 +442,12 @@ information. @kbd{C-h C-w} (@code{describe-no-warranty}) displays the full details on the complete absence of warranty for XEmacs. @kbd{C-h n} (@code{view-emacs-news}) displays the file @file{xemacs/etc/NEWS}, -which contains documentation on XEmacs changes arranged chronologically. -@kbd{C-h F} (@code{xemacs-local-faq}) displays local version of the -XEmacs frequently-answered-questions-list. @kbd{C-h t} -(@code{help-with-tutorial}) displays the learn-by-doing XEmacs -tutorial. @kbd{C-h C-c} (@code{describe-copying}) displays the file -@file{xemacs/etc/COPYING}, which tells you the conditions you must obey -in distributing copies of XEmacs. @kbd{C-h C-d} -(@code{describe-distribution}) displays another file named -@file{xemacs/etc/DISTRIB}, which tells you how you can order a copy of -the latest version of XEmacs. +which contains documentation on XEmacs changes arranged +chronologically. @kbd{C-h F} (@code{xemacs-local-faq}) displays the +local version of the XEmacs FAQ (Frequently Answered Questions list). +@kbd{C-h t} (@code{help-with-tutorial}) displays the learn-by-doing +XEmacs tutorial. @kbd{C-h C-c} (@code{describe-copying}) displays the +file @file{xemacs/etc/COPYING}, which tells you the conditions you +must obey in distributing copies of XEmacs. @kbd{C-h C-d} +(@code{describe-distribution} displays the section of the FAQ that +tells you how you can get the latest version of XEmacs. diff --text -u 'xemacs-21.5.18/man/xemacs/major.texi' 'xemacs-21.5.19/man/xemacs/major.texi' Index: ./man/xemacs/major.texi --- ./man/xemacs/major.texi Fri Oct 31 23:53:41 1997 +++ ./man/xemacs/major.texi Fri Jan 28 09:12:39 2005 @@ -26,14 +26,15 @@ Many major modes redefine the syntactical properties of characters appearing in the buffer. @xref{Syntax}. - The major modes fall into three major groups. Lisp mode (which has -several variants), C mode, and Muddle mode are for specific programming -languages. Text mode, Nroff mode, @TeX{} mode, and Outline mode are for -editing English text. The remaining major modes are not intended for use -on users' files; they are used in buffers created by Emacs for specific -purposes and include Dired mode for buffers made by Dired (@pxref{Dired}), -Mail mode for buffers made by @kbd{C-x m} (@pxref{Sending Mail}), and Shell -mode for buffers used for communicating with an inferior shell process + The major modes fall into three major groups. Programming modes +(@pxref{Programs}) are for specific programming languages. Text modes +(like Nroff mode, @TeX{} mode, Outline mode, XML mode, etc.@:) are for +editing human readable text. The remaining major modes are not intended +for direct use in editing user files; they are used in buffers created +by Emacs for specific purposes. Examples of such modes include Dired +mode which is used for buffers made by Dired (@pxref{Dired}), Mail mode +for buffers made by @kbd{C-x m} (@pxref{Sending Mail}), and Shell mode +for buffers used for communicating with an inferior shell process (@pxref{Interactive Shell}). Most programming language major modes specify that only blank lines @@ -44,9 +45,10 @@ @menu * Choosing Modes:: How major modes are specified or chosen. +* Mode Hooks:: Customizing a major mode @end menu -@node Choosing Modes,,Major Modes,Major Modes +@node Choosing Modes, Mode Hooks, Major Modes, Major Modes @section Choosing Major Modes You can select a major mode explicitly for the current buffer, but @@ -111,3 +113,49 @@ value is the symbol @code{fundamental-mode}, which specifies Fundamental mode. If @code{default-major-mode} is @code{nil}, the major mode is taken from the previously selected buffer. + +@node Mode Hooks, , Choosing Modes, Major Modes +@section Mode Hook Variables + +@cindex Hook variables +@cindex mode hook +@findex add-hook +@findex remove-hook +@vindex lisp-mode-hook +@vindex emacs-lisp-mode-hook +@vindex lisp-interaction-mode-hook +@vindex scheme-mode-hook + + The last step taken by a major mode, by convention, is to invoke a +list of user supplied functions that are stored in a ``hook'' variable. +This allows a user to further customize the major mode, and is +particularly convenient for setting up buffer local variables +(@pxref{Locals}). + + The name of the hook variable is created by appending the string +@code{-hook} to the name of the major mode. For example, the hook +variable used by @code{text-mode} would be named @code{text-mode-hook}. +By convention the mode hook function receives no arguments. If a hook +variable does not exist, or it has the value @code{nil}, the major mode +simply ignores it. + + The recommended way to add functions to a hook variable is with the +@code{add-hook} function. For example, to automatically turn on the +Auto Fill mode when Text mode is invoked the following code can be used in +the initialization file (@pxref{Init File}) + +@example +(add-hook 'text-mode-hook 'turn-on-auto-fill) +@end example + +The @code{add-hook} function will check that the function is not already +listed in the hook variable before adding it. It will also create a hook +variable with the value @code{nil} if one does not exist before adding +the function. @code{add-hook} adds functions to the front of the hook +variable list. This means that the last hook added is run first by the +major mode. It is considered very poor style to write hook functions +that depend on the order that hooks are executed. + +Hooks can be removed from hook variables with @code{remove-hook}. + + diff --text -u 'xemacs-21.5.18/man/xemacs/new.texi' 'xemacs-21.5.19/man/xemacs/new.texi' Index: ./man/xemacs/new.texi --- ./man/xemacs/new.texi Fri Apr 13 03:22:29 2001 +++ ./man/xemacs/new.texi Tue Feb 1 05:08:50 2005 @@ -235,40 +235,75 @@ @cindex version number @example -(cond ((string-match "Lucid" emacs-version) +(cond ((string-match "XEmacs" emacs-version) ;; - ;; Code for any version of Lucid Emacs or XEmacs goes here + ;; Code for any version of XEmacs goes here. ;; )) -(cond ((and (string-match "XEmacs" emacs-version) - (or (> emacs-major-version 19) - (>= emacs-minor-version 12))) +(cond ((not (string-match "XEmacs" emacs-version))) ;; - ;; Code which requires XEmacs version 19.12 or newer goes here + ;; Code for any version of GNU Emacs goes here. ;; )) -(cond ((>= emacs-major-version 19) +(cond ((and (string-match "XEmacs" emacs-version) + (emacs-version>= 21 4)) ;; - ;; Code for any vintage-19 emacs goes here + ;; Code which requires XEmacs version 21.4 or newer goes here ;; )) -(cond ((and (not (string-match "Lucid" emacs-version)) - (= emacs-major-version 19)) +(cond ((and (string-match "XEmacs" emacs-version) + (emacs-version>= 21 4 12) + (not (emacs-version>= 21 4 15))) ;; - ;; Code specific to FSF Emacs 19 (not XEmacs) goes here + ;; Code which requires exactly XEmacs version 21.4.12 through + ;; 21.4.14, inclusive, goes here. (e.g. A bug was introduced in + ;; 21.4.12 and fixed in 21.4.15 but many of the versions of + ;; XEmacs around in the computer laboratory run those versions, + ;; so I need to introduce a workaround. In such a case, you + ;; should ideally try to conditionalize on something else, + ;; e.g. a feature symbol or a simple test that can be run to + ;; smoke out the bug.) ;; )) -(cond ((< emacs-major-version 19) +(cond ((and (not (string-match "XEmacs" emacs-version) + (emacs-version>= 20 2)) ;; - ;; Code specific to emacs 18 goes here + ;; Code which requires GNU Emacs version 20.2 or newer, but not XEmacs, + ;; goes here ;; )) + +@end example + +@emph{NOTE}: @strong{DO} use @code{(emacs-version>= ...)}. @strong{DO NOT} +try to do this yourself using @code{emacs-major-version} and +@code{emacs-minor-version}. You will, with high probability, get it +wrong. Typical attempts to replace @code{(emacs-version>= 21 4)} use + +@example +(and (>= emacs-major-version 21) + (>= emacs-minor-version 4)) @end example +which correctly excludes 21.3 and all previous versions, +but also excludes 22.0 through 22.3, 23.0 through 23.3, etc. + +A "more clever" version, as advocated in earlier versions +of this very manual, was like this: + +@example +(or (> emacs-major-version 21) + (>= emacs-minor-version 4)) +@end example + +which correctly includes 21.4 and all following versions, +but also includes 20.4 through 20.99999, 19.4 through +19.99999, etc. + Alternatively, use @file{.xemacs/init.el} for an init file. @xref{Init File}. Of particular interest for use in files are: diff --text -u 'xemacs-21.5.18/man/xemacs/packages.texi' 'xemacs-21.5.19/man/xemacs/packages.texi' Index: ./man/xemacs/packages.texi --- ./man/xemacs/packages.texi Thu Aug 28 03:07:10 2003 +++ ./man/xemacs/packages.texi Mon Dec 6 12:51:46 2004 @@ -15,6 +15,9 @@ This gives an installer the ability to tailor an XEmacs installation for local needs with safe removal of unnecessary code. +@emph{NOTE}: For detailed information about how the package +hierarchies work, @xref{Package Overview,,,lispref, XEmacs Lisp Reference Manual}. + @menu * Package Terminology:: Understanding different kinds of packages. * Installing Packages:: How to install packages. @@ -301,7 +304,7 @@ a fresh install it is sufficient to untar the file at the top of the package hierarchy. -Note: If you are upgrading packages already installed, it's best to +@emph{NOTE}: If you are upgrading packages already installed, it's best to remove the old package first @ref{Removing Packages}. For example if we are installing the @file{xemacs-base} @@ -330,6 +333,9 @@ tar zxvf /path/to/mule-base-1.37-pkg.tar.gz RET @end example +@emph{NOTE}: For more detailed information about how the package +hierarchies work, @xref{Package Overview,,,lispref, XEmacs Lisp Reference Manual}. + @node Sumo, Which Packages, Manually, Installing Packages @comment node-name, next, previous, up @cindex sumo package install @@ -431,7 +437,7 @@ distributing to others. For a list and description of the different @file{Makefile} targets, -@xref{Makefile Targets,,,lispref}. +@xref{Makefile Targets,,,lispref, XEmacs Lisp Reference Manual}. @node Local.rules File, Available Packages, Building Packages, Packages @comment node-name, next, previous, up @@ -443,7 +449,7 @@ @file{Local.rules} and edit it to suit your needs. For a complete discussion of the @file{Local.rules} file, -@xref{Local.rules File,,,lispref}. +@xref{Local.rules File,,,lispref, XEmacs Lisp Reference Manual}. @node Available Packages, , Local.rules File, Packages @comment node-name, next, previous, up diff --text -u 'xemacs-21.5.18/man/xemacs/programs.texi' 'xemacs-21.5.19/man/xemacs/programs.texi' Index: ./man/xemacs/programs.texi --- ./man/xemacs/programs.texi Thu Dec 20 16:58:23 2001 +++ ./man/xemacs/programs.texi Fri Jan 28 09:12:39 2005 @@ -1,14 +1,17 @@ @node Programs, Running, Text, Top @chapter Editing Programs +@cindex Programming Languages @cindex Lisp -@cindex C - Emacs has many commands designed to understand the syntax of programming -languages such as Lisp and C. These commands can: + XEmacs provides specialized support for editing source files for many +different programming languages. For example it is possible to @itemize @bullet @item +Follow the usual indentation conventions of the language +(@pxref{Grinding}). +@item Move over or kill balanced expressions or @dfn{sexps} (@pxref{Lists}). @item Move over or mark top-level balanced expressions (@dfn{defuns}, in Lisp; @@ -18,8 +21,7 @@ @item Insert, kill, or align comments (@pxref{Comments}). @item -Follow the usual indentation conventions of the language -(@pxref{Grinding}). +Find functions and symbols in program by name (@pxref{Tags}). @end itemize The commands available for words, sentences, and paragraphs are useful in @@ -52,6 +54,7 @@ * Change Log:: Maintaining a change history for your program. * Tags:: Go direct to any function in your program in one command. Tags remembers which file it is in. +* CC Mode:: Modes for C, C++, Java and similar languages * Fortran:: Fortran mode and its special features. * Asm Mode:: Asm mode and its special features. @end menu @@ -60,24 +63,49 @@ @section Major Modes for Programming Languages @cindex Lisp mode -@cindex C mode -@cindex Scheme mode - Emacs has several major modes for the programming languages Lisp, Scheme (a -variant of Lisp), C, Fortran, and Muddle. Ideally, a major mode should be -implemented for each programming language you might want to edit with -Emacs; but often the mode for one language can serve for other -syntactically similar languages. The language modes that exist are those -that someone decided to take the trouble to write. - - There are several variants of Lisp mode, which differ in the way they -interface to Lisp execution. @xref{Lisp Modes}. - - Each of the programming language modes defines the @key{TAB} key to run -an indentation function that knows the indentation conventions of that -language and updates the current line's indentation accordingly. For -example, in C mode @key{TAB} is bound to @code{c-indent-line}. @key{LFD} -is normally defined to do @key{RET} followed by @key{TAB}; thus it, too, -indents in a mode-specific fashion. + Emacs has several major modes (@pxref{Major Modes}) to support +programming languages. These major modes will typically understand +language syntax, provide automatic indentation features, syntax based +highlighting of text, and will often provide interfaces to the +programming environment to assist in compiling, executing and debugging +programs. + + A language mode exist when someone decides to take the trouble to +write it. At this time many widely used programming languages are +supported by XEmacs. Examples include Ada, Awk, C, C++, CORBA (IDL), +Fortran, Java, Lisp, Modula 2, Objective-C, Perl, Pike, Prolog, Python, +Ruby, Scheme, Simula, SQL, Tcl, Unix Shell scripts, and VHDL. Some of +these language have seperate manuals, and some times more than one mode +may be available for a language. For example, there are several +variants of Lisp mode, which differ in the way they interface to Lisp +execution. @xref{Lisp Modes}. + + Major modes for programming language support are distributed in +optional XEmacs packages (@pxref{Packages}) that must be installed +before use. A notable exception to this rule is that a Lisp Mode is +integral to XEmacs. The Programming Mode Package (@file{prog-modes}) +contains many such modes. Some languages are supported by packages of +their own; prominent examples of such packages include @file{cc-mode} +for C, C++, Java, Objective C etc.@:, @file{python-modes} for Python, +and @file{scheme} for Scheme. + + For a language named @var{lang} the major mode for the language will +typically be named @code{@var{lang}-mode}. For example, the mode for C +is called @code{c-mode}, that for Bourne shell scripts is called +@code{sh-mode} and so on. These modes will invoke the functions listed +in the corresponding hook variables as a last step. @xref{Mode Hooks}. + + A mode can be invoked by typing @kbd{M-x @var{lang}-mode +@key{RET}}. However this step is not normally required. If the package +for a language mode is installed XEmacs usually knows when to +automatically invoke the mode. This is normally done based on examining +the file name to determine the language. @ref{Choosing Modes}. + + Each of the programming language modes defines the @key{TAB} key to +run an indentation function that knows the indentation conventions of +that language and updates the current line's indentation accordingly. +@key{LFD} is normally defined to do @key{RET} followed by @key{TAB}; +thus it, too, indents in a mode-specific fashion. @kindex DEL @findex backward-delete-char-untabify @@ -94,22 +122,6 @@ if enabled in a programming language major mode, indents the new lines which it creates. -@cindex mode hook -@vindex c-mode-hook -@vindex lisp-mode-hook -@vindex emacs-lisp-mode-hook -@vindex lisp-interaction-mode-hook -@vindex scheme-mode-hook -@vindex muddle-mode-hook - Turning on a major mode calls a user-supplied function called the -@dfn{mode hook}, which is the value of a Lisp variable. For example, -turning on C mode calls the value of the variable @code{c-mode-hook} if -that value exists and is non-@code{nil}. Mode hook variables for other -programming language modes include @code{lisp-mode-hook}, -@code{emacs-lisp-mode-hook}, @code{lisp-interaction-mode-hook}, -@code{scheme-mode-hook}, and @code{muddle-mode-hook}. The mode hook -function receives no arguments.@refill - @node Lists, Defuns, Program Modes, Programs @section Lists and Sexps @@ -198,13 +210,6 @@ specified number of times; with a negative argument, it moves in the opposite direction. -In languages such as C where the comment-terminator can be recognized, -the sexp commands move across comments as if they were whitespace. In -Lisp and other languages where comments run until the end of a line, it -is very difficult to ignore comments when parsing backwards; therefore, -in such languages the sexp commands treat the text of comments as if it -were code. - @kindex C-M-k @findex kill-sexp Killing an sexp at a time can be done with @kbd{C-M-k} (@code{kill-sexp}). @@ -338,7 +343,6 @@ * Basic Indent:: * Multi-line Indent:: Commands to reindent many lines at once. * Lisp Indent:: Specifying how each Lisp function should be indented. -* C Indent:: Choosing an indentation style for C code. @end menu @node Basic Indent, Multi-line Indent, Grinding, Grinding @@ -434,7 +438,7 @@ mark. The command @kbd{C-M-\} (@code{indent-region}) applies @key{TAB} to every line whose first character is between point and mark. -@node Lisp Indent, C Indent, Multi-line Indent, Grinding +@node Lisp Indent, , Multi-line Indent, Grinding @subsection Customizing Lisp Indentation @cindex customization @@ -508,184 +512,6 @@ until the end of the list. @end table -@node C Indent, , Lisp Indent, Grinding -@subsection Customizing C Indentation - - Two variables control which commands perform C indentation and when. - -@vindex c-auto-newline - If @code{c-auto-newline} is non-@code{nil}, newlines are inserted both -before and after braces that you insert and after colons and semicolons. -Correct C indentation is done on all the lines that are made this way. - -@vindex c-tab-always-indent - If @code{c-tab-always-indent} is non-@code{nil}, the @key{TAB} command -in C mode does indentation only if point is at the left margin or within -the line's indentation. If there is non-whitespace to the left of point, -@key{TAB} just inserts a tab character in the buffer. Normally, -this variable is @code{nil}, and @key{TAB} always reindents the current line. - - C does not have anything analogous to particular function names for which -special forms of indentation are desirable. However, it has a different -need for customization facilities: many different styles of C indentation -are in common use. - - There are six variables you can set to control the style that Emacs C -mode will use. - -@table @code -@item c-indent-level -Indentation of C statements within surrounding block. The surrounding -block's indentation is the indentation of the line on which the -open-brace appears. -@item c-continued-statement-offset -Extra indentation given to a substatement, such as the then-clause of -an @code{if} or body of a @code{while}. -@item c-brace-offset -Extra indentation for lines that start with an open brace. -@item c-brace-imaginary-offset -An open brace following other text is treated as if it were this far -to the right of the start of its line. -@item c-argdecl-indent -Indentation level of declarations of C function arguments. -@item c-label-offset -Extra indentation for a line that is a label, case, or default. -@end table - -@vindex c-indent-level - The variable @code{c-indent-level} controls the indentation for C -statements with respect to the surrounding block. In the example: - -@example - @{ - foo (); -@end example - -@noindent -the difference in indentation between the lines is @code{c-indent-level}. -Its standard value is 2. - -If the open-brace beginning the compound statement is not at the beginning -of its line, the @code{c-indent-level} is added to the indentation of the -line, not the column of the open-brace. For example, - -@example -if (losing) @{ - do_this (); -@end example - -@noindent -One popular indentation style is that which results from setting -@code{c-indent-level} to 8 and putting open-braces at the end of a line -in this way. Another popular style prefers to put the open-brace on a -separate line. - -@vindex c-brace-imaginary-offset - In fact, the value of the variable @code{c-brace-imaginary-offset} is -also added to the indentation of such a statement. Normally this variable -is zero. Think of this variable as the imaginary position of the open -brace, relative to the first non-blank character on the line. By setting -the variable to 4 and @code{c-indent-level} to 0, you can get this style: - -@example -if (x == y) @{ - do_it (); - @} -@end example - - When @code{c-indent-level} is zero, the statements inside most braces -line up exactly under the open brace. An exception are braces in column -zero, like those surrounding a function's body. The statements inside -those braces are not placed at column zero. Instead, -@code{c-brace-offset} and @code{c-continued-statement-offset} (see -below) are added to produce a typical offset between brace levels, and -the statements are indented that far. - -@vindex c-continued-statement-offset - @code{c-continued-statement-offset} controls the extra indentation for -a line that starts within a statement (but not within parentheses or -brackets). These lines are usually statements inside other statements, -like the then-clauses of @code{if} statements and the bodies of -@code{while} statements. The @code{c-continued-statement-offset} -parameter determines the difference in indentation between the two lines in: - -@example -if (x == y) - do_it (); -@end example - -@noindent -The default value for @code{c-continued-statement-offset} is 2. Some -popular indentation styles correspond to a value of zero for -@code{c-continued-statement-offset}. - -@vindex c-brace-offset - @code{c-brace-offset} is the extra indentation given to a line that -starts with an open-brace. Its standard value is zero; -compare: - -@example -if (x == y) - @{ -@end example - -@noindent -with: - -@example -if (x == y) - do_it (); -@end example - -@noindent -If you set @code{c-brace-offset} to 4, the first example becomes: - -@example -if (x == y) - @{ -@end example - -@vindex c-argdecl-indent - @code{c-argdecl-indent} controls the indentation of declarations of the -arguments of a C function. It is absolute: argument declarations receive -exactly @code{c-argdecl-indent} spaces. The standard value is 5 and -results in code like this: - -@example -char * -index (string, char) - char *string; - int char; -@end example - -@vindex c-label-offset - @code{c-label-offset} is the extra indentation given to a line that -contains a label, a case statement, or a @code{default:} statement. Its -standard value is @minus{}2 and results in code like this: - -@example -switch (c) - @{ - case 'x': -@end example - -@noindent -If @code{c-label-offset} were zero, the same code would be indented as: - -@example -switch (c) - @{ - case 'x': -@end example - -@noindent -This example assumes that the other variables above also have their -default values. - -Using the indentation style produced by the default settings of the -variables just discussed and putting open braces on separate lines -produces clear and readable files. For an example, look at any of the C -source files of XEmacs. @node Matching, Comments, Grinding, Programs @section Automatic Display of Matching Parentheses @@ -1003,7 +829,7 @@ not displayed), set it again in final compute_motion. @end smallexample -@node Tags, Fortran, Change Log, Programs +@node Tags, CC Mode, Change Log, Programs @section Tags Tables @cindex tags table @@ -1710,7 +1536,169 @@ then finds all the tags in the selected tags table whose entries match that regexp, and displays the tag names found. -@node Fortran, Asm Mode, Tags, Programs +@node CC Mode, Fortran, Tags, Programs +@section Modes for C, C++, Java and similar languages +@cindex C Mode +@cindex C++ Mode +@cindex Java Mode +@cindex AWK Mode +@cindex Objective C Mode +@cindex CORBA IDL Mode +@findex c-mode +@findex c++-mode +@findex java-mode +@findex idl-mode +@findex awk-mode +@findex pike-mode +@findex objc-mode +@vindex c-mode-hook +@vindex c++-mode-hook +@vindex java-mode-hook +@vindex idl-mode-hook +@vindex awk-mode-hook +@vindex pike-mode-hook +@vindex objc-mode-hook +@vindex c-mode-common-hook +@vindex c-initialization-hook + + The recommended means for supporting the ``C--like'' programming +languages in XEmacs is the @file{cc-mode} package. CC Mode is not +included in the basic XEmacs distribution but is available as an +optional package. If loading a file whose names ends in the @file{.cc} +extension does not automatically invoke a C++ Mode then the +@file{cc-mode} package is probably not yet installed. @xref{Packages}. + + CC Mode provides modes for editing source files in Awk +(@code{awk-mode}), C (@code{c-mode}), C++ (@code{c++-mode}), CORBA IDL +(@code{idl-mode}), Java (@code{java-mode}), Objective C +(@code{objc-mode}), and Pike (@code{pike-mode}). All these languages are +supported with an sophisticated ``indentation engine'' that is feature +rich, customizable and quite efficient. + + Each language major mode runs hooks in the conventionally named hook +variables (@pxref{Mode Hooks}). In addition to this conventional +behavior all the CC Mode major modes will also run hooks in +@code{c-mode-common-hook} @emph{before} invoking the major mode specific +hook. + + CC Mode runs any hooks in @code{c-initialization-hook} exactly once +when it is first loaded. + + CC Mode is a very comprehensive and flexible system and full +description of its capabilities is beyond the scope of this manual. It +is strongly recommended that the reader consult the CC Mode +documentation for details once the package has been +installed. @xref{Top,CC Mode,,cc-mode, The CC Mode Manual}. + +@menu +* Older Modes:: Older Modes for C and AWK +* Customizing CC Mode:: An Introduction to Customizing CC Mode. +@end menu + + +@node Older Modes, Customizing CC Mode, CC Mode, CC Mode +@subsection Older Modes for C and AWK +@cindex Old C Mode +@cindex Old AWK Mode +@cindex C Mode without CC Mode +@cindex AWK Mode without CC Mode +@cindex old-c-mode + + XEmacs provides older versions of a C Mode and an AWK Mode in the +@file{prog-modes} package. These older modes do not share the +indentation engine in CC Mode have have their own specific means of +customizing indentation. To use these modes the @file{prog-modes} +package must be installed. + + This older C mode is known simply as the ``Old C Mode''. It supports +only the C language and it lacks many of the features of CC Mode. +However the old C mode offers modest space requirements and very fast +operation. Old C Mode might be useful in space constrained +environments, on slow machines, or for editing very large files. This +old C mode is available in the @file{old-c-mode} +library. @xref{old-c-mode,Old C Mode,old-c-mode,prog-modes,The +Programming Modes Package Manual}. + + The old AWK mode exists for similar reasons. It is available in the +@file{awk-mode} library. @xref{awk-mode,Old AWK +Mode,awk-mode,prog-modes,The Programming Modes Package Manual}. + + Note that the prog-modes package will never automatically invoke these +older modes for a user. However installing the @file{cc-mode} package +@emph{will} make CC Mode's versions available automatically. As a +result a user who wants to use these older modes must explicitly load +the old libraries to use them. + +@node Customizing CC Mode, , Older Modes, CC Mode +@subsection Customizing Indentation in CC Mode + + A very brief introduction is included here on customizing CC Mode. CC +Mode has many features, including useful minor modes, that are +completely documented in its own manual. + + CC Mode implements several different ``styles'' for C code (and the +other languages supported by CC Mode). If you need to change the +indentation style for CC Mode it is recommended that you first see if an +existing style meets your requirements. The style chosen will affect the +placement of language elements like braces, function declarations and +comments. You can choose a style interactively by typing @kbd{C-c .} and +pressing the space bar at the prompt to get a list of supported +styles. @kbd{C-c .} runs the function @code{c-set-style} which applies +to all CC Mode language modes though its name might suggest otherwise. A +few of the the supported styles are listed below. + +@itemize @bullet +@item +``gnu'' --- The recommeded style from the Free Software Foundation for +GNU software. +@item +``k&r'' --- The classic style from Kernighan and Ritchie. +@item +``linux'' --- The style recommended for code in the Linux kernel. +@item +``bsd'' --- The style recommended for software developed in BSD. +@item +``java --- The ``traditional'' Java style. +@end itemize + + The default style in XEmacs is ``gnu'' except for Java mode where it +is the ``java'' style (this is governed by the variable +@code{c-default-style}). + + The styles included in CC Mode all use a buffer local variable called +@code{c-basic-offset} as the basic indentation level (this buffer local +variable is used in all CC Mode language modes though its name might +suggest otherwise). All indentation is, by default, expressed in +multiples of @code{c-basic-offset}. + + Each style defines a default value for @code{c-basic-offset}, for the +``gnu'' style sets it to 2. A very common customization scenario is +where a user wants to use an existing style but with a different basic +offset value. An easy way to do this is to set @code{c-basic-offset} in +the language mode hook after selecting the chosen style. + + For example, a user might want to follow a local coding convention of +using the ``k&r'' style for C code with indentation in two columns +multiples (instead of the five column default provided by the CC Mode +``k&r'' style). This can be achieved with the following code in the +initialization file (@pxref{Init File}) + +@example +(defun my-c-mode-hook () + (c-set-style "k&r") + (setq c-basic-offset 2)) +(add-hook 'c-mode-hook 'my-c-mode-hook) +@end example + + Most customizations for indentation in various CC modes can be +accomplished by choosing a style and then choosing value for +@code{c-basic-offset} that meets the local coding convention. CC Mode +has a very customizable indentation engine and a furthur discussion is +really beyond the scope of this manual. @xref{Indentation +Engine,,,cc-mode,The CC Mode Manual}. + + +@node Fortran, Asm Mode, CC Mode, Programs @section Fortran Mode @cindex Fortran mode diff --text -u 'xemacs-21.5.18/man/xemacs/xemacs.texi' 'xemacs-21.5.19/man/xemacs/xemacs.texi' Index: ./man/xemacs/xemacs.texi --- ./man/xemacs/xemacs.texi Thu Aug 28 03:07:10 2003 +++ ./man/xemacs/xemacs.texi Tue Feb 1 05:08:50 2005 @@ -472,6 +472,7 @@ * Change Log:: Maintaining a change history for your program. * Tags:: Go directly to any function in your program in one command. Tags remembers which file it is in. +* CC Mode:: Modes for C, C++, Java and similar languages * Fortran:: Fortran mode and its special features. * Asm Mode:: Asm mode and its special features. @@ -480,7 +481,6 @@ * Basic Indent:: * Multi-line Indent:: Commands to reindent many lines at once. * Lisp Indent:: Specifying how each Lisp function should be indented. -* C Indent:: Choosing an indentation style for C code. Tags Tables @@ -996,27 +996,12 @@ the GNU General Public License that comes with XEmacs and also appears following this section. -The easiest way to get a copy of XEmacs is from someone else who has it. -You need not ask for permission to do so, or tell any one else; just copy -it. - -If you have access to the Internet, you can get the latest version of -XEmacs from the anonymous FTP server @file{ftp.xemacs.org} in the directory -@file{/pub/xemacs}. It can also be found at numerous other archive -sites around the world; check the file @file{etc/DISTRIB} in an XEmacs -distribution for the latest known list. - +To get XEmacs, go to @uref{http://www.xemacs.org/Download/}. @unnumberedsec Getting Other Versions of Emacs -The Free Software Foundation's version of Emacs (called @dfn{FSF Emacs} -in this manual and often referred to as @dfn{GNU Emacs}) is available -by anonymous FTP from @file{prep.ai.mit.edu}. - -Win-Emacs, an older version of XEmacs that runs on Microsoft Windows -and Windows NT, is available by anonymous FTP from @file{ftp.netcom.com} -in the directory @file{/pub/pe/pearl}, or from @file{ftp.cica.indiana.edu} -as the files @file{wemdemo*.zip} in the directory @file{/pub/pc/win3/demo}. +The Free Software Foundation's version of Emacs (@dfn{GNU Emacs}) is +available at @uref{http://www.gnu.org/software/emacs/emacs.html}. @node Intro, Glossary, Distrib, Top @unnumbered Introduction @@ -1025,9 +1010,8 @@ self-documenting, customizable, extensible real-time display editor Emacs. XEmacs provides many powerful display and user-interface capabilities not found in other Emacsen and is mostly upwardly -compatible with GNU Emacs from the Free Software Foundation -(referred to as @dfn{FSF Emacs} in this manual). XEmacs also -comes standard with a great number of useful packages. +compatible with GNU Emacs from the Free Software Foundation. XEmacs +also comes standard with a great number of useful packages. We say that XEmacs is a @dfn{display} editor because normally the text being edited is visible on the screen and is updated automatically as you diff --text -u 'xemacs-21.5.18/modules/ChangeLog' 'xemacs-21.5.19/modules/ChangeLog' Index: ./modules/ChangeLog --- ./modules/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./modules/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,27 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + +2004-11-13 Ben Wing <ben@xemacs.org> + + * ldap/eldap.c (Fldap_modify): + Need braces around EXTERNAL_LIST_LOOP_2. + +2004-01-28 Stephen J. Turnbull <stephen@xemacs.org> + + * common/Makefile.common (CFLAGS): Use XE_CFLAGS. + +2004-10-27 Ben Wing <ben@xemacs.org> + + * ldap/eldap.c: + * ldap/eldap.c (Fldap_open): + * ldap/eldap.c (Fldap_search_basic): + * ldap/eldap.c (Fldap_add): + * ldap/eldap.c (Fldap_modify): + * ldap/eldap.c (Fldap_delete): + Mule-ize. + Use EXTERNAL_LIST_LOOP_2 instead of deleted EXTERNAL_LIST_LOOP. + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/modules/common/Makefile.common' 'xemacs-21.5.19/modules/common/Makefile.common' Index: ./modules/common/Makefile.common --- ./modules/common/Makefile.common Fri Aug 29 00:44:19 2003 +++ ./modules/common/Makefile.common Tue Nov 9 00:14:52 2004 @@ -33,7 +33,7 @@ SHELL=/bin/sh RM=rm -f PROGNAME=@PROGNAME@ -CFLAGS=@CFLAGS@ +CFLAGS=@XE_CFLAGS@ INSTALL=@INSTALL@ version=@version@ prefix=@prefix@ diff --text -u 'xemacs-21.5.18/modules/ldap/eldap.c' 'xemacs-21.5.19/modules/ldap/eldap.c' Index: ./modules/ldap/eldap.c --- ./modules/ldap/eldap.c Tue Sep 21 04:19:26 2004 +++ ./modules/ldap/eldap.c Sun Nov 14 10:43:12 2004 @@ -1,5 +1,7 @@ /* LDAP client interface for XEmacs. Copyright (C) 1998 Free Software Foundation, Inc. + Copyright (C) 2004 Ben Wing. + This file is part of XEmacs. @@ -97,7 +99,7 @@ #endif } invalid_operation ("LDAP error", - build_string (ldap_err2string (ldap_err))); + build_ext_string (ldap_err2string (ldap_err), Qnative)); } @@ -223,8 +225,8 @@ LDAP *ld; int ldap_port = 0; int ldap_auth = LDAP_AUTH_SIMPLE; - char *ldap_binddn = NULL; - char *ldap_password = NULL; + Extbyte *ldap_binddn = NULL; + Extbyte *ldap_password = NULL; int ldap_deref = LDAP_DEREF_NEVER; int ldap_timelimit = 0; int ldap_sizelimit = 0; @@ -305,7 +307,7 @@ /* Connect to the server and bind */ slow_down_interrupts (); - ld = ldap_open ((char *) XSTRING_DATA (host), ldap_port); + ld = ldap_open (NEW_LISP_STRING_TO_EXTERNAL (host, Qnative), ldap_port); speed_up_interrupts (); if (ld == NULL ) @@ -343,10 +345,8 @@ err = ldap_bind_s (ld, ldap_binddn, ldap_password, ldap_auth); if (err != LDAP_SUCCESS) { - Ibyte *interrmess; - EXTERNAL_TO_C_STRING (ldap_err2string (err), interrmess, Qnative); signal_error (Qprocess_error, "Failed binding to the server", - build_intstring (interrmess)); + build_ext_string (ldap_err2string (err), Qnative)); } ldap = allocate_ldap (); @@ -425,13 +425,13 @@ LDAP *ld; LDAPMessage *e; BerElement *ptr; - char *a, *dn; + Extbyte *a, *dn; int i, rc; int matches; struct ldap_unwind_struct unwind; int ldap_scope = LDAP_SCOPE_SUBTREE; - char **ldap_attributes = NULL; + Extbyte **ldap_attributes = NULL; int speccount = specpdl_depth (); @@ -482,13 +482,14 @@ ldap_attributes = alloca_array (char *, 1 + XINT (Flength (attrs))); i = 0; - EXTERNAL_LIST_LOOP (attrs, attrs) - { - Lisp_Object current = XCAR (attrs); - CHECK_STRING (current); - LISP_STRING_TO_EXTERNAL (current, ldap_attributes[i], Qnative); - ++i; - } + { + EXTERNAL_LIST_LOOP_2 (current, attrs) + { + CHECK_STRING (current); + LISP_STRING_TO_EXTERNAL (current, ldap_attributes[i], Qnative); + ++i; + } + } ldap_attributes[i] = NULL; } @@ -497,9 +498,11 @@ /* Perform the search */ if (ldap_search (ld, - NILP (base) ? (char *) "" : (char *) XSTRING_DATA (base), + NILP (base) ? "" : + NEW_LISP_STRING_TO_EXTERNAL (base, Qnative), ldap_scope, - NILP (filter) ? (char *) "" : (char *) XSTRING_DATA (filter), + NILP (filter) ? "" : + NEW_LISP_STRING_TO_EXTERNAL (filter, Qnative), ldap_attributes, NILP (attrsonly) ? 0 : 1) == -1) @@ -536,9 +539,9 @@ signal_ldap_error (ld, e, 0); entry = Fcons (build_ext_string (dn, Qnative), Qnil); } - for (a= ldap_first_attribute (ld, e, &ptr); + for (a = ldap_first_attribute (ld, e, &ptr); a != NULL; - a = ldap_next_attribute (ld, e, ptr) ) + a = ldap_next_attribute (ld, e, ptr)) { list = Fcons (build_ext_string (a, Qnative), Qnil); unwind.vals = ldap_get_values_len (ld, e, a); @@ -618,9 +621,9 @@ Lisp_Object current = Qnil; Lisp_Object values = Qnil; - struct gcpro gcpro1, gcpro2; + struct gcpro gcpro1; - GCPRO2 (current, values); + GCPRO1 (values); /* Do all the parameter checking */ CHECK_LIVE_LDAP (ldap); @@ -639,51 +642,57 @@ ldap_mods = alloca_array (LDAPMod, len); ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len); i = 0; - EXTERNAL_LIST_LOOP (entry, entry) - { - current = XCAR (entry); - CHECK_CONS (current); - CHECK_STRING (XCAR (current)); - ldap_mods_ptrs[i] = &(ldap_mods[i]); - LISP_STRING_TO_EXTERNAL (XCAR (current), ldap_mods[i].mod_type, Qnative); - ldap_mods[i].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES; - values = XCDR (current); - if (CONSP (values)) - { - len = (Elemcount) XINT (Flength (values)); - bervals = alloca_array (struct berval, len); - ldap_mods[i].mod_vals.modv_bvals = - alloca_array (struct berval *, 1 + len); - j = 0; - EXTERNAL_LIST_LOOP (values, values) - { - current = XCAR (values); - CHECK_STRING (current); - ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]); - TO_EXTERNAL_FORMAT (LISP_STRING, current, - ALLOCA, (bervals[j].bv_val, - bervals[j].bv_len), - Qnative); - j++; - } - ldap_mods[i].mod_vals.modv_bvals[j] = NULL; - } - else - { - CHECK_STRING (values); - bervals = alloca_array (struct berval, 1); - ldap_mods[i].mod_vals.modv_bvals = alloca_array (struct berval *, 2); - ldap_mods[i].mod_vals.modv_bvals[0] = &(bervals[0]); - TO_EXTERNAL_FORMAT (LISP_STRING, values, - ALLOCA, (bervals[0].bv_val, - bervals[0].bv_len), - Qnative); - ldap_mods[i].mod_vals.modv_bvals[1] = NULL; - } - i++; - } + + { + EXTERNAL_LIST_LOOP_2 (current, entry) + { + CHECK_CONS (current); + CHECK_STRING (XCAR (current)); + ldap_mods_ptrs[i] = &(ldap_mods[i]); + LISP_STRING_TO_EXTERNAL (XCAR (current), ldap_mods[i].mod_type, + Qnative); + ldap_mods[i].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES; + values = XCDR (current); + if (CONSP (values)) + { + len = (Elemcount) XINT (Flength (values)); + bervals = alloca_array (struct berval, len); + ldap_mods[i].mod_vals.modv_bvals = + alloca_array (struct berval *, 1 + len); + j = 0; + { + EXTERNAL_LIST_LOOP_2 (cur2, values) + { + CHECK_STRING (cur2); + ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]); + TO_EXTERNAL_FORMAT (LISP_STRING, cur2, + ALLOCA, (bervals[j].bv_val, + bervals[j].bv_len), + Qnative); + j++; + } + } + ldap_mods[i].mod_vals.modv_bvals[j] = NULL; + } + else + { + CHECK_STRING (values); + bervals = alloca_array (struct berval, 1); + ldap_mods[i].mod_vals.modv_bvals = alloca_array (struct berval *, + 2); + ldap_mods[i].mod_vals.modv_bvals[0] = &(bervals[0]); + TO_EXTERNAL_FORMAT (LISP_STRING, values, + ALLOCA, (bervals[0].bv_val, + bervals[0].bv_len), + Qnative); + ldap_mods[i].mod_vals.modv_bvals[1] = NULL; + } + i++; + } + } ldap_mods_ptrs[i] = NULL; - rc = ldap_add_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs); + rc = ldap_add_s (ld, NEW_LISP_STRING_TO_EXTERNAL (dn, Qnative), + ldap_mods_ptrs); if (rc != LDAP_SUCCESS) signal_ldap_error (ld, NULL, rc); @@ -710,7 +719,6 @@ Lisp_Object mod_op; Elemcount len; - Lisp_Object current = Qnil; Lisp_Object values = Qnil; struct gcpro gcpro1, gcpro2; @@ -732,48 +740,52 @@ ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len); i = 0; - GCPRO2 (current, values); - EXTERNAL_LIST_LOOP (mods, mods) - { - current = XCAR (mods); - CHECK_CONS (current); - CHECK_SYMBOL (XCAR (current)); - mod_op = XCAR (current); - ldap_mods_ptrs[i] = &(ldap_mods[i]); - ldap_mods[i].mod_op = LDAP_MOD_BVALUES; - if (EQ (mod_op, Qadd)) - ldap_mods[i].mod_op |= LDAP_MOD_ADD; - else if (EQ (mod_op, Qdelete)) - ldap_mods[i].mod_op |= LDAP_MOD_DELETE; - else if (EQ (mod_op, Qreplace)) - ldap_mods[i].mod_op |= LDAP_MOD_REPLACE; - else - invalid_constant ("Invalid LDAP modification type", mod_op); - current = XCDR (current); - CHECK_STRING (XCAR (current)); - LISP_STRING_TO_EXTERNAL (XCAR (current), ldap_mods[i].mod_type, Qnative); - values = XCDR (current); - len = (Elemcount) XINT (Flength (values)); - bervals = alloca_array (struct berval, len); - ldap_mods[i].mod_vals.modv_bvals = - alloca_array (struct berval *, 1 + len); - j = 0; - EXTERNAL_LIST_LOOP (values, values) - { - current = XCAR (values); - CHECK_STRING (current); - ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]); - TO_EXTERNAL_FORMAT (LISP_STRING, current, - ALLOCA, (bervals[j].bv_val, - bervals[j].bv_len), - Qnative); - j++; - } - ldap_mods[i].mod_vals.modv_bvals[j] = NULL; - i++; - } + GCPRO1 (values); + { + EXTERNAL_LIST_LOOP_2 (current, mods) + { + CHECK_CONS (current); + CHECK_SYMBOL (XCAR (current)); + mod_op = XCAR (current); + ldap_mods_ptrs[i] = &(ldap_mods[i]); + ldap_mods[i].mod_op = LDAP_MOD_BVALUES; + if (EQ (mod_op, Qadd)) + ldap_mods[i].mod_op |= LDAP_MOD_ADD; + else if (EQ (mod_op, Qdelete)) + ldap_mods[i].mod_op |= LDAP_MOD_DELETE; + else if (EQ (mod_op, Qreplace)) + ldap_mods[i].mod_op |= LDAP_MOD_REPLACE; + else + invalid_constant ("Invalid LDAP modification type", mod_op); + current = XCDR (current); + CHECK_STRING (XCAR (current)); + LISP_STRING_TO_EXTERNAL (XCAR (current), ldap_mods[i].mod_type, + Qnative); + values = XCDR (current); + len = (Elemcount) XINT (Flength (values)); + bervals = alloca_array (struct berval, len); + ldap_mods[i].mod_vals.modv_bvals = + alloca_array (struct berval *, 1 + len); + j = 0; + { + EXTERNAL_LIST_LOOP_2 (cur2, values) + { + CHECK_STRING (cur2); + ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]); + TO_EXTERNAL_FORMAT (LISP_STRING, cur2, + ALLOCA, (bervals[j].bv_val, + bervals[j].bv_len), + Qnative); + j++; + } + ldap_mods[i].mod_vals.modv_bvals[j] = NULL; + i++; + } + } + } ldap_mods_ptrs[i] = NULL; - rc = ldap_modify_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs); + rc = ldap_modify_s (ld, NEW_LISP_STRING_TO_EXTERNAL (dn, Qnative), + ldap_mods_ptrs); if (rc != LDAP_SUCCESS) signal_ldap_error (ld, NULL, rc); @@ -797,7 +809,7 @@ ld = XLDAP (ldap)->ld; CHECK_STRING (dn); - rc = ldap_delete_s (ld, (char *) XSTRING_DATA (dn)); + rc = ldap_delete_s (ld, NEW_LISP_STRING_TO_EXTERNAL (dn, Qnative)); if (rc != LDAP_SUCCESS) signal_ldap_error (ld, NULL, rc); diff --text -u /dev/null 'xemacs-21.5.19/modules/postgresql/configure' Index: ./modules/postgresql/configure --- ./modules/postgresql/configure Thu Jan 1 09:00:00 1970 +++ ./modules/postgresql/configure Mon Nov 18 15:52:33 2002 @@ -0,0 +1,3808 @@ +#! /bin/sh +# From configure.ac Revision: 1.1 . +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.53a for PostgreSQL module 1.0. +# +# Report bugs to <xemacs-beta@xemacs.org>. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +# +# Configuration script for the PostgreSQL module. +# Copyright (C) 2002 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. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# NLS nuisances. +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && + { $as_unset LANG || test "${LANG+set}" != set; } || + { LANG=C; export LANG; } +(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && + { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || + { LC_ALL=C; export LC_ALL; } +(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && + { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || + { LC_TIME=C; export LC_TIME; } +(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && + { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || + { LC_CTYPE=C; export LC_CTYPE; } +(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && + { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || + { LANGUAGE=C; export LANGUAGE; } +(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && + { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || + { LC_COLLATE=C; export LC_COLLATE; } +(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && + { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || + { LC_NUMERIC=C; export LC_NUMERIC; } +(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && + { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || + { LC_MESSAGES=C; export LC_MESSAGES; } + + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conftest.sh + echo "exit 0" >>conftest.sh + chmod +x conftest.sh + if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conftest.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='PostgreSQL module' +PACKAGE_TARNAME='postgresql-module' +PACKAGE_VERSION='1.0' +PACKAGE_STRING='PostgreSQL module 1.0' +PACKAGE_BUGREPORT='xemacs-beta@xemacs.org' + +ac_unique_file="postgresql.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif" + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_ELLCC_set=${ELLCC+set} +ac_env_ELLCC_value=$ELLCC +ac_cv_env_ELLCC_set=${ELLCC+set} +ac_cv_env_ELLCC_value=$ELLCC +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures PostgreSQL module 1.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of PostgreSQL module 1.0:";; + esac + cat <<\_ACEOF + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + ELLCC The path to the ellcc module compiler + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to <xemacs-beta@xemacs.org>. +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +PostgreSQL module configure 1.0 +generated by GNU Autoconf 2.53a + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. + +Configuration script for the PostgreSQL module. +Copyright (C) 2002 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. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by PostgreSQL module $as_me 1.0, which was +generated by GNU Autoconf 2.53a. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell meta-characters. +ac_configure_args= +ac_sep= +for ac_arg +do + case $ac_arg in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n ) continue ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + ac_sep=" " ;; + esac + # Get rid of the leading space. +done + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null; + ls a.out conftest 2>/dev/null; + ls a.* conftest.* 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + a.out ) # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool --akim. + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5 +echo "$as_me: error: C compiler cannot create executables" >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (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 + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include <stdlib.h>' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <stdlib.h> +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + + + +# Find ELLCC + +# Extract the first word of "ellcc", so it can be a program name with args. +set dummy ellcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_ELLCC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $ELLCC in + [\\/]* | ?:[\\/]*) + ac_cv_path_ELLCC="$ELLCC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ELLCC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_ELLCC" && ac_cv_path_ELLCC=""FAIL"" + ;; +esac +fi +ELLCC=$ac_cv_path_ELLCC + +if test -n "$ELLCC"; then + echo "$as_me:$LINENO: result: $ELLCC" >&5 +echo "${ECHO_T}$ELLCC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test "$ELLCC" = "FAIL"; then + { { echo "$as_me:$LINENO: error: Cannot find ellcc" >&5 +echo "$as_me: error: Cannot find ellcc" >&2;} + { (exit 1); exit 1; }; } +fi + + + +for header_dir in "" "pgsql/" "postgresql/"; do + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <assert.h> + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <assert.h> + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./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 + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_Header=no" +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +as_ac_Header=`echo "ac_cv_header_${header_dir}libpq-fe.h" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for ${header_dir}libpq-fe.h" >&5 +echo $ECHO_N "checking for ${header_dir}libpq-fe.h... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking ${header_dir}libpq-fe.h usability" >&5 +echo $ECHO_N "checking ${header_dir}libpq-fe.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#include <${header_dir}libpq-fe.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking ${header_dir}libpq-fe.h presence" >&5 +echo $ECHO_N "checking ${header_dir}libpq-fe.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <${header_dir}libpq-fe.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: ${header_dir}libpq-fe.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: ${header_dir}libpq-fe.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: ${header_dir}libpq-fe.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: ${header_dir}libpq-fe.h: proceeding with the preprocessor's result" >&2;};; + no:yes ) + { echo "$as_me:$LINENO: WARNING: ${header_dir}libpq-fe.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: ${header_dir}libpq-fe.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: ${header_dir}libpq-fe.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: ${header_dir}libpq-fe.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: ${header_dir}libpq-fe.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: ${header_dir}libpq-fe.h: proceeding with the preprocessor's result" >&2;};; +esac +echo "$as_me:$LINENO: checking for ${header_dir}libpq-fe.h" >&5 +echo $ECHO_N "checking for ${header_dir}libpq-fe.h... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + libpq_fe_h_file=${header_dir}libpq-fe.h; break +fi + + +done + +test -z "$libpq_fe_h_file" && + { { echo "$as_me:$LINENO: error: Cannot find the PostgresQL header files; try specifying CPPFLAGS." >&5 +echo "$as_me: error: Cannot find the PostgresQL header files; try specifying CPPFLAGS." >&2;} + { (exit 1); exit 1; }; } +cat >>confdefs.h <<_ACEOF +#define LIBPQ_FE_H_FILE "$libpq_fe_h_file" +_ACEOF + + + +echo "$as_me:$LINENO: checking for PQconnectdb in -lpq" >&5 +echo $ECHO_N "checking for PQconnectdb in -lpq... $ECHO_C" >&6 +if test "${ac_cv_lib_pq_PQconnectdb+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpq $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "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 PQconnectdb (); +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +PQconnectdb (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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_pq_PQconnectdb=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_pq_PQconnectdb=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pq_PQconnectdb" >&5 +echo "${ECHO_T}$ac_cv_lib_pq_PQconnectdb" >&6 +if test $ac_cv_lib_pq_PQconnectdb = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPQ 1 +_ACEOF + + LIBS="-lpq $LIBS" + +else + { { echo "$as_me:$LINENO: error: Cannot find the PostgresQL library. Try specifying LDFLAGS." >&5 +echo "$as_me: error: Cannot find the PostgresQL library. Try specifying LDFLAGS." >&2;} + { (exit 1); exit 1; }; } +fi + +echo "$as_me:$LINENO: checking for PQconnectStart in -lpq" >&5 +echo $ECHO_N "checking for PQconnectStart in -lpq... $ECHO_C" >&6 +if test "${ac_cv_lib_pq_PQconnectStart+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpq $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "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 PQconnectStart (); +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +PQconnectStart (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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_pq_PQconnectStart=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_pq_PQconnectStart=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pq_PQconnectStart" >&5 +echo "${ECHO_T}$ac_cv_lib_pq_PQconnectStart" >&6 +if test $ac_cv_lib_pq_PQconnectStart = yes; then + + with_postgresqlv7=yes; + cat >>confdefs.h <<\_ACEOF +#define HAVE_POSTGRESQLV7 1 +_ACEOF + +fi + +postgresql_libs="$LIBS" + + + +# This part should appear unchanged in every module configure.ac +PROGNAME="module" + +MOD_CC="@ELLCC@" + +MODARCHDIR="\$(shell @ELLCC@ --mod-archdir)" + +MAKE_DOCFILE="\$(MODARCHDIR)/make-docfile" + +MODCFLAGS="\$(CFLAGS) --mode=compile --mod-output=\$@ -I\$(MODARCHDIR)/include" + +INSTALLPATH="\$(shell @ELLCC@ --mod-site-location)" + +MOD_INSTALL_PROGRAM="@INSTALL_PROGRAM@" + +OBJECT_TO_BUILD="\$(MODNAME).ell" + + + ac_config_files="$ac_config_files Makefile.in Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if cmp -s $cache_file confcache; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# NLS nuisances. +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && + { $as_unset LANG || test "${LANG+set}" != set; } || + { LANG=C; export LANG; } +(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && + { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || + { LC_ALL=C; export LC_ALL; } +(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && + { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || + { LC_TIME=C; export LC_TIME; } +(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && + { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || + { LC_CTYPE=C; export LC_CTYPE; } +(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && + { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || + { LANGUAGE=C; export LANGUAGE; } +(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && + { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || + { LC_COLLATE=C; export LC_COLLATE; } +(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && + { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || + { LC_NUMERIC=C; export LC_NUMERIC; } +(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && + { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || + { LC_MESSAGES=C; export LC_MESSAGES; } + + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conftest.sh + echo "exit 0" >>conftest.sh + chmod +x conftest.sh + if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conftest.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by PostgreSQL module $as_me 1.0, which was +generated by GNU Autoconf 2.53a. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +PostgreSQL module config.status 1.0 +configured by $0, generated by GNU Autoconf 2.53a, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion" + exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;; +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile.in" ) CONFIG_FILES="$CONFIG_FILES Makefile.in" ;; + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. +: ${TMPDIR=/tmp} +{ + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=$TMPDIR/cs$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@ELLCC@,$ELLCC,;t t +s,@CPP@,$CPP,;t t +s,@postgresql_libs@,$postgresql_libs,;t t +s,@PROGNAME@,$PROGNAME,;t t +s,@MOD_CC@,$MOD_CC,;t t +s,@MODARCHDIR@,$MODARCHDIR,;t t +s,@MAKE_DOCFILE@,$MAKE_DOCFILE,;t t +s,@MODCFLAGS@,$MODCFLAGS,;t t +s,@INSTALLPATH@,$INSTALLPATH,;t t +s,@MOD_INSTALL_PROGRAM@,$MOD_INSTALL_PROGRAM,;t t +s,@OBJECT_TO_BUILD@,$OBJECT_TO_BUILD,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + exec 5>/dev/null + $SHELL $CONFIG_STATUS || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + diff --text -u 'xemacs-21.5.18/netinstall/ChangeLog' 'xemacs-21.5.19/netinstall/ChangeLog' Index: ./netinstall/ChangeLog Prereq: 1.30 --- ./netinstall/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./netinstall/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,12 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + +2004-11-05 Ben Wing <ben@xemacs.org> + + * res.rc: + Fix ^M brokenness. + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. @@ -499,6 +508,6 @@ * all: port from cygwin setup. -%%% $Id: ChangeLog,v 1.30 2004/03/22 09:24:03 stephent Exp $ -$Revision: 1.30 $ +%%% $Id: ChangeLog,v 1.32 2005/01/26 05:11:01 ben Exp $ +$Revision: 1.32 $ diff --text -u 'xemacs-21.5.18/nt/ChangeLog' 'xemacs-21.5.19/nt/ChangeLog' Index: ./nt/ChangeLog --- ./nt/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./nt/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,52 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * config.inc.samp (COMPFACE_DIR): + Change version to 1.5.1 in accordance with FTP site. + +2005-01-31 Ben Wing <ben@xemacs.org> + + * xemacs.mak (install): + Also copy BUGS, README, COPYING and Installation. + +2005-01-27 Ben Wing <ben@xemacs.org> + + * xemacs.mak ({$(MANDIR)}.texi{$(INFODIR)}.info): + Use filename only when calling makeinfo, or it chokes on index + generation. + + * xemacs.mak (TEMACS_COMMON_LFLAGS): + * xemacs.mak ( $(XEMACS_LFLAGS) -section): + Generate separate .pdb and .map files for temacs/xemacs; may + make profiling possible. + +2005-01-24 Ben Wing <ben@xemacs.org> + + * config.inc.samp: + * config.inc.samp (PNG_DIR): + Declare OPTIONAL_LIBRARY_DIR as root of library directories. + Redo all graphics library defaults to mirror the versions and + directories in the current binary aux distribution on xemacs + web site. Enable TIFF and COMPFACE by default since you can + now compile with them and binary libs are provided. + + * xemacs.mak: + * xemacs.mak (INCLUDES): + Put our own directories first in case of conflict (e.g. config.h + in compface). + + * xemacs.mak ($(BLDLIB_SRC)/minitar.exe): + * xemacs.mak (LIB_SRC_TOOLS): + Use MSVCRT to avoid link problems. + +2004-11-07 Ben Wing <ben@xemacs.org> + + * xemacs.mak (INTERNALS_SRCS): + index.texi is deleted from internals/. + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/nt/config.inc.samp' 'xemacs-21.5.19/nt/config.inc.samp' Index: ./nt/config.inc.samp --- ./nt/config.inc.samp Fri Nov 7 00:12:33 2003 +++ ./nt/config.inc.samp Fri Feb 4 11:58:32 2005 @@ -26,38 +26,49 @@ # Compiled-in features: graphics formats # ############################################################################ +# Directory under which the optional libraries are placed. To make your +# life easy, just grab http://ftp.xemacs.org/aux/optional-libs.exe +# (a self-installing .ZIP) and unzip them into an appropriate directory +# (by default, c:\src). This gets you precompiled versions of all of +# the libraries below. +OPTIONAL_LIBRARY_DIR=c:\src + # Set this to enable XPM support (virtually mandatory), and specify # the directory containing xpm. Get the library from # http://ftp.xemacs.org/aux/xpm-3.4k.tar.gz. HAVE_XPM=1 -XPM_DIR=c:\src\xpm-3.4k +XPM_DIR=$(OPTIONAL_LIBRARY_DIR)\xpm-3.4k # Set this to enable GIF support (built-in). HAVE_GIF=1 # Set this to enable PNG support (virtually mandatory), and specify # the directories containing png and zlib. Get the latest version from -# ftp://ftp.uu.net/graphics/png/. You will have to rename the zlib directory -# from zlib-1.1.4 or whatever to just `zlib' for the build to work. +# ftp://ftp.uu.net/graphics/png/. NOTE: In order to compile libpng, +# you will have to rename the zlib directory to just `zlib'. We don't +# do that here so we can preserve the version number, like for the other +# libraries. HAVE_PNG=1 -PNG_DIR=c:\src\libpng-1.2.5 -ZLIB_DIR=c:\src\zlib - -# Set this to enable TIFF support, and specify the directory containing tiff. -# Get the latest version from ftp://ftp.uu.net/graphics/tiff/. Not on by -# default since TIFF isn't really very important. -HAVE_TIFF=0 -TIFF_DIR=c:\src\tiff-v3.5.7 +PNG_DIR=$(OPTIONAL_LIBRARY_DIR)\libpng-1.2.8 +ZLIB_DIR=$(OPTIONAL_LIBRARY_DIR)\zlib-1.2.1 -# Set this to enable JPEG support, and specify the directory containing jpeg. -# Get the latest version from ftp://ftp.uu.net/graphics/jpeg/. +# Set this to enable JPEG support (useful, but not necessary), and specify +# the directory containing jpeg. Get the latest version from +# ftp://ftp.uu.net/graphics/jpeg/. HAVE_JPEG=1 -JPEG_DIR=c:\src\jpeg-6b +JPEG_DIR=$(OPTIONAL_LIBRARY_DIR)\jpeg-6b -# Set this to enable XFace support, and specify the directory containing -# compface. Get the library from http://ftp.xemacs.org/aux/compface.tar.gz. -HAVE_XFACE=0 -COMPFACE_DIR= +# Set this to enable TIFF support (not very important), and specify the +# directory containing tiff. Get the latest version from +# ftp://ftp.uu.net/graphics/tiff/. +HAVE_TIFF=1 +TIFF_DIR=$(OPTIONAL_LIBRARY_DIR)\tiff-v3.5.7 + +# Set this to enable XFace support (not very important), and specify the +# directory containing compface. Get the library from +# http://ftp.xemacs.org/aux/compface-1.5.1.tar.gz. +HAVE_XFACE=1 +COMPFACE_DIR=$(OPTIONAL_LIBRARY_DIR)\compface-1.5.1 ############################################################################ # Build settings # diff --text -u 'xemacs-21.5.18/nt/installer/Wise/ChangeLog' 'xemacs-21.5.19/nt/installer/Wise/ChangeLog' Index: ./nt/installer/Wise/ChangeLog --- ./nt/installer/Wise/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./nt/installer/Wise/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,11 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + +2004-11-16 Ben Wing <ben@xemacs.org> + + * display-readme.dlg: + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/nt/installer/Wise/dirs.py' 'xemacs-21.5.19/nt/installer/Wise/dirs.py' Index: ./nt/installer/Wise/dirs.py --- ./nt/installer/Wise/dirs.py Fri Apr 13 03:23:11 2001 +++ ./nt/installer/Wise/dirs.py Sat Nov 6 08:11:42 2004 @@ -1,21 +1,21 @@ -#Configuration variables - -#where the source is: - -source = r"X:\XEmacs-21" -#where the installed distribution is: -installed = r"C:\Program Files\XEmacs\xemacs-21.0-b62" - -#where the (built and installed) packages are -packages = r"C:\Program Files\XEmacs\xemacs-packages" - -#where the package source is -pkg_src = r"X:\xemacs-packages" - -#Subdirs relative to the base installation directory -#Everything except packages goes here: -dst = "XEmacs-21.0-b62" -#packages go here: -pkg_dst = "xemacs-packages" - - +#Configuration variables + +#where the source is: + +source = r"X:\XEmacs-21" +#where the installed distribution is: +installed = r"C:\Program Files\XEmacs\xemacs-21.0-b62" + +#where the (built and installed) packages are +packages = r"C:\Program Files\XEmacs\xemacs-packages" + +#where the package source is +pkg_src = r"X:\xemacs-packages" + +#Subdirs relative to the base installation directory +#Everything except packages goes here: +dst = "XEmacs-21.0-b62" +#packages go here: +pkg_dst = "xemacs-packages" + + diff --text -u 'xemacs-21.5.18/nt/installer/Wise/display-readme.dlg' 'xemacs-21.5.19/nt/installer/Wise/display-readme.dlg' Index: ./nt/installer/Wise/display-readme.dlg --- ./nt/installer/Wise/display-readme.dlg Sat Apr 28 11:10:57 2001 +++ ./nt/installer/Wise/display-readme.dlg Wed Nov 17 11:32:16 2004 @@ -1,63 +1,63 @@ -Document Type: DLG -item: Custom Dialog - Name=Display ReadMe - Display Variable=DISPLAY - item: Dialog - Title=Read Me File - Title French=Fichier Lisez-moi - Title German=Liesmich-Datei - Title Portuguese=Ficheiro Leia-me - Title Spanish=Archivo Léeme - Title Italian=File Leggimi - Title Danish=Vigtigt fil - Title Dutch=Leesmij-bestand - Title Norwegian=Informasjonsfil - Title Swedish=Läs mig-fil - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=172 185 214 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=I &Agree > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Próximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&Næste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&Nästa > - end - item: Push Button - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Slet - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Editbox - Rectangle=85 11 254 170 - Value=%TEMP%\%READMEFILE% - Help Context=16711681 - Create Flags=01010000101000000000100000000100 - end - end -end +Document Type: DLG +item: Custom Dialog + Name=Display ReadMe + Display Variable=DISPLAY + item: Dialog + Title=Read Me File + Title French=Fichier Lisez-moi + Title German=Liesmich-Datei + Title Portuguese=Ficheiro Leia-me + Title Spanish=Archivo Léeme + Title Italian=File Leggimi + Title Danish=Vigtigt fil + Title Dutch=Leesmij-bestand + Title Norwegian=Informasjonsfil + Title Swedish=Läs mig-fil + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=I &Agree > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Slet + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Editbox + Rectangle=85 11 254 170 + Value=%TEMP%\%READMEFILE% + Help Context=16711681 + Create Flags=01010000101000000000100000000100 + end + end +end diff --text -u 'xemacs-21.5.18/nt/installer/Wise/libs.dlg' 'xemacs-21.5.19/nt/installer/Wise/libs.dlg' Index: ./nt/installer/Wise/libs.dlg --- ./nt/installer/Wise/libs.dlg Fri Apr 13 03:23:13 2001 +++ ./nt/installer/Wise/libs.dlg Sat Nov 6 08:11:42 2004 @@ -1,170 +1,170 @@ -Document Type: DLG -item: Custom Dialog - Name=Select Components - Display Variable=DISPLAY - Flags=00000001 - item: Dialog - Title=Select Components - Title French=Sélectionner les éléments - Title German=Komponenten auswählen - Title Portuguese=Seleccionar Componentes - Title Spanish=Seleccione los Componentes - Title Italian=Seleziona Componenti - Title Danish=Vælg komponenter - Title Dutch=Selecteer onderdelen - Title Norwegian=Velg komponenter - Title Swedish=Välj komponenter - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=172 185 214 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Próximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&Næste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&Nästa > - end - item: Push Button - Rectangle=130 185 172 199 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Text=< &Back - Text French=<&Retour - Text German=<&Zurück - Text Portuguese=<&Retornar - Text Spanish=<&Retroceder - Text Italian=< &Indietro - Text Danish=<&Tilbage - Text Dutch=<&Terug - Text Norwegian=<&Tilbake - Text Swedish=< &Tillbaka - end - item: Push Button - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Annuller - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=205 156 253 166 - Variable=COMPONENTS - Value=MAINDIR - Create Flags=01010000000000000000000000000010 - end - item: Static - Rectangle=205 148 253 157 - Variable=COMPONENTS - Create Flags=01010000000000000000000000000010 - end - item: Static - Rectangle=95 147 184 158 - Create Flags=01010000000000000000000000000000 - Text=Disk Space Required: - Text French=Espace disque requis - Text German=Benötigter Festplattenspeicher: - Text Portuguese=Espaço de disco necessário: - Text Spanish=Espacio de Disco Requerido: - Text Italian=Spazio su disco richiesto: - Text Danish=Nødvendig diskplads: - Text Dutch=Vereiste hoeveelheid schijfruimte - Text Norwegian=Diskplass nødvendig: - Text Swedish=Erforderligt diskutrymme - end - item: Static - Rectangle=95 157 190 167 - Create Flags=01010000000000000000000000000000 - Text=Disk Space Remaining: - Text French=Espace disque disponible - Text German=Verbleibender Festplattenspeicher: - Text Portuguese=Espaço de disco restante: - Text Spanish=Espacio de Disco Remanente: - Text Italian=Spazio su disco rimanente: - Text Danish=Ledig diskplads: - Text Dutch=Resterende schijfruimte - Text Norwegian=Ledig diskplass: - Text Swedish=Återstående diskutrymme - end - item: Static - Rectangle=90 138 264 168 - Action=1 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=90 8 260 41 - Create Flags=01010000000000000000000000000000 - Text=In the options list below, select the checkboxes for the options that you would like to have installed. The disk space fields reflect the requirements of the options you have selected. - Text French=Dans la liste d'options suivante, veuillez sélectionner les cases des options que vous désirez installer. Le champ d'espace disque indique les conditions requises pour les options choisies - Text German=Wählen Sie in der Optionenliste unten die Kontrollkästchen für diejenigen Optionen, die Sie installieren möchten. Die Speicherfelder zeigen die benötigte Speicherkapazität für die gewählten Optionen an. - Text Portuguese=Na lista de opções abaixo, seleccione as caixas de verificação para as opções que gostaria de ter instalado. Os campos de espaço de disco reflectem os requerimentos das opções que seleccionou. - Text Spanish=En la lista de opciones que se ofrece a continuación, seleccione las casillas de comprobación para las opciones que desea instalar. Los campos del espacio en el disco reflejan los requerimientos de las opciones que ha seleccionado. - Text Italian=Nell’elenco delle opzioni sotto, marca le caselle di controllo delle opzioni che vuoi installare. I campi dello spazio sul disco riflettono i requisiti delle opzioni selezionate. - Text Danish=Marker afkrydsningsfelterne for de komponenter, der skal installeres, på listen herunder. Diskpladsfelterne angiver pladskravene for de valgte komponenter. - Text Dutch=Kruis in de onderstaande lijst het vakje aan naast de opties die u wilt installeren. Achter elke optie staat de benodigde schijfruimte vermeld. - Text Norwegian=I listen over alternativer nedenfor, klikk i kontrollrutene for de alternativene du ønsker å installere. Diskplassfeltene gjenspeiler kravene for de alternativene du har valgt. - Text Swedish=Kryssa för i rutorna nedan vilka alternativ du vill få installerade. I diskutrymmesfälten anges utrymmesbehoven för de alternativ du väljer. - end - item: Checkbox - Rectangle=91 41 126 56 - Variable=COMPONENTS LIBS - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000010000000000000011 - Flags=0000000000000010 - Text=Libraries - Text= - end - item: Checkbox - Rectangle=90 56 148 71 - Variable=COMPONENTS COMM - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000010000000000000011 - Flags=0000000000000010 - Text=Communications - Text= - end - end - item: Dialog - Title=Library Packages - Width=268 - Height=204 - Font Name=Helv - Font Size=8 - end - item: Dialog - Title=Library Packages - Width=268 - Height=204 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=219 170 254 185 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000010000000000000000 - Text=OK - end - end -end +Document Type: DLG +item: Custom Dialog + Name=Select Components + Display Variable=DISPLAY + Flags=00000001 + item: Dialog + Title=Select Components + Title French=Sélectionner les éléments + Title German=Komponenten auswählen + Title Portuguese=Seleccionar Componentes + Title Spanish=Seleccione los Componentes + Title Italian=Seleziona Componenti + Title Danish=Vælg komponenter + Title Dutch=Selecteer onderdelen + Title Norwegian=Velg komponenter + Title Swedish=Välj komponenter + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=130 185 172 199 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Text=< &Back + Text French=<&Retour + Text German=<&Zurück + Text Portuguese=<&Retornar + Text Spanish=<&Retroceder + Text Italian=< &Indietro + Text Danish=<&Tilbage + Text Dutch=<&Terug + Text Norwegian=<&Tilbake + Text Swedish=< &Tillbaka + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=205 156 253 166 + Variable=COMPONENTS + Value=MAINDIR + Create Flags=01010000000000000000000000000010 + end + item: Static + Rectangle=205 148 253 157 + Variable=COMPONENTS + Create Flags=01010000000000000000000000000010 + end + item: Static + Rectangle=95 147 184 158 + Create Flags=01010000000000000000000000000000 + Text=Disk Space Required: + Text French=Espace disque requis + Text German=Benötigter Festplattenspeicher: + Text Portuguese=Espaço de disco necessário: + Text Spanish=Espacio de Disco Requerido: + Text Italian=Spazio su disco richiesto: + Text Danish=Nødvendig diskplads: + Text Dutch=Vereiste hoeveelheid schijfruimte + Text Norwegian=Diskplass nødvendig: + Text Swedish=Erforderligt diskutrymme + end + item: Static + Rectangle=95 157 190 167 + Create Flags=01010000000000000000000000000000 + Text=Disk Space Remaining: + Text French=Espace disque disponible + Text German=Verbleibender Festplattenspeicher: + Text Portuguese=Espaço de disco restante: + Text Spanish=Espacio de Disco Remanente: + Text Italian=Spazio su disco rimanente: + Text Danish=Ledig diskplads: + Text Dutch=Resterende schijfruimte + Text Norwegian=Ledig diskplass: + Text Swedish=Återstående diskutrymme + end + item: Static + Rectangle=90 138 264 168 + Action=1 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=90 8 260 41 + Create Flags=01010000000000000000000000000000 + Text=In the options list below, select the checkboxes for the options that you would like to have installed. The disk space fields reflect the requirements of the options you have selected. + Text French=Dans la liste d'options suivante, veuillez sélectionner les cases des options que vous désirez installer. Le champ d'espace disque indique les conditions requises pour les options choisies + Text German=Wählen Sie in der Optionenliste unten die Kontrollkästchen für diejenigen Optionen, die Sie installieren möchten. Die Speicherfelder zeigen die benötigte Speicherkapazität für die gewählten Optionen an. + Text Portuguese=Na lista de opções abaixo, seleccione as caixas de verificação para as opções que gostaria de ter instalado. Os campos de espaço de disco reflectem os requerimentos das opções que seleccionou. + Text Spanish=En la lista de opciones que se ofrece a continuación, seleccione las casillas de comprobación para las opciones que desea instalar. Los campos del espacio en el disco reflejan los requerimientos de las opciones que ha seleccionado. + Text Italian=Nell’elenco delle opzioni sotto, marca le caselle di controllo delle opzioni che vuoi installare. I campi dello spazio sul disco riflettono i requisiti delle opzioni selezionate. + Text Danish=Marker afkrydsningsfelterne for de komponenter, der skal installeres, på listen herunder. Diskpladsfelterne angiver pladskravene for de valgte komponenter. + Text Dutch=Kruis in de onderstaande lijst het vakje aan naast de opties die u wilt installeren. Achter elke optie staat de benodigde schijfruimte vermeld. + Text Norwegian=I listen over alternativer nedenfor, klikk i kontrollrutene for de alternativene du ønsker å installere. Diskplassfeltene gjenspeiler kravene for de alternativene du har valgt. + Text Swedish=Kryssa för i rutorna nedan vilka alternativ du vill få installerade. I diskutrymmesfälten anges utrymmesbehoven för de alternativ du väljer. + end + item: Checkbox + Rectangle=91 41 126 56 + Variable=COMPONENTS LIBS + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000010000000000000011 + Flags=0000000000000010 + Text=Libraries + Text= + end + item: Checkbox + Rectangle=90 56 148 71 + Variable=COMPONENTS COMM + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000010000000000000011 + Flags=0000000000000010 + Text=Communications + Text= + end + end + item: Dialog + Title=Library Packages + Width=268 + Height=204 + Font Name=Helv + Font Size=8 + end + item: Dialog + Title=Library Packages + Width=268 + Height=204 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=219 170 254 185 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000010000000000000000 + Text=OK + end + end +end diff --text -u 'xemacs-21.5.18/nt/installer/Wise/pre_wise.py' 'xemacs-21.5.19/nt/installer/Wise/pre_wise.py' Index: ./nt/installer/Wise/pre_wise.py --- ./nt/installer/Wise/pre_wise.py Fri Apr 13 03:23:14 2001 +++ ./nt/installer/Wise/pre_wise.py Sat Nov 6 08:11:42 2004 @@ -1,133 +1,133 @@ -import string -import re -import os -import types - -infile=open("xemacs.tmpl","r") - -import version -import dirs -import filelist -import packages - -def letter(package): - index = packages.all.index(package) - if index>29: - raise "WISE error: too many components" - return chr(ord("A")+index) - -def letters(package_list): - ret = "" - for p in package_list: - ret = ret+letter(p) - return ret - -def describe(package): - if package in packages.descriptions.keys(): - return ": "+packages.descriptions[package] - else: return "" - -def ifblock(var,val): - return("item: If/While Statement\n Variable=%s\n Value=%s\n Flags=00001010\nend\n" % (var,val)) - -def endblock(): - return("item: End Block\nend\n") - -def setvar(var,val): - return("item: Set Variable\n Variable=%s\n Value=%s\n Flags=10000000\nend\n" % (string.upper(var), val)) - -def default_letters_of_category(cat): - val = "" - for p in packages.default: - if packages.category_of_package(p) == cat: - val = val + packages.letter_of_package(p) - return val - -def set_category_defaults(): - ret = "" - for c in packages.category_names: - ret = ret + setvar(c, default_letters_of_category(c)) - return ret - -def do_category(cat): - ret = ifblock("COMPONENTS", packages.letter_of_category(cat)) - for pkg in packages.packages_of_category(cat): - ret = ret + ifblock(string.upper(cat),packages.letter_of_package(pkg)) - for f in files_of_package(pkg): - ret = ret+install_pkg_file(f) - ret = ret + endblock() - ret = ret + endblock() - return ret - -def files_of_package(package): - manifest_file = dirs.packages + "\\pkginfo\\MANIFEST." + package - manifest = open(manifest_file,"r") - lines = manifest.readlines() - lines = map(lambda s:s[:-1], lines) - lines = map(lambda s:string.replace(s,'/','\\'), lines) - return lines - -def category_dialog(cat): - npkg = len(packages.packages_of_category(cat)) - ret="" - ret=ret+" item: Dialog\n Title="+packages.category_descriptions[cat]+" Packages\n" - ret=ret+" Width=210\n" - ret=ret+" Height=%d\n" % (45+npkg*10) - ret=ret+" Font Name=Helv\n" - ret=ret+" Font Size=8\n" - ret=ret+" item: Push Button\n" - ret=ret+" Rectangle=107 %d 147 %d\n" % (5+npkg*10+2, 5+npkg*10+17) - ret=ret+" Create Flags=01010000000000010000000000000001\n" - ret=ret+" Text=OK\n" - ret=ret+" end\n" - ret=ret+" item: Push Button\n" - ret=ret+" Rectangle=153 %d 193 %d\n" % (5+npkg*10+2, 5+npkg*10+17) - ret=ret+" Variable=%s\n" % string.upper(cat) - ret=ret+" Value=%%%s_SAVE%%\n" % string.upper(cat) - ret=ret+" Create Flags=01010000000000010000000000000000\n" - ret=ret+" Flags=0000000000000001\n" - ret=ret+" Text=Cancel\n" - ret=ret+" end\n" - ret=ret+" item: Checkbox\n" - ret=ret+" Rectangle=0 5 191 %d\n" % (10*npkg) - ret=ret+" Variable=%s\n"%string.upper(cat) - ret=ret+" Create Flags=01010000000000010000000000000011\n" - ret=ret+" Flags=0000000000000010\n" - for pkg in packages.packages_of_category(cat): - ret = ret+" Text=%s: %s\n"%( pkg, packages.package_descriptions[pkg]) - ret=ret+" Text=\n" - ret=ret+" end\n" - ret=ret+" end\n" - return ret - -def src_path(src,name): - return src + "\\" + name - -def dst_path(dst,name): - return "%MAINDIR%"+"\\"+dst+"\\" + name - -def install_file(name,src,dst): - return("item: Install File\n Source=%s\n Destination=%s\n Flags=0000000010000010\nend\n" % (src_path(src,name),dst_path(dst,name))) - -def install_pkg_file(name): - return install_file(name,dirs.packages,dirs.pkg_dst) - -def do_package(package): - return ifblock("COMPONENTS",letter(package)) + \ - string.join(map(install_pkg_file,files(package)),"")+ \ - endblock() - -for line in infile.readlines(): - left=string.find(line,"<<<") - if left>=0: - right=string.find(line,">>>") - expr=line[left+3:right] - val=eval(expr) - if type(val)==types.StringType: - print line[:left] + val + line[right+3:], - elif type(val)==types.ListType: - for v in val: - print line[:left] + v + line[right+3:], - else: print line, - - +import string +import re +import os +import types + +infile=open("xemacs.tmpl","r") + +import version +import dirs +import filelist +import packages + +def letter(package): + index = packages.all.index(package) + if index>29: + raise "WISE error: too many components" + return chr(ord("A")+index) + +def letters(package_list): + ret = "" + for p in package_list: + ret = ret+letter(p) + return ret + +def describe(package): + if package in packages.descriptions.keys(): + return ": "+packages.descriptions[package] + else: return "" + +def ifblock(var,val): + return("item: If/While Statement\n Variable=%s\n Value=%s\n Flags=00001010\nend\n" % (var,val)) + +def endblock(): + return("item: End Block\nend\n") + +def setvar(var,val): + return("item: Set Variable\n Variable=%s\n Value=%s\n Flags=10000000\nend\n" % (string.upper(var), val)) + +def default_letters_of_category(cat): + val = "" + for p in packages.default: + if packages.category_of_package(p) == cat: + val = val + packages.letter_of_package(p) + return val + +def set_category_defaults(): + ret = "" + for c in packages.category_names: + ret = ret + setvar(c, default_letters_of_category(c)) + return ret + +def do_category(cat): + ret = ifblock("COMPONENTS", packages.letter_of_category(cat)) + for pkg in packages.packages_of_category(cat): + ret = ret + ifblock(string.upper(cat),packages.letter_of_package(pkg)) + for f in files_of_package(pkg): + ret = ret+install_pkg_file(f) + ret = ret + endblock() + ret = ret + endblock() + return ret + +def files_of_package(package): + manifest_file = dirs.packages + "\\pkginfo\\MANIFEST." + package + manifest = open(manifest_file,"r") + lines = manifest.readlines() + lines = map(lambda s:s[:-1], lines) + lines = map(lambda s:string.replace(s,'/','\\'), lines) + return lines + +def category_dialog(cat): + npkg = len(packages.packages_of_category(cat)) + ret="" + ret=ret+" item: Dialog\n Title="+packages.category_descriptions[cat]+" Packages\n" + ret=ret+" Width=210\n" + ret=ret+" Height=%d\n" % (45+npkg*10) + ret=ret+" Font Name=Helv\n" + ret=ret+" Font Size=8\n" + ret=ret+" item: Push Button\n" + ret=ret+" Rectangle=107 %d 147 %d\n" % (5+npkg*10+2, 5+npkg*10+17) + ret=ret+" Create Flags=01010000000000010000000000000001\n" + ret=ret+" Text=OK\n" + ret=ret+" end\n" + ret=ret+" item: Push Button\n" + ret=ret+" Rectangle=153 %d 193 %d\n" % (5+npkg*10+2, 5+npkg*10+17) + ret=ret+" Variable=%s\n" % string.upper(cat) + ret=ret+" Value=%%%s_SAVE%%\n" % string.upper(cat) + ret=ret+" Create Flags=01010000000000010000000000000000\n" + ret=ret+" Flags=0000000000000001\n" + ret=ret+" Text=Cancel\n" + ret=ret+" end\n" + ret=ret+" item: Checkbox\n" + ret=ret+" Rectangle=0 5 191 %d\n" % (10*npkg) + ret=ret+" Variable=%s\n"%string.upper(cat) + ret=ret+" Create Flags=01010000000000010000000000000011\n" + ret=ret+" Flags=0000000000000010\n" + for pkg in packages.packages_of_category(cat): + ret = ret+" Text=%s: %s\n"%( pkg, packages.package_descriptions[pkg]) + ret=ret+" Text=\n" + ret=ret+" end\n" + ret=ret+" end\n" + return ret + +def src_path(src,name): + return src + "\\" + name + +def dst_path(dst,name): + return "%MAINDIR%"+"\\"+dst+"\\" + name + +def install_file(name,src,dst): + return("item: Install File\n Source=%s\n Destination=%s\n Flags=0000000010000010\nend\n" % (src_path(src,name),dst_path(dst,name))) + +def install_pkg_file(name): + return install_file(name,dirs.packages,dirs.pkg_dst) + +def do_package(package): + return ifblock("COMPONENTS",letter(package)) + \ + string.join(map(install_pkg_file,files(package)),"")+ \ + endblock() + +for line in infile.readlines(): + left=string.find(line,"<<<") + if left>=0: + right=string.find(line,">>>") + expr=line[left+3:right] + val=eval(expr) + if type(val)==types.StringType: + print line[:left] + val + line[right+3:], + elif type(val)==types.ListType: + for v in val: + print line[:left] + v + line[right+3:], + else: print line, + + diff --text -u 'xemacs-21.5.18/nt/installer/Wise/type.dlg' 'xemacs-21.5.19/nt/installer/Wise/type.dlg' Index: ./nt/installer/Wise/type.dlg --- ./nt/installer/Wise/type.dlg Fri Apr 13 03:23:14 2001 +++ ./nt/installer/Wise/type.dlg Sat Nov 6 08:11:42 2004 @@ -1,32 +1,32 @@ -Document Type: DLG -item: Custom Dialog - Name=type - item: Dialog - Title=type - Width=238 - Height=208 - Font Name=Helv - Font Size=8 - item: Radio Button - Rectangle=5 5 40 20 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000010000000000001001 - Text=minimal - Text= - end - item: Radio Button - Rectangle=5 25 40 40 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000010000000000001001 - Text=custom - Text= - end - item: Radio Button - Rectangle=5 45 40 60 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000010000000000001001 - Text=full - Text= - end - end -end +Document Type: DLG +item: Custom Dialog + Name=type + item: Dialog + Title=type + Width=238 + Height=208 + Font Name=Helv + Font Size=8 + item: Radio Button + Rectangle=5 5 40 20 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000010000000000001001 + Text=minimal + Text= + end + item: Radio Button + Rectangle=5 25 40 40 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000010000000000001001 + Text=custom + Text= + end + item: Radio Button + Rectangle=5 45 40 60 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000010000000000001001 + Text=full + Text= + end + end +end diff --text -u 'xemacs-21.5.18/nt/installer/Wise/version.py' 'xemacs-21.5.19/nt/installer/Wise/version.py' Index: ./nt/installer/Wise/version.py --- ./nt/installer/Wise/version.py Fri Apr 13 03:23:14 2001 +++ ./nt/installer/Wise/version.py Sat Nov 6 08:11:42 2004 @@ -1,3 +1,3 @@ -title="XEmacs 21.0b62 EXPERIMENTAL" -welcome="Welcome to the %APPTITLE% setup program. Please note that this is an experimental release and some features may not work correctly, especially on machines running Windows 95. Please read the file PROBLEMS in the xemacs installation directory. Send comments or bug reports to xemacs-nt@xemacs.org. For more info see http://www.xemacs.org" - +title="XEmacs 21.0b62 EXPERIMENTAL" +welcome="Welcome to the %APPTITLE% setup program. Please note that this is an experimental release and some features may not work correctly, especially on machines running Windows 95. Please read the file PROBLEMS in the xemacs installation directory. Send comments or bug reports to xemacs-nt@xemacs.org. For more info see http://www.xemacs.org" + diff --text -u 'xemacs-21.5.18/nt/installer/Wise/welcome.dlg' 'xemacs-21.5.19/nt/installer/Wise/welcome.dlg' Index: ./nt/installer/Wise/welcome.dlg --- ./nt/installer/Wise/welcome.dlg Fri Apr 13 03:23:14 2001 +++ ./nt/installer/Wise/welcome.dlg Sat Nov 6 08:11:42 2004 @@ -1,63 +1,63 @@ -Document Type: DLG -item: Custom Dialog - Name=Welcome - Display Variable=DISPLAY - item: Dialog - Title=Welcome - Title French=Bienvenue - Title German=Willkommen - Title Portuguese=Bem-vindo - Title Spanish=Bienvenido - Title Italian=Benvenuto - Title Danish=Velkommen - Title Dutch=Welkom - Title Norwegian=Velkommen - Title Swedish=Välkommen - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=172 185 214 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Próximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&Næste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&Nästa > - end - item: Push Button - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Annuller - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=91 22 245 118 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000000 - Text=Welcome to the %APPTITLE% setup program. Please note that this is an experimental release and some features may not work correctly. Send comments or bug reports to xemacs-nt@xemacs.org rather than one of the other XEmacs mailing lists. For more info see http://www.xemacs.org - end - end -end +Document Type: DLG +item: Custom Dialog + Name=Welcome + Display Variable=DISPLAY + item: Dialog + Title=Welcome + Title French=Bienvenue + Title German=Willkommen + Title Portuguese=Bem-vindo + Title Spanish=Bienvenido + Title Italian=Benvenuto + Title Danish=Velkommen + Title Dutch=Welkom + Title Norwegian=Velkommen + Title Swedish=Välkommen + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=91 22 245 118 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000000000000000000000 + Text=Welcome to the %APPTITLE% setup program. Please note that this is an experimental release and some features may not work correctly. Send comments or bug reports to xemacs-nt@xemacs.org rather than one of the other XEmacs mailing lists. For more info see http://www.xemacs.org + end + end +end diff --text -u 'xemacs-21.5.18/nt/installer/Wise/xemacs.tmpl' 'xemacs-21.5.19/nt/installer/Wise/xemacs.tmpl' Index: ./nt/installer/Wise/xemacs.tmpl --- ./nt/installer/Wise/xemacs.tmpl Fri Apr 13 03:23:15 2001 +++ ./nt/installer/Wise/xemacs.tmpl Sat Nov 6 08:11:42 2004 @@ -1,1310 +1,1310 @@ -Document Type: WSE -item: Global - Version=7.0 - Title=<<<version.title + " Installation">>> - Flags=00000100 - Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - Japanese Font Name=MS Gothic - Japanese Font Size=10 - Progress Bar DLL=%_WISE_%\Progress\WIZ%_EXE_OS_TYPE_%.DLL - Start Gradient=0 0 255 - End Gradient=0 0 0 - Windows Flags=00000100000000010010110000001000 - Log Pathname=%MAINDIR%\INSTALL.LOG - Message Font=MS Sans Serif - Font Size=8 - Disk Filename=SETUP - Patch Flags=0000000000000001 - Patch Threshold=85 - Patch Memory=4000 - FTP Cluster Size=20 - Dialogs Version=6 - Variable Name1=_SYS_ - Variable Default1=C:\WINDOWS\SYSTEM - Variable Flags1=00001000 - Variable Name2=_WISE_ - Variable Default2=C:\PROGRAM FILES\WISE INSTALLBUILDER - Variable Flags2=00001000 -end -item: Get Temporary Filename - Variable=READMEFILE -end -item: Install File - Source=<<<dirs.source>>>\nt\Wise\Copying.txt - Destination=%TEMP%\%READMEFILE% - Flags=0000000000100010 -end -item: Open/Close INSTALL.LOG - Flags=00000001 -end -item: Check if File/Dir Exists - Pathname=%SYS% - Flags=10000100 -end -item: Set Variable - Variable=SYS - Value=%WIN% -end -item: End Block -end -item: Set Variable - Variable=APPTITLE - Value=<<<version.title>>> - Flags=10000000 -end -item: Set Variable - Variable=GROUP - Value=XEmacs - Flags=10000000 -end -item: Set Variable - Variable=DISABLED - Value=! -end -item: Set Variable - Variable=MAINDIR - Value=XEmacs - Flags=10000000 -end -item: Check Configuration - Flags=10111011 -end -item: Get Registry Key Value - Variable=COMMON - Key=SOFTWARE\Microsoft\Windows\CurrentVersion - Default=C:\Program Files\Common Files - Value Name=CommonFilesDir - Flags=00000100 -end -item: Get Registry Key Value - Variable=PROGRAM_FILES - Key=SOFTWARE\Microsoft\Windows\CurrentVersion - Default=C:\Program Files - Value Name=ProgramFilesDir - Flags=00000100 -end -item: Set Variable - Variable=MAINDIR - Value=%PROGRAM_FILES%\%MAINDIR% - Flags=00001100 -end -item: Set Variable - Variable=EXPLORER - Value=1 -end -item: Else Statement -end -item: Set Variable - Variable=MAINDIR - Value=C:\%MAINDIR% - Flags=00001100 -end -item: End Block -end -item: Set Variable - Variable=BACKUP - Value=%MAINDIR%\BACKUP - Flags=10000000 -end -item: Set Variable - Variable=DOBACKUP - Value=B - Flags=10000000 -end -item: Set Variable - Variable=COMPONENTS - Value=ACE - Flags=10000000 -end -<<<set_category_defaults()>>> -item: Wizard Block - Direction Variable=DIRECTION - Display Variable=DISPLAY - Bitmap Pathname=<<<dirs.source>>>\nt\Wise\gnu.bmp - X Position=9 - Y Position=10 - Filler Color=8421440 - Dialog=Select Program Manager Group - Dialog=Select Backup Directory - Dialog=Display Registration Information - Dialog=Get Registration Information - Variable=EXPLORER - Variable=DOBACKUP - Variable=DOBRAND - Variable=DOBRAND - Value=1 - Value=A - Value=1 - Value=1 - Compare=0 - Compare=1 - Compare=0 - Compare=1 - Flags=00000011 -end -item: Custom Dialog Set - Name=Welcome - Display Variable=DISPLAY - item: Dialog - Title=Welcome - Title French=Bienvenue - Title German=Willkommen - Title Portuguese=Bem-vindo - Title Spanish=Bienvenido - Title Italian=Benvenuto - Title Danish=Velkommen - Title Dutch=Welkom - Title Norwegian=Velkommen - Title Swedish=Välkommen - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=172 185 214 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Próximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&Næste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&Nästa > - end - item: Push Button - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Annuller - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=91 22 245 118 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000000 - Text=<<<version.welcome>>> - end - end -end -item: Custom Dialog Set - Name=Display ReadMe - Display Variable=DISPLAY - item: Dialog - Title=Read Me File - Title French=Fichier Lisez-moi - Title German=Liesmich-Datei - Title Portuguese=Ficheiro Leia-me - Title Spanish=Archivo Léeme - Title Italian=File Leggimi - Title Danish=Vigtigt fil - Title Dutch=Leesmij-bestand - Title Norwegian=Informasjonsfil - Title Swedish=Läs mig-fil - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=172 185 214 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=I &Agree > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Próximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&Næste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&Nästa > - end - item: Push Button - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Slet - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Editbox - Rectangle=85 11 254 170 - Value=%TEMP%\%READMEFILE% - Help Context=16711681 - Create Flags=01010000101000000000100000000100 - end - end -end -item: Custom Dialog Set - Name=Select Destination Directory - Display Variable=DISPLAY - item: Dialog - Title=Choose Destination Location - Title French=Choisissez la localisation de destination - Title German=Zielpfad wählen - Title Portuguese=Escolher Local de Destino - Title Spanish=Elegir una localización de destino - Title Italian=Scegli Posizione di Destinazione - Title Danish=Vælg destinationsmappe - Title Dutch=Kies doellocatie - Title Norwegian=Velg målplassering - Title Swedish=Välj ställe för installationen - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=172 185 214 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Próximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&Næste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&Nästa > - end - item: Push Button - Rectangle=130 185 172 199 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Flags=0000000000000001 - Text=< &Back - Text French=<&Retour - Text German=<&Zurück - Text Portuguese=<&Retornar - Text Spanish=<&Retroceder - Text Italian=< &Indietro - Text Danish=<&Tilbage - Text Dutch=<&Terug - Text Norwegian=<&Tilbake - Text Swedish=< &Tillbaka - end - item: Push Button - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Annuller - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=90 10 260 122 - Create Flags=01010000000000000000000000000000 - Text=Setup will install %APPTITLE% in the following folder. - Text= - Text=To install into a different folder, click Browse, and select another folder. - Text= - Text=You can choose not to install %APPTITLE% by clicking Cancel to exit Setup. - Text French=%APPTITLE% va être installé dans le répertoire ci-dessous - Text French= - Text French=Pour l'installer dans un répertoire différent, cliquez sur Parcourir et sélectionnez un autre répertoire - Text French= - Text French=Vous pouvez choisir de ne pas installer %APPTITLE% en cliquant sur Annuler pour quitter l'Installation - Text German=Installation speichert %APPTITLE% im unten angegebenen Ordner: - Text German= - Text German=Zur Installation in einem anderen Ordner auf Blättern klicken und einen anderen Ordner wählen. - Text German= - Text German=Wenn Sie %APPTITLE% nicht installieren möchten, können Sie durch Klicken auf Abbrechen die Installation beenden. - Text Portuguese=Configuração instalará %APPTITLE% na seguinte pasta - Text Portuguese= - Text Portuguese=Para instalar numa pasta diferente, faça um clique sobre Procurar, e seleccione uma outra pasta. - Text Portuguese= - Text Portuguese=Pode escolher não instalar %APPTITLE% clicando no botão Cancelar para sair da Configuração - Text Spanish=El programa de Configuración instalará %APPTITLE% en la siguiente carpeta. - Text Spanish= - Text Spanish=Para instalar en una carpeta diferente, haga un clic en Visualizar, y seleccione otra carpeta. - Text Spanish= - Text Spanish=Puede elegir no instalar %APPTITLE% haciendo un clic en Cancelar para salir de Configuración. - Text Italian=Il programma di installazione installerà %APPTITLE% nella seguente cartella. - Text Italian= - Text Italian=Per effettuare l’installazione in una cartella diversa, fai clic su Sfoglia, e scegli un’altra cartella. - Text Italian= - Text Italian=Puoi scegliere di non installare %APPTITLE% facendo clic su Annulla per uscire dal programma di installazione - Text Danish=Installationsprogrammet installerer %APPTITLE% i denne mappe. - Text Danish= - Text Danish=Man installerer i en anden mappe ved at klikke på Browse og vælge en anden mappe. - Text Danish= - Text Danish=Man kan vælge ikke at installere %APPTITLE% ved at klikke på Slet og forlade installationsprogrammet. - Text Dutch=Het installatieprogramma installeert %APPTITLE% in de volgende directory. - Text Dutch= - Text Dutch=Als u het in een andere directory wilt installeren, klik dan op Bladeren en kies een andere locatie. - Text Dutch= - Text Dutch=U kunt ervoor kiezen om %APPTITLE% niet te installeren: klik op Annuleren om het installatieprogramma te verlaten. - Text Norwegian=Oppsett vil installere %APPTITLE% i følgende mappe. - Text Norwegian= - Text Norwegian=For å installere i en annen mappe, klikk Bla igjennom og velg en annen mappe. - Text Norwegian= - Text Norwegian=Du kan velge å ikke installere %APPTITLE% ved å velge Avbryt for å gå ut av Oppsett. - Text Swedish=Installationsprogrammet installerar %APPTITLE% i följande mapp. - Text Swedish= - Text Swedish=Om du vill att installationen ska göras i en annan mapp, klickar du på Bläddra och väljer en annan mapp. - Text Swedish= - Text Swedish=Du kan välja att inte installera %APPTITLE% genom att klicka på Avbryt för att lämna installationsprogrammet. - end - item: Static - Rectangle=90 134 260 162 - Action=1 - Create Flags=01010000000000000000000000000111 - Text=Destination Folder - Text French=Répertoire de destination - Text German=Zielordner - Text Portuguese=Pasta de Destino - Text Spanish=Carpeta de Destino - Text Italian=Cartella di destinazione - Text Danish=Destinationsmappe - Text Dutch=Doeldirectory - Text Norwegian=Målmappe - Text Swedish=Destinationsmapp - end - item: Push Button - Rectangle=213 143 255 157 - Variable=MAINDIR_SAVE - Value=%MAINDIR% - Destination Dialog=1 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=B&rowse... - Text French=P&arcourir - Text German=B&lättern... - Text Portuguese=P&rocurar - Text Spanish=V&isualizar... - Text Italian=Sfoglia... - Text Danish=&Gennemse... - Text Dutch=B&laderen... - Text Norwegian=Bla igjennom - Text Swedish=&Bläddra - end - item: Static - Rectangle=95 146 211 157 - Destination Dialog=2 - Create Flags=01010000000000000000000000000000 - Text=%MAINDIR% - Text French=%MAINDIR% - Text German=%MAINDIR% - Text Portuguese=%MAINDIR% - Text Spanish=%MAINDIR% - Text Italian=%MAINDIR% - Text Danish=%MAINDIR% - Text Dutch=%MAINDIR% - Text Norwegian=%MAINDIR% - Text Swedish=%MAINDIR% - end - end - item: Dialog - Title=Select Destination Directory - Title French=Choisissez le répertoire de destination - Title German=Zielverzeichnis wählen - Title Portuguese=Seleccionar Directório de Destino - Title Spanish=Seleccione el Directorio de Destino - Title Italian=Seleziona Directory di destinazione - Title Danish=Vælg Destinationsbibliotek - Title Dutch=Kies doeldirectory - Title Norwegian=Velg målkatalog - Title Swedish=Välj destinationskalatog - Width=221 - Height=173 - Font Name=Helv - Font Size=8 - item: Listbox - Rectangle=5 2 160 149 - Variable=MAINDIR - Create Flags=01010000100000010000000101000000 - Flags=0000110000100010 - Text=%MAINDIR% - Text French=%MAINDIR% - Text German=%MAINDIR% - Text Portuguese=%MAINDIR% - Text Spanish=%MAINDIR% - Text Italian=%MAINDIR% - Text Danish=%MAINDIR% - Text Dutch=%MAINDIR% - Text Norwegian=%MAINDIR% - Text Swedish=%MAINDIR% - end - item: Push Button - Rectangle=167 6 212 21 - Create Flags=01010000000000010000000000000001 - Text=OK - Text French=OK - Text German=OK - Text Portuguese=OK - Text Spanish=ACEPTAR - Text Italian=OK - Text Danish=OK - Text Dutch=OK - Text Norwegian=OK - Text Swedish=OK - end - item: Push Button - Rectangle=167 25 212 40 - Variable=MAINDIR - Value=%MAINDIR_SAVE% - Create Flags=01010000000000010000000000000000 - Flags=0000000000000001 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Slet - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - end -end -item: Custom Dialog Set - Name=Select Packages - Display Variable=DISPLAY - item: Dialog - Title=Select Packages - Width=271 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=150 187 195 202 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suite > - Text German=&Weiter > - Text Spanish=&Siguiente > - Text Italian=&Avanti > - end - item: Push Button - Rectangle=105 187 150 202 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Text=< &Back - Text French=< &Retour - Text German=< &Zurück - Text Spanish=< &Atrás - Text Italian=< &Indietro - end - item: Push Button - Rectangle=211 187 256 202 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=&Cancel - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Static - Rectangle=8 180 256 181 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=86 8 258 28 - Create Flags=01010000000000000000000000000000 - Flags=0000000000000001 - Name=Times New Roman - Font Style=-24 0 0 0 700 255 0 0 0 3 2 1 18 - Text=Select Packages - Text French=Sélectionner les composants - Text German=Komponenten auswählen - Text Spanish=Seleccione componentes - Text Italian=Selezionare i componenti - end - item: Checkbox - Rectangle=83 62 211 146 - Variable=COMPONENTS LIBS,COMM,OA,OS,PROG,WP,GAMES - Create Flags=01010000000000010000000000000011 - Flags=0000000000000110 - Text=Libraries - Text=Communication - Text=Productivity - Text=Operating System - Text=Programming - Text=Word Processing - Text=Games and Amusements - Text= - end - item: Static - Rectangle=194 162 242 172 - Variable=COMPONENTS, LIBS, COMM, OA, OS, PROG, WP, GAMES - Value=MAINDIR - Create Flags=01010000000000000000000000000010 - end - item: Static - Rectangle=194 153 242 162 - Variable=COMPONENTS, LIBS, COMM, OA, OS, PROG, WP, GAMES - Create Flags=01010000000000000000000000000010 - end - item: Static - Rectangle=107 153 196 164 - Create Flags=01010000000000000000000000000000 - Text=Disk Space Required: - Text French=Espace disque requis : - Text German=Notwendiger Speicherplatz: - Text Spanish=Espacio requerido en el disco: - Text Italian=Spazio su disco necessario: - end - item: Static - Rectangle=107 162 196 172 - Create Flags=01010000000000000000000000000000 - Text=Disk Space Remaining: - Text French=Espace disque disponible : - Text German=Verbleibender Speicherplatz: - Text Spanish=Espacio en disco disponible: - Text Italian=Spazio su disco disponibile: - end - item: Static - Rectangle=80 146 256 175 - Action=1 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=83 30 256 57 - Create Flags=01010000000000000000000000000000 - Text=Choose which package categories to install by checking the boxes below. Press the Options buttons to select individual packages. - Text French=Choisissez les composants que vous voulez installer en cochant les cases ci-dessous. - Text German=Wählen Sie die zu installierenden Komponenten, indem Sie in die entsprechenden Kästchen klicken. - Text Spanish=Elija los componentes que desee instalar marcando los cuadros de abajo. - Text Italian=Scegliere quali componenti installare selezionando le caselle sottostanti. - end - item: Push Button - Rectangle=230 62 254 72 - Variable=LIBS_SAVE - Value=%LIBS% - Destination Dialog=1 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=Options - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Push Button - Rectangle=230 74 254 84 - Variable=COMM_SAVE - Value=%COMM% - Destination Dialog=2 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=Options - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Push Button - Rectangle=230 86 254 96 - Variable=OA_SAVE - Value=%OA% - Destination Dialog=3 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=Options - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Push Button - Rectangle=230 98 254 108 - Variable=OS_SAVE - Value=%OS% - Destination Dialog=4 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=Options - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Push Button - Rectangle=230 110 254 120 - Variable=PROG_SAVE - Value=%PROG% - Destination Dialog=5 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=Options - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Push Button - Rectangle=230 122 254 132 - Variable=WP_SAVE - Value=%WP% - Destination Dialog=6 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=Options - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Push Button - Rectangle=230 134 254 144 - Variable=GAMES_SAVE - Value=%GAMES% - Destination Dialog=7 - Action=2 - Create Flags=01010000000000010000000000000000 - Text=Options - Text French=&Annuler - Text German=&Abbrechen - Text Spanish=&Cancelar - Text Italian=&Annulla - end - item: Set Variable - Variable=COMPONENTS - Value=X - Flags=00000001 - end - end -<<<string.join(map(category_dialog,packages.category_names),"")>>> -end -item: Custom Dialog Set - Name=Select Program Manager Group - Display Variable=DISPLAY - item: Dialog - Title=Select Program Manager Group - Title French=Sélectionnez le Groupe du Gestionnaire de Programmes - Title German=Programm-Managergruppe wählen - Title Portuguese=Seleccionar o Grupo Gestor de Programas - Title Spanish=Seleccione el Grupo del Administrador del Programa - Title Italian=Seleziona il gruppo Program Manager - Title Danish=Vælg Programstyringsgruppen - Title Dutch=Kies Programmabeheergroep. - Title Norwegian=Velg Programbehandlingsgruppen - Title Swedish=Välj grupp i Programhanteraren - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=172 185 214 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Próximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&Næste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&Nästa > - end - item: Push Button - Rectangle=130 185 172 199 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Flags=0000000000000001 - Text=< &Back - Text French=<&Retour - Text German=<&Zurück - Text Portuguese=<&Retornar - Text Spanish=<&Retroceder - Text Italian=< &Indietro - Text Danish=<&Back - Text Dutch=<&Terug - Text Norwegian=<&Tilbake - Text Swedish=< &Tillbaka - end - item: Push Button - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Slet - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=90 10 260 38 - Create Flags=01010000000000000000000000000000 - Text=Enter the name of the Program Manager group to add %APPTITLE% icons to: - Text French=Entrez le nom du groupe du Gestionnaire de Programmes où placer les icônes %APPTITLE% à : - Text German=Den Namen der Programm-Managergruppe wählen, in der die %APPTITLE%-Symbole gespeichert werden sollen: - Text Portuguese=Introduzir o nome do Grupo Gestor de Programa para acrescentar os ícones %APPTITLE% para: - Text Spanish=Introduzca el nombre del grupo del Administrador del Programa para añadir los iconos %APPTITLE para: - Text Italian=Inserisci il nome del gruppo Program Manager per aggiungere le icone di %APPTITLE% a: - Text Danish=Indtast navnet på Programstyringsgruppen der skal tilføjes %APPTITLE% elementer: - Text Dutch=Breng de naam van de programmabeheergroep in waaraan u %APPTITLE%-pictogrammen wilt toevoegen. - Text Norwegian=Tast inn navnet på programbehandlingsgruppen for å legge %APPTITLE%-ikoner til: - Text Swedish=Skriv in namnet på den grupp i Programhanteraren där du vill ha ikonerna för %APPTITLE%: - end - item: Combobox - Rectangle=90 42 260 148 - Variable=GROUP - Create Flags=01010000001000010000001100000001 - Flags=0000000000000001 - Text=%GROUP% - Text= - Text French=%GROUP% - Text French= - Text German=%GROUP% - Text German= - Text Portuguese=%GROUP% - Text Portuguese= - Text Spanish=%GROUP% - Text Spanish= - Text Italian=%GROUP% - Text Italian= - Text Danish=%GROUP% - Text Danish= - Text Dutch=%GROUP% - Text Dutch= - Text Norwegian=%GROUP% - Text Norwegian= - Text Swedish=%GROUP% - Text Swedish= - end - end -end -item: Custom Dialog Set - Name=Start Installation - Display Variable=DISPLAY - item: Dialog - Title=Start Installation - Title French=Commencer l'installation - Title German=Installation beginnen - Title Portuguese=Iniciar Instalação - Title Spanish=Comenzar la Instalación - Title Italian=Avvia Installazione - Title Danish=Start installationen - Title Dutch=Start de installatie. - Title Norwegian=Start installeringen - Title Swedish=Starta installationen - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=172 185 214 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Next > - Text French=&Suivant> - Text German=&Weiter> - Text Portuguese=&Próximo> - Text Spanish=&Siguiente > - Text Italian=&Avanti > - Text Danish=&Næste> - Text Dutch=&Volgende> - Text Norwegian=&Neste> - Text Swedish=&Nästa > - end - item: Push Button - Rectangle=130 185 172 199 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Text=< &Back - Text French=<&Retour - Text German=<&Zurück - Text Portuguese=<&Retornar - Text Spanish=<&Retroceder - Text Italian=< &Indietro - Text Danish=<&Tilbage - Text Dutch=<&Terug - Text Norwegian=<&Tilbake - Text Swedish=< &Tillbaka - end - item: Push Button - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Annuller - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=90 10 260 70 - Create Flags=01010000000000000000000000000000 - Text=You are now ready to install %APPTITLE%. - Text= - Text=Press the Next button to begin the installation or the Back button to reenter the installation information. - Text French=Vous êtes maintenant prêt à installer %APPTITLE% - Text French= - Text French=Cliquez sur Suivant pour commencer l'installation ou Retour pour entrer à nouveau les informations d'installation - Text German=Sie sind jetzt zur Installation von %APPTITLE% bereit. - Text German= - Text German=Auf die Schaltfläche Weiter klicken, um mit dem Start der Installation zu beginnen, oder auf die Schaltfläche Zurück, um die Installationsinformationen nochmals aufzurufen. - Text Portuguese=Está agora pronto para instalar %APPTITLE% - Text Portuguese= - Text Portuguese=Pressione o botão Próximo para começar a instalação ou o botão Retornar para introduzir novamente a informação sobre a instalação - Text Spanish=Ahora estará listo para instalar %APPTITLE%. - Text Spanish= - Text Spanish=Pulse el botón de Próximo para comenzar la instalación o el botón Retroceder para volver a introducir la información sobre la instalación. - Text Italian=Sei pronto ad installare %APPTITLE%. - Text Italian= - Text Italian=Premi il tasto Avanti per iniziare l’installazione o il tasto Indietro per rientrare nuovamente nei dati sull’installazione - Text Danish=Du er nu klar til at installere %APPTITLE%. - Text Danish= - Text Danish=Klik på Næste for at starte installationen eller på Tilbage for at ændre installationsoplysningerne. - Text Dutch=U bent nu klaar om %APPTITLE% te installeren. - Text Dutch= - Text Dutch=Druk op Volgende om met de installatie te beginnen of op Terug om de installatie-informatie opnieuw in te voeren. - Text Norwegian=Du er nå klar til å installere %APPTITLE% - Text Norwegian= - Text Norwegian=Trykk på Neste-tasten for å starte installeringen, eller Tilbake-tasten for å taste inn installasjonsinformasjonen på nytt. - Text Swedish=Du är nu redo att installera %APPTITLE%. - Text Swedish= - Text Swedish=Tryck på Nästa för att starta installationen eller på Tillbaka för att skriva in installationsinformationen på nytt. - end - end -end -item: If/While Statement - Variable=DISPLAY - Value=Select Destination Directory -end -item: Set Variable - Variable=BACKUP - Value=%MAINDIR%\BACKUP -end -item: End Block -end -item: End Block -end -item: If/While Statement - Variable=DOBACKUP - Value=A -end -item: Set Variable - Variable=BACKUPDIR - Value=%BACKUP% -end -item: End Block -end -item: Open/Close INSTALL.LOG -end -item: Check Disk Space - Component=COMPONENTS -end -item: Display Graphic - Pathname=<<<dirs.source>>>\nt\Wise\xemacs-beta.bmp - X Position=32784 - Y Position=16 -end -item: Include Script - Pathname=%_WISE_%\INCLUDE\uninstal.wse -end -<<<ifblock("COMPONENTS","X")>>> -<<<string.join(map(lambda x:install_file(x[0],x[1],x[2]),filelist.all),"")>>> -<<<endblock()>>> -<<<map(do_category,packages.category_names)>>> -item: Set Variable - Variable=COMMON - Value=%COMMON% - Flags=00010100 -end -item: Set Variable - Variable=MAINDIR - Value=%MAINDIR% - Flags=00010100 -end -item: Check Configuration - Flags=10111011 -end -item: Get Registry Key Value - Variable=STARTUPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%WIN%\Start Menu\Programs\StartUp - Value Name=StartUp - Flags=00000010 -end -item: Get Registry Key Value - Variable=DESKTOPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%WIN%\Desktop - Value Name=Desktop - Flags=00000010 -end -item: Get Registry Key Value - Variable=STARTMENUDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%WIN%\Start Menu - Value Name=Start Menu - Flags=00000010 -end -item: Get Registry Key Value - Variable=GROUPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%WIN%\Start Menu\Programs - Value Name=Programs - Flags=00000010 -end -item: Get Registry Key Value - Variable=CSTARTUPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%STARTUPDIR% - Value Name=Common Startup - Flags=00000100 -end -item: Get Registry Key Value - Variable=CDESKTOPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%DESKTOPDIR% - Value Name=Common Desktop - Flags=00000100 -end -item: Get Registry Key Value - Variable=CSTARTMENUDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%STARTMENUDIR% - Value Name=Common Start Menu - Flags=00000100 -end -item: Get Registry Key Value - Variable=CGROUPDIR - Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - Default=%GROUPDIR% - Value Name=Common Programs - Flags=00000100 -end -item: Set Variable - Variable=CGROUP_SAVE - Value=%GROUP% -end -item: Set Variable - Variable=GROUP - Value=%GROUPDIR%\%GROUP% -end -item: Create Shortcut - Source=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe - Destination=%GROUP%\XEmacs.lnk - Working Directory=\ - Icon Number=0 -end -item: Create Shortcut - Source=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe - Destination=%DESKTOPDIR%\XEmacs.lnk - Working Directory=\ - Icon Number=0 -end -item: Else Statement -end -item: Add ProgMan Icon - Group=%GROUP% - Icon Name=XEmacs - Command Line=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe - Default Directory=\ - Flags=01000000 -end -item: End Block -end -item: Edit Registry - Total Keys=16 - item: Key - Key=SOFTWARE\GNU\XEmacs - New Value=%MAINDIR% - Value Name=emacs_dir - Root=2 - end - item: Key - Key=SOFTWARE\GNU\XEmacs - New Value=%MAINDIR%\xemacs-packages - Value Name=EMACSPACKAGEPATH - Root=2 - end - item: Key - Key=SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\runemacs.exe - New Value=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32 - Value Name=Path - Root=2 - end - item: Key - Key=SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\xemacs.exe - New Value=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32 - Value Name=Path - Root=2 - end - item: Key - Key=.el - New Value=elfile - end - item: Key - Key=.el - New Value=text/plain - Value Name=Content Type - end - item: Key - Key=elfile - New Value=Emacs lisp - end - item: Key - Key=elfile - New Value=00 00 01 00 - Value Name=EditFlags - Data Type=4 - end - item: Key - Key=elfile\DefaultIcon - New Value=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe,2 - end - item: Key - Key=elfile\QuickView - New Value=* - end - item: Key - Key=elfile\Shell - New Value= - end - item: Key - Key=elfile\Shell\open - end - item: Key - Key=elfile\Shell\open\command - New Value=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe "%%1" - end - item: Key - Key=elfile\Shell\open\ddeexec - New Value=open("%%1") - end - item: Key - Key=elfile\Shell\open\ddeexec\Application - New Value=XEmacs - New Value= - end - item: Key - Key=elfile\Shell\open\ddeexec\topic - New Value=System - end -end -item: Wizard Block - Direction Variable=DIRECTION - Display Variable=DISPLAY - Bitmap Pathname=<<<dirs.source>>>\nt\Wise\gnu.bmp - X Position=9 - Y Position=10 - Filler Color=8421440 - Flags=00000011 -end -item: Custom Dialog Set - Name=Finished - Display Variable=DISPLAY - item: Dialog - Title=Installation Complete - Title French=Installation en cours - Title German=Installation abgeschlossen - Title Portuguese=Instalação Completa - Title Spanish=Se ha completado la Instalación - Title Italian=Installazione completata - Title Danish=Installation gennemført - Title Dutch=Installatie afgerond - Title Norwegian=Installasjonen er fullført - Title Swedish=Installationen klar - Width=280 - Height=224 - Font Name=Helv - Font Size=8 - item: Push Button - Rectangle=170 185 212 199 - Variable=DIRECTION - Value=N - Create Flags=01010000000000010000000000000001 - Text=&Finish > - Text French=&Terminer> - Text German=&Fertigstellen> - Text Portuguese=&Terminar > - Text Spanish=&Finalizar> - Text Italian=&Fine > - Text Danish=&Afslut > - Text Dutch=&Klaar> - Text Norwegian=&Avslutt> - Text Swedish=&Sluta> - end - item: Push Button - Control Name=CANCEL - Rectangle=222 185 264 199 - Action=3 - Create Flags=01010000000000010000000000000000 - Text=Cancel - Text French=Annuler - Text German=Abbrechen - Text Portuguese=Cancelar - Text Spanish=Cancelar - Text Italian=Annulla - Text Danish=Annuller - Text Dutch=Annuleren - Text Norwegian=Avbryt - Text Swedish=Avbryt - end - item: Static - Rectangle=9 177 263 178 - Action=3 - Create Flags=01010000000000000000000000000111 - end - item: Static - Rectangle=90 10 260 63 - Enabled Color=00000000000000001111111111111111 - Create Flags=01010000000000000000000000000000 - Text=%APPTITLE% has been successfully installed. - Text= - Text= - Text=Press the Finish button to exit this installation. - Text= - Text French=L'installation de %APPTITLE% est réussie - Text French= - Text French= - Text French=Cliquez sur Terminer pour quitter cette installation - Text French= - Text German=%APPTITLE% wurde erfolgreich installiert. - Text German= - Text German= - Text German=Zum Beenden dieser Installation Fertigstellen anklicken. - Text German= - Text Portuguese=%APPTITLE% foi instalado com êxito - Text Portuguese= - Text Portuguese= - Text Portuguese=Pressionar o botão Terminar para sair desta instalação - Text Portuguese= - Text Spanish=%APPTITLE% se ha instalado con éxito. - Text Spanish= - Text Spanish= - Text Spanish=Pulse el botón de Finalizar para salir de esta instalación. - Text Spanish= - Text Italian=%APPTITLE% è stato installato. - Text Italian= - Text Italian= - Text Italian=Premi il pulsante Fine per uscire dal programma di installazione - Text Italian= - Text Danish=%APPTITLE% er nu installeret korrekt. - Text Danish= - Text Danish= - Text Danish=Klik på Afslut for at afslutte installationen. - Text Danish= - Text Dutch=%APPTITLE% is met succes geïnstalleerd. - Text Dutch= - Text Dutch= - Text Dutch=Druk op Klaar om deze installatie af te ronden. - Text Dutch= - Text Norwegian=Installasjonen av %APPTITLE% er suksessfull. - Text Norwegian= - Text Norwegian= - Text Norwegian=Trykk på Avslutt-tasten for å avslutte denne installasjonen. - Text Norwegian= - Text Swedish=Installationen av %APPTITLE% har lyckats. - Text Swedish= - Text Swedish= - Text Swedish=Tryck på Sluta för att gå ur installationsprogrammet. - Text Swedish= - end - item: Push Button - Control Name=BACK - Rectangle=128 185 170 199 - Variable=DIRECTION - Value=B - Create Flags=01010000000000010000000000000000 - Text=< &Back - Text French=<&Retour - Text German=<&Zurück - Text Portuguese=<&Retornar - Text Spanish=<&Retroceder - Text Italian=< &Indietro - Text Danish=<&Tilbage - Text Dutch=<&Terug - Text Norwegian=<&Tilbake - Text Swedish=< &Tillbaka - end - item: Set Control Attribute - Control Name=BACK - Operation=1 - end - item: Set Control Attribute - Control Name=CANCEL - Operation=1 - end - end -end -item: End Block -end -item: New Event - Name=Cancel -end -item: Include Script - Pathname=%_WISE_%\INCLUDE\rollback.wse -end +Document Type: WSE +item: Global + Version=7.0 + Title=<<<version.title + " Installation">>> + Flags=00000100 + Languages=65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + Japanese Font Name=MS Gothic + Japanese Font Size=10 + Progress Bar DLL=%_WISE_%\Progress\WIZ%_EXE_OS_TYPE_%.DLL + Start Gradient=0 0 255 + End Gradient=0 0 0 + Windows Flags=00000100000000010010110000001000 + Log Pathname=%MAINDIR%\INSTALL.LOG + Message Font=MS Sans Serif + Font Size=8 + Disk Filename=SETUP + Patch Flags=0000000000000001 + Patch Threshold=85 + Patch Memory=4000 + FTP Cluster Size=20 + Dialogs Version=6 + Variable Name1=_SYS_ + Variable Default1=C:\WINDOWS\SYSTEM + Variable Flags1=00001000 + Variable Name2=_WISE_ + Variable Default2=C:\PROGRAM FILES\WISE INSTALLBUILDER + Variable Flags2=00001000 +end +item: Get Temporary Filename + Variable=READMEFILE +end +item: Install File + Source=<<<dirs.source>>>\nt\Wise\Copying.txt + Destination=%TEMP%\%READMEFILE% + Flags=0000000000100010 +end +item: Open/Close INSTALL.LOG + Flags=00000001 +end +item: Check if File/Dir Exists + Pathname=%SYS% + Flags=10000100 +end +item: Set Variable + Variable=SYS + Value=%WIN% +end +item: End Block +end +item: Set Variable + Variable=APPTITLE + Value=<<<version.title>>> + Flags=10000000 +end +item: Set Variable + Variable=GROUP + Value=XEmacs + Flags=10000000 +end +item: Set Variable + Variable=DISABLED + Value=! +end +item: Set Variable + Variable=MAINDIR + Value=XEmacs + Flags=10000000 +end +item: Check Configuration + Flags=10111011 +end +item: Get Registry Key Value + Variable=COMMON + Key=SOFTWARE\Microsoft\Windows\CurrentVersion + Default=C:\Program Files\Common Files + Value Name=CommonFilesDir + Flags=00000100 +end +item: Get Registry Key Value + Variable=PROGRAM_FILES + Key=SOFTWARE\Microsoft\Windows\CurrentVersion + Default=C:\Program Files + Value Name=ProgramFilesDir + Flags=00000100 +end +item: Set Variable + Variable=MAINDIR + Value=%PROGRAM_FILES%\%MAINDIR% + Flags=00001100 +end +item: Set Variable + Variable=EXPLORER + Value=1 +end +item: Else Statement +end +item: Set Variable + Variable=MAINDIR + Value=C:\%MAINDIR% + Flags=00001100 +end +item: End Block +end +item: Set Variable + Variable=BACKUP + Value=%MAINDIR%\BACKUP + Flags=10000000 +end +item: Set Variable + Variable=DOBACKUP + Value=B + Flags=10000000 +end +item: Set Variable + Variable=COMPONENTS + Value=ACE + Flags=10000000 +end +<<<set_category_defaults()>>> +item: Wizard Block + Direction Variable=DIRECTION + Display Variable=DISPLAY + Bitmap Pathname=<<<dirs.source>>>\nt\Wise\gnu.bmp + X Position=9 + Y Position=10 + Filler Color=8421440 + Dialog=Select Program Manager Group + Dialog=Select Backup Directory + Dialog=Display Registration Information + Dialog=Get Registration Information + Variable=EXPLORER + Variable=DOBACKUP + Variable=DOBRAND + Variable=DOBRAND + Value=1 + Value=A + Value=1 + Value=1 + Compare=0 + Compare=1 + Compare=0 + Compare=1 + Flags=00000011 +end +item: Custom Dialog Set + Name=Welcome + Display Variable=DISPLAY + item: Dialog + Title=Welcome + Title French=Bienvenue + Title German=Willkommen + Title Portuguese=Bem-vindo + Title Spanish=Bienvenido + Title Italian=Benvenuto + Title Danish=Velkommen + Title Dutch=Welkom + Title Norwegian=Velkommen + Title Swedish=Välkommen + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=91 22 245 118 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000000000000000000000 + Text=<<<version.welcome>>> + end + end +end +item: Custom Dialog Set + Name=Display ReadMe + Display Variable=DISPLAY + item: Dialog + Title=Read Me File + Title French=Fichier Lisez-moi + Title German=Liesmich-Datei + Title Portuguese=Ficheiro Leia-me + Title Spanish=Archivo Léeme + Title Italian=File Leggimi + Title Danish=Vigtigt fil + Title Dutch=Leesmij-bestand + Title Norwegian=Informasjonsfil + Title Swedish=Läs mig-fil + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=I &Agree > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Slet + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Editbox + Rectangle=85 11 254 170 + Value=%TEMP%\%READMEFILE% + Help Context=16711681 + Create Flags=01010000101000000000100000000100 + end + end +end +item: Custom Dialog Set + Name=Select Destination Directory + Display Variable=DISPLAY + item: Dialog + Title=Choose Destination Location + Title French=Choisissez la localisation de destination + Title German=Zielpfad wählen + Title Portuguese=Escolher Local de Destino + Title Spanish=Elegir una localización de destino + Title Italian=Scegli Posizione di Destinazione + Title Danish=Vælg destinationsmappe + Title Dutch=Kies doellocatie + Title Norwegian=Velg målplassering + Title Swedish=Välj ställe för installationen + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=130 185 172 199 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Flags=0000000000000001 + Text=< &Back + Text French=<&Retour + Text German=<&Zurück + Text Portuguese=<&Retornar + Text Spanish=<&Retroceder + Text Italian=< &Indietro + Text Danish=<&Tilbage + Text Dutch=<&Terug + Text Norwegian=<&Tilbake + Text Swedish=< &Tillbaka + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=90 10 260 122 + Create Flags=01010000000000000000000000000000 + Text=Setup will install %APPTITLE% in the following folder. + Text= + Text=To install into a different folder, click Browse, and select another folder. + Text= + Text=You can choose not to install %APPTITLE% by clicking Cancel to exit Setup. + Text French=%APPTITLE% va être installé dans le répertoire ci-dessous + Text French= + Text French=Pour l'installer dans un répertoire différent, cliquez sur Parcourir et sélectionnez un autre répertoire + Text French= + Text French=Vous pouvez choisir de ne pas installer %APPTITLE% en cliquant sur Annuler pour quitter l'Installation + Text German=Installation speichert %APPTITLE% im unten angegebenen Ordner: + Text German= + Text German=Zur Installation in einem anderen Ordner auf Blättern klicken und einen anderen Ordner wählen. + Text German= + Text German=Wenn Sie %APPTITLE% nicht installieren möchten, können Sie durch Klicken auf Abbrechen die Installation beenden. + Text Portuguese=Configuração instalará %APPTITLE% na seguinte pasta + Text Portuguese= + Text Portuguese=Para instalar numa pasta diferente, faça um clique sobre Procurar, e seleccione uma outra pasta. + Text Portuguese= + Text Portuguese=Pode escolher não instalar %APPTITLE% clicando no botão Cancelar para sair da Configuração + Text Spanish=El programa de Configuración instalará %APPTITLE% en la siguiente carpeta. + Text Spanish= + Text Spanish=Para instalar en una carpeta diferente, haga un clic en Visualizar, y seleccione otra carpeta. + Text Spanish= + Text Spanish=Puede elegir no instalar %APPTITLE% haciendo un clic en Cancelar para salir de Configuración. + Text Italian=Il programma di installazione installerà %APPTITLE% nella seguente cartella. + Text Italian= + Text Italian=Per effettuare l’installazione in una cartella diversa, fai clic su Sfoglia, e scegli un’altra cartella. + Text Italian= + Text Italian=Puoi scegliere di non installare %APPTITLE% facendo clic su Annulla per uscire dal programma di installazione + Text Danish=Installationsprogrammet installerer %APPTITLE% i denne mappe. + Text Danish= + Text Danish=Man installerer i en anden mappe ved at klikke på Browse og vælge en anden mappe. + Text Danish= + Text Danish=Man kan vælge ikke at installere %APPTITLE% ved at klikke på Slet og forlade installationsprogrammet. + Text Dutch=Het installatieprogramma installeert %APPTITLE% in de volgende directory. + Text Dutch= + Text Dutch=Als u het in een andere directory wilt installeren, klik dan op Bladeren en kies een andere locatie. + Text Dutch= + Text Dutch=U kunt ervoor kiezen om %APPTITLE% niet te installeren: klik op Annuleren om het installatieprogramma te verlaten. + Text Norwegian=Oppsett vil installere %APPTITLE% i følgende mappe. + Text Norwegian= + Text Norwegian=For å installere i en annen mappe, klikk Bla igjennom og velg en annen mappe. + Text Norwegian= + Text Norwegian=Du kan velge å ikke installere %APPTITLE% ved å velge Avbryt for å gå ut av Oppsett. + Text Swedish=Installationsprogrammet installerar %APPTITLE% i följande mapp. + Text Swedish= + Text Swedish=Om du vill att installationen ska göras i en annan mapp, klickar du på Bläddra och väljer en annan mapp. + Text Swedish= + Text Swedish=Du kan välja att inte installera %APPTITLE% genom att klicka på Avbryt för att lämna installationsprogrammet. + end + item: Static + Rectangle=90 134 260 162 + Action=1 + Create Flags=01010000000000000000000000000111 + Text=Destination Folder + Text French=Répertoire de destination + Text German=Zielordner + Text Portuguese=Pasta de Destino + Text Spanish=Carpeta de Destino + Text Italian=Cartella di destinazione + Text Danish=Destinationsmappe + Text Dutch=Doeldirectory + Text Norwegian=Målmappe + Text Swedish=Destinationsmapp + end + item: Push Button + Rectangle=213 143 255 157 + Variable=MAINDIR_SAVE + Value=%MAINDIR% + Destination Dialog=1 + Action=2 + Create Flags=01010000000000010000000000000000 + Text=B&rowse... + Text French=P&arcourir + Text German=B&lättern... + Text Portuguese=P&rocurar + Text Spanish=V&isualizar... + Text Italian=Sfoglia... + Text Danish=&Gennemse... + Text Dutch=B&laderen... + Text Norwegian=Bla igjennom + Text Swedish=&Bläddra + end + item: Static + Rectangle=95 146 211 157 + Destination Dialog=2 + Create Flags=01010000000000000000000000000000 + Text=%MAINDIR% + Text French=%MAINDIR% + Text German=%MAINDIR% + Text Portuguese=%MAINDIR% + Text Spanish=%MAINDIR% + Text Italian=%MAINDIR% + Text Danish=%MAINDIR% + Text Dutch=%MAINDIR% + Text Norwegian=%MAINDIR% + Text Swedish=%MAINDIR% + end + end + item: Dialog + Title=Select Destination Directory + Title French=Choisissez le répertoire de destination + Title German=Zielverzeichnis wählen + Title Portuguese=Seleccionar Directório de Destino + Title Spanish=Seleccione el Directorio de Destino + Title Italian=Seleziona Directory di destinazione + Title Danish=Vælg Destinationsbibliotek + Title Dutch=Kies doeldirectory + Title Norwegian=Velg målkatalog + Title Swedish=Välj destinationskalatog + Width=221 + Height=173 + Font Name=Helv + Font Size=8 + item: Listbox + Rectangle=5 2 160 149 + Variable=MAINDIR + Create Flags=01010000100000010000000101000000 + Flags=0000110000100010 + Text=%MAINDIR% + Text French=%MAINDIR% + Text German=%MAINDIR% + Text Portuguese=%MAINDIR% + Text Spanish=%MAINDIR% + Text Italian=%MAINDIR% + Text Danish=%MAINDIR% + Text Dutch=%MAINDIR% + Text Norwegian=%MAINDIR% + Text Swedish=%MAINDIR% + end + item: Push Button + Rectangle=167 6 212 21 + Create Flags=01010000000000010000000000000001 + Text=OK + Text French=OK + Text German=OK + Text Portuguese=OK + Text Spanish=ACEPTAR + Text Italian=OK + Text Danish=OK + Text Dutch=OK + Text Norwegian=OK + Text Swedish=OK + end + item: Push Button + Rectangle=167 25 212 40 + Variable=MAINDIR + Value=%MAINDIR_SAVE% + Create Flags=01010000000000010000000000000000 + Flags=0000000000000001 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Slet + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + end +end +item: Custom Dialog Set + Name=Select Packages + Display Variable=DISPLAY + item: Dialog + Title=Select Packages + Width=271 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=150 187 195 202 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suite > + Text German=&Weiter > + Text Spanish=&Siguiente > + Text Italian=&Avanti > + end + item: Push Button + Rectangle=105 187 150 202 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Text=< &Back + Text French=< &Retour + Text German=< &Zurück + Text Spanish=< &Atrás + Text Italian=< &Indietro + end + item: Push Button + Rectangle=211 187 256 202 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=&Cancel + Text French=&Annuler + Text German=&Abbrechen + Text Spanish=&Cancelar + Text Italian=&Annulla + end + item: Static + Rectangle=8 180 256 181 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=86 8 258 28 + Create Flags=01010000000000000000000000000000 + Flags=0000000000000001 + Name=Times New Roman + Font Style=-24 0 0 0 700 255 0 0 0 3 2 1 18 + Text=Select Packages + Text French=Sélectionner les composants + Text German=Komponenten auswählen + Text Spanish=Seleccione componentes + Text Italian=Selezionare i componenti + end + item: Checkbox + Rectangle=83 62 211 146 + Variable=COMPONENTS LIBS,COMM,OA,OS,PROG,WP,GAMES + Create Flags=01010000000000010000000000000011 + Flags=0000000000000110 + Text=Libraries + Text=Communication + Text=Productivity + Text=Operating System + Text=Programming + Text=Word Processing + Text=Games and Amusements + Text= + end + item: Static + Rectangle=194 162 242 172 + Variable=COMPONENTS, LIBS, COMM, OA, OS, PROG, WP, GAMES + Value=MAINDIR + Create Flags=01010000000000000000000000000010 + end + item: Static + Rectangle=194 153 242 162 + Variable=COMPONENTS, LIBS, COMM, OA, OS, PROG, WP, GAMES + Create Flags=01010000000000000000000000000010 + end + item: Static + Rectangle=107 153 196 164 + Create Flags=01010000000000000000000000000000 + Text=Disk Space Required: + Text French=Espace disque requis : + Text German=Notwendiger Speicherplatz: + Text Spanish=Espacio requerido en el disco: + Text Italian=Spazio su disco necessario: + end + item: Static + Rectangle=107 162 196 172 + Create Flags=01010000000000000000000000000000 + Text=Disk Space Remaining: + Text French=Espace disque disponible : + Text German=Verbleibender Speicherplatz: + Text Spanish=Espacio en disco disponible: + Text Italian=Spazio su disco disponibile: + end + item: Static + Rectangle=80 146 256 175 + Action=1 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=83 30 256 57 + Create Flags=01010000000000000000000000000000 + Text=Choose which package categories to install by checking the boxes below. Press the Options buttons to select individual packages. + Text French=Choisissez les composants que vous voulez installer en cochant les cases ci-dessous. + Text German=Wählen Sie die zu installierenden Komponenten, indem Sie in die entsprechenden Kästchen klicken. + Text Spanish=Elija los componentes que desee instalar marcando los cuadros de abajo. + Text Italian=Scegliere quali componenti installare selezionando le caselle sottostanti. + end + item: Push Button + Rectangle=230 62 254 72 + Variable=LIBS_SAVE + Value=%LIBS% + Destination Dialog=1 + Action=2 + Create Flags=01010000000000010000000000000000 + Text=Options + Text French=&Annuler + Text German=&Abbrechen + Text Spanish=&Cancelar + Text Italian=&Annulla + end + item: Push Button + Rectangle=230 74 254 84 + Variable=COMM_SAVE + Value=%COMM% + Destination Dialog=2 + Action=2 + Create Flags=01010000000000010000000000000000 + Text=Options + Text French=&Annuler + Text German=&Abbrechen + Text Spanish=&Cancelar + Text Italian=&Annulla + end + item: Push Button + Rectangle=230 86 254 96 + Variable=OA_SAVE + Value=%OA% + Destination Dialog=3 + Action=2 + Create Flags=01010000000000010000000000000000 + Text=Options + Text French=&Annuler + Text German=&Abbrechen + Text Spanish=&Cancelar + Text Italian=&Annulla + end + item: Push Button + Rectangle=230 98 254 108 + Variable=OS_SAVE + Value=%OS% + Destination Dialog=4 + Action=2 + Create Flags=01010000000000010000000000000000 + Text=Options + Text French=&Annuler + Text German=&Abbrechen + Text Spanish=&Cancelar + Text Italian=&Annulla + end + item: Push Button + Rectangle=230 110 254 120 + Variable=PROG_SAVE + Value=%PROG% + Destination Dialog=5 + Action=2 + Create Flags=01010000000000010000000000000000 + Text=Options + Text French=&Annuler + Text German=&Abbrechen + Text Spanish=&Cancelar + Text Italian=&Annulla + end + item: Push Button + Rectangle=230 122 254 132 + Variable=WP_SAVE + Value=%WP% + Destination Dialog=6 + Action=2 + Create Flags=01010000000000010000000000000000 + Text=Options + Text French=&Annuler + Text German=&Abbrechen + Text Spanish=&Cancelar + Text Italian=&Annulla + end + item: Push Button + Rectangle=230 134 254 144 + Variable=GAMES_SAVE + Value=%GAMES% + Destination Dialog=7 + Action=2 + Create Flags=01010000000000010000000000000000 + Text=Options + Text French=&Annuler + Text German=&Abbrechen + Text Spanish=&Cancelar + Text Italian=&Annulla + end + item: Set Variable + Variable=COMPONENTS + Value=X + Flags=00000001 + end + end +<<<string.join(map(category_dialog,packages.category_names),"")>>> +end +item: Custom Dialog Set + Name=Select Program Manager Group + Display Variable=DISPLAY + item: Dialog + Title=Select Program Manager Group + Title French=Sélectionnez le Groupe du Gestionnaire de Programmes + Title German=Programm-Managergruppe wählen + Title Portuguese=Seleccionar o Grupo Gestor de Programas + Title Spanish=Seleccione el Grupo del Administrador del Programa + Title Italian=Seleziona il gruppo Program Manager + Title Danish=Vælg Programstyringsgruppen + Title Dutch=Kies Programmabeheergroep. + Title Norwegian=Velg Programbehandlingsgruppen + Title Swedish=Välj grupp i Programhanteraren + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=130 185 172 199 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Flags=0000000000000001 + Text=< &Back + Text French=<&Retour + Text German=<&Zurück + Text Portuguese=<&Retornar + Text Spanish=<&Retroceder + Text Italian=< &Indietro + Text Danish=<&Back + Text Dutch=<&Terug + Text Norwegian=<&Tilbake + Text Swedish=< &Tillbaka + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Slet + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=90 10 260 38 + Create Flags=01010000000000000000000000000000 + Text=Enter the name of the Program Manager group to add %APPTITLE% icons to: + Text French=Entrez le nom du groupe du Gestionnaire de Programmes où placer les icônes %APPTITLE% à : + Text German=Den Namen der Programm-Managergruppe wählen, in der die %APPTITLE%-Symbole gespeichert werden sollen: + Text Portuguese=Introduzir o nome do Grupo Gestor de Programa para acrescentar os ícones %APPTITLE% para: + Text Spanish=Introduzca el nombre del grupo del Administrador del Programa para añadir los iconos %APPTITLE para: + Text Italian=Inserisci il nome del gruppo Program Manager per aggiungere le icone di %APPTITLE% a: + Text Danish=Indtast navnet på Programstyringsgruppen der skal tilføjes %APPTITLE% elementer: + Text Dutch=Breng de naam van de programmabeheergroep in waaraan u %APPTITLE%-pictogrammen wilt toevoegen. + Text Norwegian=Tast inn navnet på programbehandlingsgruppen for å legge %APPTITLE%-ikoner til: + Text Swedish=Skriv in namnet på den grupp i Programhanteraren där du vill ha ikonerna för %APPTITLE%: + end + item: Combobox + Rectangle=90 42 260 148 + Variable=GROUP + Create Flags=01010000001000010000001100000001 + Flags=0000000000000001 + Text=%GROUP% + Text= + Text French=%GROUP% + Text French= + Text German=%GROUP% + Text German= + Text Portuguese=%GROUP% + Text Portuguese= + Text Spanish=%GROUP% + Text Spanish= + Text Italian=%GROUP% + Text Italian= + Text Danish=%GROUP% + Text Danish= + Text Dutch=%GROUP% + Text Dutch= + Text Norwegian=%GROUP% + Text Norwegian= + Text Swedish=%GROUP% + Text Swedish= + end + end +end +item: Custom Dialog Set + Name=Start Installation + Display Variable=DISPLAY + item: Dialog + Title=Start Installation + Title French=Commencer l'installation + Title German=Installation beginnen + Title Portuguese=Iniciar Instalação + Title Spanish=Comenzar la Instalación + Title Italian=Avvia Installazione + Title Danish=Start installationen + Title Dutch=Start de installatie. + Title Norwegian=Start installeringen + Title Swedish=Starta installationen + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=172 185 214 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Next > + Text French=&Suivant> + Text German=&Weiter> + Text Portuguese=&Próximo> + Text Spanish=&Siguiente > + Text Italian=&Avanti > + Text Danish=&Næste> + Text Dutch=&Volgende> + Text Norwegian=&Neste> + Text Swedish=&Nästa > + end + item: Push Button + Rectangle=130 185 172 199 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Text=< &Back + Text French=<&Retour + Text German=<&Zurück + Text Portuguese=<&Retornar + Text Spanish=<&Retroceder + Text Italian=< &Indietro + Text Danish=<&Tilbage + Text Dutch=<&Terug + Text Norwegian=<&Tilbake + Text Swedish=< &Tillbaka + end + item: Push Button + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=90 10 260 70 + Create Flags=01010000000000000000000000000000 + Text=You are now ready to install %APPTITLE%. + Text= + Text=Press the Next button to begin the installation or the Back button to reenter the installation information. + Text French=Vous êtes maintenant prêt à installer %APPTITLE% + Text French= + Text French=Cliquez sur Suivant pour commencer l'installation ou Retour pour entrer à nouveau les informations d'installation + Text German=Sie sind jetzt zur Installation von %APPTITLE% bereit. + Text German= + Text German=Auf die Schaltfläche Weiter klicken, um mit dem Start der Installation zu beginnen, oder auf die Schaltfläche Zurück, um die Installationsinformationen nochmals aufzurufen. + Text Portuguese=Está agora pronto para instalar %APPTITLE% + Text Portuguese= + Text Portuguese=Pressione o botão Próximo para começar a instalação ou o botão Retornar para introduzir novamente a informação sobre a instalação + Text Spanish=Ahora estará listo para instalar %APPTITLE%. + Text Spanish= + Text Spanish=Pulse el botón de Próximo para comenzar la instalación o el botón Retroceder para volver a introducir la información sobre la instalación. + Text Italian=Sei pronto ad installare %APPTITLE%. + Text Italian= + Text Italian=Premi il tasto Avanti per iniziare l’installazione o il tasto Indietro per rientrare nuovamente nei dati sull’installazione + Text Danish=Du er nu klar til at installere %APPTITLE%. + Text Danish= + Text Danish=Klik på Næste for at starte installationen eller på Tilbage for at ændre installationsoplysningerne. + Text Dutch=U bent nu klaar om %APPTITLE% te installeren. + Text Dutch= + Text Dutch=Druk op Volgende om met de installatie te beginnen of op Terug om de installatie-informatie opnieuw in te voeren. + Text Norwegian=Du er nå klar til å installere %APPTITLE% + Text Norwegian= + Text Norwegian=Trykk på Neste-tasten for å starte installeringen, eller Tilbake-tasten for å taste inn installasjonsinformasjonen på nytt. + Text Swedish=Du är nu redo att installera %APPTITLE%. + Text Swedish= + Text Swedish=Tryck på Nästa för att starta installationen eller på Tillbaka för att skriva in installationsinformationen på nytt. + end + end +end +item: If/While Statement + Variable=DISPLAY + Value=Select Destination Directory +end +item: Set Variable + Variable=BACKUP + Value=%MAINDIR%\BACKUP +end +item: End Block +end +item: End Block +end +item: If/While Statement + Variable=DOBACKUP + Value=A +end +item: Set Variable + Variable=BACKUPDIR + Value=%BACKUP% +end +item: End Block +end +item: Open/Close INSTALL.LOG +end +item: Check Disk Space + Component=COMPONENTS +end +item: Display Graphic + Pathname=<<<dirs.source>>>\nt\Wise\xemacs-beta.bmp + X Position=32784 + Y Position=16 +end +item: Include Script + Pathname=%_WISE_%\INCLUDE\uninstal.wse +end +<<<ifblock("COMPONENTS","X")>>> +<<<string.join(map(lambda x:install_file(x[0],x[1],x[2]),filelist.all),"")>>> +<<<endblock()>>> +<<<map(do_category,packages.category_names)>>> +item: Set Variable + Variable=COMMON + Value=%COMMON% + Flags=00010100 +end +item: Set Variable + Variable=MAINDIR + Value=%MAINDIR% + Flags=00010100 +end +item: Check Configuration + Flags=10111011 +end +item: Get Registry Key Value + Variable=STARTUPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%WIN%\Start Menu\Programs\StartUp + Value Name=StartUp + Flags=00000010 +end +item: Get Registry Key Value + Variable=DESKTOPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%WIN%\Desktop + Value Name=Desktop + Flags=00000010 +end +item: Get Registry Key Value + Variable=STARTMENUDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%WIN%\Start Menu + Value Name=Start Menu + Flags=00000010 +end +item: Get Registry Key Value + Variable=GROUPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%WIN%\Start Menu\Programs + Value Name=Programs + Flags=00000010 +end +item: Get Registry Key Value + Variable=CSTARTUPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%STARTUPDIR% + Value Name=Common Startup + Flags=00000100 +end +item: Get Registry Key Value + Variable=CDESKTOPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%DESKTOPDIR% + Value Name=Common Desktop + Flags=00000100 +end +item: Get Registry Key Value + Variable=CSTARTMENUDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%STARTMENUDIR% + Value Name=Common Start Menu + Flags=00000100 +end +item: Get Registry Key Value + Variable=CGROUPDIR + Key=Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + Default=%GROUPDIR% + Value Name=Common Programs + Flags=00000100 +end +item: Set Variable + Variable=CGROUP_SAVE + Value=%GROUP% +end +item: Set Variable + Variable=GROUP + Value=%GROUPDIR%\%GROUP% +end +item: Create Shortcut + Source=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe + Destination=%GROUP%\XEmacs.lnk + Working Directory=\ + Icon Number=0 +end +item: Create Shortcut + Source=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe + Destination=%DESKTOPDIR%\XEmacs.lnk + Working Directory=\ + Icon Number=0 +end +item: Else Statement +end +item: Add ProgMan Icon + Group=%GROUP% + Icon Name=XEmacs + Command Line=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe + Default Directory=\ + Flags=01000000 +end +item: End Block +end +item: Edit Registry + Total Keys=16 + item: Key + Key=SOFTWARE\GNU\XEmacs + New Value=%MAINDIR% + Value Name=emacs_dir + Root=2 + end + item: Key + Key=SOFTWARE\GNU\XEmacs + New Value=%MAINDIR%\xemacs-packages + Value Name=EMACSPACKAGEPATH + Root=2 + end + item: Key + Key=SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\runemacs.exe + New Value=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32 + Value Name=Path + Root=2 + end + item: Key + Key=SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\xemacs.exe + New Value=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32 + Value Name=Path + Root=2 + end + item: Key + Key=.el + New Value=elfile + end + item: Key + Key=.el + New Value=text/plain + Value Name=Content Type + end + item: Key + Key=elfile + New Value=Emacs lisp + end + item: Key + Key=elfile + New Value=00 00 01 00 + Value Name=EditFlags + Data Type=4 + end + item: Key + Key=elfile\DefaultIcon + New Value=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe,2 + end + item: Key + Key=elfile\QuickView + New Value=* + end + item: Key + Key=elfile\Shell + New Value= + end + item: Key + Key=elfile\Shell\open + end + item: Key + Key=elfile\Shell\open\command + New Value=%MAINDIR%\<<<dirs.dst>>>\i386-pc-win32\runemacs.exe "%%1" + end + item: Key + Key=elfile\Shell\open\ddeexec + New Value=open("%%1") + end + item: Key + Key=elfile\Shell\open\ddeexec\Application + New Value=XEmacs + New Value= + end + item: Key + Key=elfile\Shell\open\ddeexec\topic + New Value=System + end +end +item: Wizard Block + Direction Variable=DIRECTION + Display Variable=DISPLAY + Bitmap Pathname=<<<dirs.source>>>\nt\Wise\gnu.bmp + X Position=9 + Y Position=10 + Filler Color=8421440 + Flags=00000011 +end +item: Custom Dialog Set + Name=Finished + Display Variable=DISPLAY + item: Dialog + Title=Installation Complete + Title French=Installation en cours + Title German=Installation abgeschlossen + Title Portuguese=Instalação Completa + Title Spanish=Se ha completado la Instalación + Title Italian=Installazione completata + Title Danish=Installation gennemført + Title Dutch=Installatie afgerond + Title Norwegian=Installasjonen er fullført + Title Swedish=Installationen klar + Width=280 + Height=224 + Font Name=Helv + Font Size=8 + item: Push Button + Rectangle=170 185 212 199 + Variable=DIRECTION + Value=N + Create Flags=01010000000000010000000000000001 + Text=&Finish > + Text French=&Terminer> + Text German=&Fertigstellen> + Text Portuguese=&Terminar > + Text Spanish=&Finalizar> + Text Italian=&Fine > + Text Danish=&Afslut > + Text Dutch=&Klaar> + Text Norwegian=&Avslutt> + Text Swedish=&Sluta> + end + item: Push Button + Control Name=CANCEL + Rectangle=222 185 264 199 + Action=3 + Create Flags=01010000000000010000000000000000 + Text=Cancel + Text French=Annuler + Text German=Abbrechen + Text Portuguese=Cancelar + Text Spanish=Cancelar + Text Italian=Annulla + Text Danish=Annuller + Text Dutch=Annuleren + Text Norwegian=Avbryt + Text Swedish=Avbryt + end + item: Static + Rectangle=9 177 263 178 + Action=3 + Create Flags=01010000000000000000000000000111 + end + item: Static + Rectangle=90 10 260 63 + Enabled Color=00000000000000001111111111111111 + Create Flags=01010000000000000000000000000000 + Text=%APPTITLE% has been successfully installed. + Text= + Text= + Text=Press the Finish button to exit this installation. + Text= + Text French=L'installation de %APPTITLE% est réussie + Text French= + Text French= + Text French=Cliquez sur Terminer pour quitter cette installation + Text French= + Text German=%APPTITLE% wurde erfolgreich installiert. + Text German= + Text German= + Text German=Zum Beenden dieser Installation Fertigstellen anklicken. + Text German= + Text Portuguese=%APPTITLE% foi instalado com êxito + Text Portuguese= + Text Portuguese= + Text Portuguese=Pressionar o botão Terminar para sair desta instalação + Text Portuguese= + Text Spanish=%APPTITLE% se ha instalado con éxito. + Text Spanish= + Text Spanish= + Text Spanish=Pulse el botón de Finalizar para salir de esta instalación. + Text Spanish= + Text Italian=%APPTITLE% è stato installato. + Text Italian= + Text Italian= + Text Italian=Premi il pulsante Fine per uscire dal programma di installazione + Text Italian= + Text Danish=%APPTITLE% er nu installeret korrekt. + Text Danish= + Text Danish= + Text Danish=Klik på Afslut for at afslutte installationen. + Text Danish= + Text Dutch=%APPTITLE% is met succes geïnstalleerd. + Text Dutch= + Text Dutch= + Text Dutch=Druk op Klaar om deze installatie af te ronden. + Text Dutch= + Text Norwegian=Installasjonen av %APPTITLE% er suksessfull. + Text Norwegian= + Text Norwegian= + Text Norwegian=Trykk på Avslutt-tasten for å avslutte denne installasjonen. + Text Norwegian= + Text Swedish=Installationen av %APPTITLE% har lyckats. + Text Swedish= + Text Swedish= + Text Swedish=Tryck på Sluta för att gå ur installationsprogrammet. + Text Swedish= + end + item: Push Button + Control Name=BACK + Rectangle=128 185 170 199 + Variable=DIRECTION + Value=B + Create Flags=01010000000000010000000000000000 + Text=< &Back + Text French=<&Retour + Text German=<&Zurück + Text Portuguese=<&Retornar + Text Spanish=<&Retroceder + Text Italian=< &Indietro + Text Danish=<&Tilbage + Text Dutch=<&Terug + Text Norwegian=<&Tilbake + Text Swedish=< &Tillbaka + end + item: Set Control Attribute + Control Name=BACK + Operation=1 + end + item: Set Control Attribute + Control Name=CANCEL + Operation=1 + end + end +end +item: End Block +end +item: New Event + Name=Cancel +end +item: Include Script + Pathname=%_WISE_%\INCLUDE\rollback.wse +end diff --text -u 'xemacs-21.5.18/nt/xemacs.mak' 'xemacs-21.5.19/nt/xemacs.mak' Index: ./nt/xemacs.mak --- ./nt/xemacs.mak Tue Jun 1 08:41:30 2004 +++ ./nt/xemacs.mak Tue Feb 1 05:08:52 2005 @@ -1,7 +1,7 @@ # Makefile for Microsoft NMAKE -*- Makefile -*- # # Copyright (C) 1995 Board of Trustees, University of Illinois. -# Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003 Ben Wing. +# Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2004 Ben Wing. # Copyright (C) 1997, 1998, 2000 Jonathan Harris. # Copyright (C) 1995 Sun Microsystems, Inc. # Copyright (C) 1998 Free Software Foundation, Inc. @@ -206,6 +206,11 @@ # A little bit of adhockery. Default to use system malloc and # DLL version of the C runtime library when using portable # dumping. These are the optimal settings. +# +# NOTE: The various graphics libraries are generally compiled to use +# MSVCRT.DLL (the same that we use in USE_CRTDLL, more or less), so using +# this is a good thing. + !if !defined(USE_SYSTEM_MALLOC) USE_SYSTEM_MALLOC=$(USE_PORTABLE_DUMPER) !endif @@ -597,7 +602,7 @@ ########################### Determine generic includes/defines/flags. -INCLUDES=$(MSW_INCLUDES) -I$(NT)\inc -I$(SRC) +INCLUDES=-I$(NT)\inc -I$(SRC) $(MSW_INCLUDES) DEFINES=$(MSW_DEFINES) $(MULE_DEFINES) $(UNION_DEFINES) \ $(DUMPER_DEFINES) $(KKCC_DEFINES) $(MALLOC_DEFINES) \ @@ -906,7 +911,7 @@ # Minitar uses zlib so just use cdecl to simplify things $(BLDLIB_SRC)/minitar.exe : $(NT)/minitar.c - $(CCV) -I"$(ZLIB_DIR)" $(LIB_SRC_DEFINES) $(CFLAGS_CDECL_NO_LIB) $(LINK_DEPENDENCY_ARGS) "$(ZLIB_DIR)\zlib.lib" + $(CCV) -I"$(ZLIB_DIR)" $(LIB_SRC_DEFINES) $(CFLAGS_CDECL_NO_LIB) -MD $(LINK_DEPENDENCY_ARGS) "$(ZLIB_DIR)\zlib.lib" LIB_SRC_TOOLS = \ $(BLDLIB_SRC)/etags.exe \ @@ -957,7 +962,7 @@ {$(MANDIR)}.texi{$(INFODIR)}.info: cd $(MANDIR) - $(MAKEINFO) $** + $(MAKEINFO) $(**F) XEMACS_SRCS = \ $(MANDIR)\xemacs\abbrevs.texi \ @@ -1071,8 +1076,7 @@ $(MANDIR)\lispref\x-windows.texi INTERNALS_SRCS = \ - $(MANDIR)\internals\internals.texi \ - $(MANDIR)\internals\index.texi + $(MANDIR)\internals\internals.texi NEW_USERS_GUIDE_SRCS = \ $(MANDIR)\new-users-guide\custom1.texi \ @@ -1259,10 +1263,13 @@ oldnames.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib \ shell32.lib wsock32.lib netapi32.lib winmm.lib winspool.lib ole32.lib \ mpr.lib uuid.lib imm32.lib $(LIBC_LIB) -TEMACS_LFLAGS=-nologo $(LIBRARIES) $(DEBUG_FLAGS_LINK) \ +TEMACS_COMMON_LFLAGS=-nologo $(LIBRARIES) $(DEBUG_FLAGS_LINK) \ -base:0x1000000 -stack:0x800000 $(TEMACS_ENTRYPOINT) -subsystem:windows \ - -pdb:$(BLDSRC)\temacs.pdb -map:$(BLDSRC)\temacs.map \ -heap:0x00100000 -nodefaultlib $(PROFILE_FLAGS) setargv.obj +TEMACS_LFLAGS=$(TEMACS_COMMON_LFLAGS) \ + -pdb:$(BLDSRC)\temacs.pdb -map:$(BLDSRC)\temacs.map +XEMACS_LFLAGS=$(TEMACS_COMMON_LFLAGS) \ + -pdb:$(BLDSRC)\xemacs.pdb -map:$(BLDSRC)\xemacs.map ########################### Definitions for running temacs.exe/xemacs.exe @@ -1376,7 +1383,7 @@ # Make the resource section read/write since almost all of it is the dump # data which needs to be writable. This avoids having to copy it. link.exe @<< - $(TEMACS_LFLAGS) -section:.rsrc,rw -out:$(BLDSRC)\xemacs.exe $(TEMACS_OBJS) $(OUTDIR)\xemacs.res $(TEMACS_LIBS) $(OUTDIR)\dump-id.obj + $(XEMACS_LFLAGS) -section:.rsrc,rw -out:$(BLDSRC)\xemacs.exe $(TEMACS_OBJS) $(OUTDIR)\xemacs.res $(TEMACS_LIBS) $(OUTDIR)\dump-id.obj << -$(DEL) $(BLDSRC)\xemacs.dmp !endif @@ -1450,8 +1457,16 @@ @echo Installing in $(INSTALL_DIR) ... @echo PlaceHolder > PlaceHolder @$(COPY) $(SRCROOT)\PROBLEMS "$(INSTALL_DIR)\" + @$(COPY) $(SRCROOT)\BUGS "$(INSTALL_DIR)\" + @$(COPY) $(SRCROOT)\README "$(INSTALL_DIR)\" + @$(COPY) $(SRCROOT)\COPYING "$(INSTALL_DIR)\" + @$(COPY) $(SRCROOT)\Installation "$(INSTALL_DIR)\" @$(COPY) PlaceHolder "$(INSTALL_DIR)\lock\" -$(DEL) "$(INSTALL_DIR)\lock\PlaceHolder" +# @$(COPY) $(BLDLIB_SRC)\*.exe "$(INSTALL_DIR)\lib-src\" +# @$(COPY) $(BLDLIB_SRC)\DOC "$(INSTALL_DIR)\lib-src\" +# @$(COPY) $(CONFIG_VALUES) "$(INSTALL_DIR)\lib-src\" +# @$(COPY) $(BLDSRC)\xemacs.exe "$(INSTALL_DIR)\bin\" @$(COPY) $(BLDLIB_SRC)\*.exe "$(INSTALL_DIR)\$(EMACS_CONFIGURATION)\" @$(COPY) $(BLDLIB_SRC)\DOC "$(INSTALL_DIR)\$(EMACS_CONFIGURATION)" @$(COPY) $(CONFIG_VALUES) "$(INSTALL_DIR)\$(EMACS_CONFIGURATION)" diff --text -u 'xemacs-21.5.18/src/.gdbinit' 'xemacs-21.5.19/src/.gdbinit' Index: ./src/.gdbinit --- ./src/.gdbinit Sat Jul 19 05:07:05 2003 +++ ./src/.gdbinit Thu Oct 28 19:48:15 2004 @@ -225,7 +225,7 @@ # GDB's command language makes you want to ... -define ptype +define pptype set $type_ptr = ($arg0 *) $val print $type_ptr print *$type_ptr @@ -250,58 +250,58 @@ end else if $lrecord_type == lrecord_type_string - ptype Lisp_String + pptype Lisp_String else if $lrecord_type == lrecord_type_cons - ptype Lisp_Cons + pptype Lisp_Cons else if $lrecord_type == lrecord_type_symbol - ptype Lisp_Symbol + pptype Lisp_Symbol printf "Symbol name: %s\n", ((Lisp_String *)$type_ptr->name)->data_ else if $lrecord_type == lrecord_type_vector - ptype Lisp_Vector + pptype Lisp_Vector printf "Vector of length %d\n", $type_ptr->size #print *($type_ptr->data) @ $type_ptr->size else if $lrecord_type == lrecord_type_bit_vector - ptype Lisp_Bit_Vector + pptype Lisp_Bit_Vector else if $lrecord_type == lrecord_type_buffer pstructtype buffer else if $lrecord_type == lrecord_type_char_table - ptype Lisp_Char_Table + pptype Lisp_Char_Table else if $lrecord_type == lrecord_type_char_table_entry - ptype Lisp_Char_Table_Entry + pptype Lisp_Char_Table_Entry else if $lrecord_type == lrecord_type_charset - ptype Lisp_Charset + pptype Lisp_Charset else if $lrecord_type == lrecord_type_coding_system - ptype Lisp_Coding_System + pptype Lisp_Coding_System else if $lrecord_type == lrecord_type_color_instance - ptype Lisp_Color_Instance + pptype Lisp_Color_Instance else if $lrecord_type == lrecord_type_command_builder - ptype command_builder + pptype command_builder else if $lrecord_type == lrecord_type_compiled_function - ptype Lisp_Compiled_Function + pptype Lisp_Compiled_Function else if $lrecord_type == lrecord_type_console pstructtype console else if $lrecord_type == lrecord_type_database - ptype Lisp_Database + pptype Lisp_Database else if $lrecord_type == lrecord_type_device pstructtype device else if $lrecord_type == lrecord_type_event - ptype Lisp_Event + pptype Lisp_Event else if $lrecord_type == lrecord_type_extent pstructtype extent @@ -313,64 +313,64 @@ pstructtype extent_info else if $lrecord_type == lrecord_type_face - ptype Lisp_Face + pptype Lisp_Face else if $lrecord_type == lrecord_type_float - ptype Lisp_Float + pptype Lisp_Float else if $lrecord_type == lrecord_type_font_instance - ptype Lisp_Font_Instance + pptype Lisp_Font_Instance else if $lrecord_type == lrecord_type_frame pstructtype frame else if $lrecord_type == lrecord_type_glyph - ptype Lisp_Glyph + pptype Lisp_Glyph else if $lrecord_type == lrecord_type_gui_item - ptype Lisp_Gui_Item + pptype Lisp_Gui_Item else if $lrecord_type == lrecord_type_hash_table - ptype Lisp_Hash_Table + pptype Lisp_Hash_Table else if $lrecord_type == lrecord_type_image_instance - ptype Lisp_Image_Instance + pptype Lisp_Image_Instance else if $lrecord_type == lrecord_type_keymap - ptype Lisp_Keymap + pptype Lisp_Keymap else if $lrecord_type == lrecord_type_lcrecord_list pstructtype lcrecord_list else if $lrecord_type == lrecord_type_ldap - ptype Lisp_LDAP + pptype Lisp_LDAP else if $lrecord_type == lrecord_type_lstream pstructtype lstream else if $lrecord_type == lrecord_type_marker - ptype Lisp_Marker + pptype Lisp_Marker else if $lrecord_type == lrecord_type_opaque - ptype Lisp_Opaque + pptype Lisp_Opaque else if $lrecord_type == lrecord_type_opaque_ptr - ptype Lisp_Opaque_Ptr + pptype Lisp_Opaque_Ptr else if $lrecord_type == lrecord_type_popup_data - ptype popup_data + pptype popup_data else if $lrecord_type == lrecord_type_process - ptype Lisp_Process + pptype Lisp_Process else if $lrecord_type == lrecord_type_range_table - ptype Lisp_Range_Table + pptype Lisp_Range_Table else if $lrecord_type == lrecord_type_specifier - ptype Lisp_Specifier + pptype Lisp_Specifier else if $lrecord_type == lrecord_type_subr - ptype Lisp_Subr + pptype Lisp_Subr else if $lrecord_type == lrecord_type_symbol_value_buffer_local pstructtype symbol_value_buffer_local @@ -385,16 +385,16 @@ pstructtype symbol_value_varalias else if $lrecord_type == lrecord_type_timeout - ptype Lisp_Timeout + pptype Lisp_Timeout else if $lrecord_type == lrecord_type_toolbar_button pstructtype toolbar_button else if $lrecord_type == lrecord_type_tooltalk_message - ptype Lisp_Tooltalk_Message + pptype Lisp_Tooltalk_Message else if $lrecord_type == lrecord_type_tooltalk_pattern - ptype Lisp_Tooltalk_Pattern + pptype Lisp_Tooltalk_Pattern else if $lrecord_type == lrecord_type_weak_list pstructtype weak_list @@ -405,11 +405,23 @@ if $lrecord_type == lrecord_type_window_configuration pstructtype window_config else + if $lrecord_type == lrecord_type_fc_pattern + pstructtype fc_pattern + else + if $lrecord_type == lrecord_type_fc_objectset + pstructtype fc_objectset + else + if $lrecord_type == lrecord_type_fc_fontset + pstructtype fc_fontset + else echo Unknown Lisp Object type\n print $arg0 # Barf, gag, retch end end + end + end + end end end end diff --text -u 'xemacs-21.5.18/src/ChangeLog' 'xemacs-21.5.19/src/ChangeLog' Index: ./src/ChangeLog --- ./src/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./src/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,3 +1,2363 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + +2005-02-04 Vin Shelton <acs@xemacs.org> + + * lread.c (check_if_suppressed, check_if_suppressed): + EXTERNAL_LIST_LOOP_2 declares variables and must be enclosed in + braces. Thanks, Fabrice. + +2005-02-03 David Evers <extsw@appliedgenerics.com> + + * process-unix.c (unix_send_process): Flush the last chunk, even + when the pipe is blocked. + +2005-02-03 Ben Wing <ben@xemacs.org> + + * dumper.c: + * dumper.c (pdump_file_try): + * dumper.c (DUMP_SLACK): + * dumper.c (pdump_load): + Include extra DUMP_SLACK when allocating space for exe path. + + * glyphs-eimage.c: + Reformat comment. + + * sysproc.h: + Delete out-of-date comment about abort. + +2005-02-03 Jerry James <james@xemacs.org> + + * dumper.c (pdump_load_finish): Cast to Rawbyte * instead of char *. + +2005-02-03 Jerry James <james@xemacs.org> + + * config.h.in: Remove #define this c_this. + * device-x.c (construct_name_list): Rename this -> this_widget. + * eval.c (wants_debugger): Rename this -> curr. + * frame.c (delete_frame_internal): Rename this -> this_frame. + * gui-gtk.c (ungcpro_popup_callbacks): Rename this -> this_callback. + * gui-gtk.c (get_gcpro_popup_callbacks): Ditto. + * gui-x.c (gcpro_popup_callbacks): Ditto. + * gui-x.c (ungcpro_popup_callbacks): Ditto. + * lisp.h: Remove #undef this and #defin this c_this. + * redisplay.c (generate_fstring_runes): Rename this -> this_str. + +2005-02-01 Jerry James <james@xemacs.org> + + * dumper.c: Olivier Galibert's changes to enable dumping data via + a Java-like serialization/deserialization process. + + * number.c: OG's bignum conversion functions. Also, use the + dumping capability to initialize bigfloat-max-prec sanely. + + * alloc.c: + * buffer.c: + * bytecode.c: + * console.c: + * data.c: + * device.c: + * elhash.c: + * eval.c: + * events.c: + * extents.c: + * file-coding.c: + * frame.c: + * glyphs.c: + * lstream.c: + * marker.c: + * mule-charset.c: + * mule-coding.c: + * objects.c: + * profile.c: + * rangetab.c: + * redisplay.c: + * specifier.c: + * unicode.c: + * window.c: + Add curly braces to the data2 arg of each memory_description + initializer. Add a union member name to each reference to data2. + + * lrecord.h: Ditto. OG changes to add and document + XD_OPAQUE_PTR_CONVERTIBLE and XD_OPAQUE_DATA_CONVERTIBLE. Add + memory_contents_description to solve pointer aliasing problems. + +2005-02-02 Ben Wing <ben@xemacs.org> + + * lread.c: + * lread.c (check_if_suppressed): + * lread.c (Fload_internal): + * lread.c (locate_file_in_directory_mapper): + * lread.c (readevalloop): + * lread.c (syms_of_lread): + * lread.c (vars_of_lread): + * lisp.h: + Remove undeeded Vload_file_name_internal_the_purecopy, + Qload_file_name -- use internal_bind_lisp_object instead of + specbind. + + Add load-suppress-alist. + +2005-02-02 Ben Wing <ben@xemacs.org> + + * menubar.c: + * menubar.c (Fcompare_menu_text): + New fun to compare menu itext as if the two were normalized. + + * menubar.c (Fnormalize_menu_text): + * menubar.c (syms_of_menubar): + Rename; there are no external callers of this function. + Remove unneeded BUFFER argument. Don't downcase. + (This will be done in compare-menu-text.) + Document that return value may be same string. + +2003-02-15 Ben Wing <ben@xemacs.org> + + * syswindows.h: Define W32API_2_2 for w32api.h v2.2 or higher. + Use it when defining a missing structure that is present in this + version of w32api.h. + * event-msw.c (mswindows_wnd_proc): Conditionalize bug fix on + !W32API_2_2. + +2005-01-31 Ben Wing <ben@xemacs.org> + + * emacs.c: + Define assert_failed() always. + * lisp.h: + Always define ABORT(). + +2005-01-29 Ben Wing <ben@xemacs.org> + + * alloc.c (garbage_collect_1): + * backtrace.h: + * bytecode.c (execute_rare_opcode): + * cmdloop.c: + * cmdloop.c (initial_command_loop): + * cmdloop.c (Frecursive_edit): + * cmdloop.c (call_command_loop): + * eval.c: + * eval.c (call_debugger): + * eval.c (Fcatch): + * eval.c (internal_catch): + * eval.c (throw_or_bomb_out): + * eval.c (condition_case_1): + * eval.c (maybe_get_trapping_problems_backtrace): + * eval.c (flagged_a_squirmer): + * eval.c (issue_call_trapping_problems_warning): + * eval.c (call_trapping_problems): + * lisp.h: + * macros.c (Fexecute_kbd_macro): + Also include a backtrace when we catch an attempt to throw outside + of a function where call_trapping_problems() has been used. + +2005-01-29 Ben Wing <ben@xemacs.org> + + * file-coding.c (snarf_coding_system): + Use UExtbyte for semantic correctness. + * file-coding.c (look_for_coding_system_magic_cookie): + Fix code that recognizes ;;;###coding cookie. + +2005-01-27 Ben Wing <ben@xemacs.org> + + * console-impl.h (struct console_methods): + * objects-gtk.c: + * objects-gtk.c (gtk_color_list): + * objects-gtk.c (gtk_font_list): + * objects-gtk.c (console_type_create_objects_gtk): + * objects-gtk.c (__gtk_font_list_internal): + * objects-msw.c: + * objects-msw.c (mswindows_font_list): + * objects-msw.c (mswindows_find_charset_font): + * objects-msw.c (mswindows_color_list): + * objects-msw.c (syms_of_objects_mswindows): + * objects-msw.c (console_type_create_objects_mswindows): + * objects-tty.c (tty_color_list): + * objects-tty.c (tty_font_list): + * objects-tty.c (syms_of_objects_tty): + * objects-tty.c (console_type_create_objects_tty): + * objects-x.c: + * objects-x.c (x_color_list): + * objects-x.c (x_font_list): + * objects-x.c (console_type_create_objects_x): + * objects.c: + * objects.c (Fcolor_list): + * objects.c (Ffont_list): + * objects.c (syms_of_objects): + list-fonts->font-list. Create color-list. Abstract out + x/msw-specific versions and obsolete the x/msw-specific Lisp + functions. + +2005-01-27 Ben Wing <ben@xemacs.org> + + * nt.c: + * fileio.c: + Fix sync comments. + + * config.h.in: + * dired-msw.c (mswindows_get_files): + * emacs.c (main_1): + * event-msw.c (mswindows_wnd_proc): + * fileio.c: + * fileio.c (find_end_of_directory_component): + * fileio.c (Ffile_name_directory): + * fileio.c (Ffile_name_as_directory): + * fileio.c (if): + * fileio.c (Ffile_truename): + * fileio.c (Ffile_readable_p): + * fileio.c (Ffile_symlink_p): + * fileio.c (Ffile_accessible_directory_p): + * fileio.c (vars_of_fileio): + * glyphs.c: + * glyphs.c (pixmap_to_lisp_data): + * lisp.h: + * nt.c: + * nt.c (get_long_basename): + * nt.c (get_cached_volume_information): + * nt.c (mswindows_readdir): + * nt.c (open_unc_volume): + * nt.c (mswindows_access): + * nt.c (mswindows_link): + * nt.c (mswindows_rename): + * nt.c (mswindows_unlink): + * nt.c (mswindows_stat): + * nt.c (mswindows_utime): + * nt.c (open_input_file): + * nt.c (open_output_file): + * nt.c (Fmswindows_short_file_name): + * nt.c (init_nt): + * process-nt.c (nt_create_process): + * realpath.c: + * realpath.c (readlink_or_correct_case): + * realpath.c (qxe_realpath): + * sound.c (Fplay_sound_file): + * symsinit.h: + * sysdep.c: + * sysdep.c (qxe_lstat): + * sysdep.c (qxe_stat): + * sysfile.h: + * syswindows.h: + * syswindows.h (LOCAL_FILE_FORMAT_TO_TSTR): + * syswindows.h (LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR): + * win32.c: + * win32.c (Fmswindows_shell_execute): + * win32.c (struct read_link_hash): + * win32.c (mswindows_read_link_1): + * win32.c (mswindows_read_link): + * win32.c (vars_of_win32): + * win32.c (init_win32): + Add support for treating shortcuts under Windows as symbolic links. + Enabled with mswindows-shortcuts-are-links (t by default). Rewrite + lots of places to use PATHNAME_CONVERT_OUT, which is moved to + sysfile.h. Add PATHNAME_RESOLVE_LINKS, which only does things + under Windows. + + Add profiling section for expand_file_name calls. + + * nt.c (mswindows_rename): + * nt.c (mswindows_unlink): + * sysdep.c (sys_subshell): + Unicode-ize. + + * realpath.c (readlink_or_correct_case): + Renamed from readlink_and_correct_case. Fix some problems with + Windows implementation due to incorrect understanding of workings + of the function. + + * sound.c (Fplay_sound_file): + * ntplay.c (nt_play_sound_file): + * sound.c: + * sound.h: + Rename play_sound_file to nt_play_sound_file and pass + internally-formatted data to it to avoid converting out and back + again. + + * text.h: + is_c -> is_ascii. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * free-hook.c (check_free): + Fix aliasing warning. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * redisplay.c: + * redisplay.c (generate_displayable_area): + * redisplay.c (regenerate_window): + * redisplay.h: + * signal.c: + * signal.c (check_quit): + Move backtraces to internals manual. Fix some race conditions + leading to crashes due to incomplete protection of critical + sections. In signal.c, be more aggressive in catching incomplete + critical section protection -- we cannot even check for QUIT, + *EVER*, in a critical section. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * emacs.c: + Update history section. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * lisp.h: + Clean up and generalize creation of string hash tables. + Use Hashcode rather than unsigned long. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * emacs-marshals.c: + * emacs-marshals.c (initialize_marshaller_storage): + * hash.c: + * hash.c (string_equal): + * hash.c (make_hash_table): + * hash.h: + * ui-gtk.c (type_already_imported_p): + Clean up and generalize creation of string hash tables. + + * ui-gtk.c (emacs_gtk_boxed_hash): + * elhash.h: + * gccache-gtk.c (gc_cache_hash): + * glyphs-gtk.c (gtk_image_instance_hash): + * lrecord.h (struct lrecord_implementation): + * marker.c (marker_hash): + * objects-gtk.c (gtk_color_instance_hash): + * objects-msw.c (mswindows_color_instance_hash): + * objects-tty.c (tty_color_instance_hash): + * objects-x.c (x_color_instance_hash): + * objects.c (color_instance_hash): + * objects.c (font_instance_hash): + * opaque.c (hash_opaque): + * opaque.c (hash_opaque_ptr): + * rangetab.c (range_table_entry_hash): + * rangetab.c (range_table_hash): + * specifier.c (specifier_hash): + * specifier.h (struct specifier_methods): + * xgccache.c (gc_cache_hash): + Use Hashcode rather than unsigned long. + +2005-01-26 Ben Wing <ben@xemacs.org> + + * profile.c: + * profile.c (vars_of_profile): + * profile.h: + Add fillers for easier temporary profiling. + Add RETURN_UNGCPRO_EXIT_PROFILING, RETURN_EXIT_PROFILING. + +2005-01-25 Ben Wing <ben@xemacs.org> + + * extents.c: + * extents.c (next_previous_single_property_change): + * extents.c (next_previous_single_property_change_fn): + * extents.c (syms_of_extents): + * extents.h: + * indent.c (last_visible_position): + * syntax.c (update_syntax_cache): + Implement next/previous-single-char-property-change and make + next/previous-single-property-change work like in FSF. + +2005-01-25 Ben Wing <ben@xemacs.org> + + * Makefile.in.in: + * Makefile.in.in (%.o): + Don't compile executable as Windows (-mwindows) under Cygwin. + Semi-recent changes to Cygwin's executable-startup handling make + it impossible to access the TTY this way. + + Don't use special linker file under Cygwin (cygwin.sc) except + when non-PDUMP (even in this case it is highly questionable); you + get errors like + + 1 [main] temacs 1364 fhandler_console::fixup_after_exec: error opening input console handle after exec, errno 13, Win32 error 5 + 5820 [main] temacs 1364 fhandler_console::fixup_after_exec: error opening output console handle after exec, errno 13, Win32 error 5 + +2005-01-24 Ben Wing <ben@xemacs.org> + + * bytecode.c (optimize_compiled_function): + * print.c (ONE_DIGIT): + Add casts to avoid warning. + + * compiler.h: + Add MSC_VERSION and include definitions of DOESNT_RETURN and + friends here, like for GCC. Need different definitions for VC7 + and VC6. + + * s/windowsnt.h: + Remove stuff moved to compiler.h. Disable warning 4646 ("function + declared with __declspec(noreturn) has non-void return type") + on VC7 since lots of Lisp primitives trigger this and there is + no easy way to kludge around the warning. + + * glyphs-eimage.c: + Some really nasty hacks to allow TIFF and JPEG to both be compiled. + #### The better solution is to move the TIFF and JPEG code to + different files. + + * glyphs-msw.c (mswindows_xbm_instantiate): + Define __STDC__ to avoid problems with compface.h. + + * intl-auto-encap-win32.c (qxeImmGetCandidateListCount): + * intl-auto-encap-win32.c (qxeFindResourceEx): + * intl-auto-encap-win32.h: + * intl-encap-win32.c: + * intl-encap-win32.c (qxeImmGetCompositionFont): + * syswindows.h: + Those wankers at Microsoft cannot leave well enough alone. + Various functions change parameter types semi-randomly between + VC6 and VC7, so we need to include our own versions that + can handle both kinds with appropriate casting. + + * EmacsFrame.c (EmacsFrameRecomputeCellSize): + * EmacsShell-sub.c: + * EmacsShell-sub.c (ABORT): + * EmacsShell-sub.c (SuperClassRootGeometryManager): + * EmacsShell-sub.c (RootGeometryManager): + * EmacsShell.c: + * EmacsShell.c (ABORT): + * EmacsShell.c (EmacsShellUpdateSizeHints): + * alloc.c: + * alloc.c (very_old_free_lcrecord): + * alloc.c (lispdesc_indirect_count_1): + * alloc.c (lispdesc_one_description_line_size): + * alloc.c (lispdesc_block_size_1): + * alloc.c (kkcc_marking): + * alloca.c (i00afunc): + * buffer.c (delete_from_buffer_alist): + * buffer.c (MARKED_SLOT): + * bytecode.c (execute_rare_opcode): + * bytecode.c (optimize_byte_code): + * bytecode.c (Ffetch_bytecode): + * charset.h: + * chartab.c (char_table_type_to_symbol): + * chartab.c (decode_char_table_range): + * chartab.c (encode_char_table_range): + * chartab.c (Freset_char_table): + * chartab.c (get_range_char_table_1): + * chartab.c (check_valid_char_table_value): + * chartab.c (map_char_table): + * chartab.c (chartab_instantiate): + * cm.c (cmcheckmagic): + * console-stream.c (stream_window_output_begin): + * console-stream.c (stream_window_output_end): + * console-stream.c (stream_frame_output_begin): + * console-stream.c (stream_frame_output_end): + * console-stream.c (stream_output_display_block): + * console-stream.c (stream_clear_region): + * console.c (get_console_variant): + * console.c (MARKED_SLOT): + * data.c (finish_marking_weak_lists): + * data.c (encode_weak_list_type): + * debug.h (DASSERT): + * device-msw.c (mswindows_get_default_margin): + * device-tty.c (tty_init_device): + * device-x.c (get_device_from_display): + * device-x.c (x_get_visual_depth): + * doprnt.c (parse_doprnt_spec): + * doprnt.c (get_doprnt_args): + * dumper.c (pdump_unsupported_dump_type): + * dumper.c (pdump_bump_depth): + * dynarr.c (stack_like_free): + * elhash.c (print_hash_table): + * elhash.c (make_standard_lisp_hash_table): + * elhash.c (hash_table_instantiate): + * emacs.c: + * emacs.c (sort_args): + * emacs.c (main): + * emacs.c (Fforce_debugging_signal): + * emacs.c (assert_failed): + * eval.c (throw_or_bomb_out): + * eval.c (Fsignal): + * eval.c (vars_of_eval): + * event-Xt.c (emacs_Xt_mapping_action): + * event-Xt.c (Xt_process_to_emacs_event): + * event-gtk.c (gtk_process_to_emacs_event): + * event-msw.c (mswindows_need_event): + * event-msw.c (mswindows_wnd_proc): + * event-msw.c (emacs_mswindows_format_magic_event): + * event-stream.c (Fadd_timeout): + * event-stream.c (Fadd_async_timeout): + * event-stream.c (execute_internal_event): + * event-stream.c (Frecent_keys): + * event-stream.c (extract_this_command_keys_nth_mouse_event): + * event-stream.c (lookup_command_event): + * events.c (mark_event): + * events.c (event_equal): + * events.c (event_hash): + * events.c (Fmake_event): + * events.c (Fdeallocate_event): + * events.c (event_chain_find_previous): + * events.c (event_to_character): + * events.c (format_event_object): + * events.c (Fevent_type): + * events.c (event_pixel_translation): + * events.c (Fevent_properties): + * extents.c (extent_in_region_p): + * extents.c (print_extent): + * extents.c (process_extents_for_insertion_mapper): + * extents.c (glyph_layout_to_symbol): + * faces.c (face_validate): + * file-coding.c (eol_type_to_symbol): + * file-coding.c (subsidiary_coding_system): + * file-coding.c (chain_conversion_end_type): + * file-coding.c (convert_eol_print): + * file-coding.c (convert_eol_getprop): + * file-coding.c (convert_eol_canonicalize_after_coding): + * file-coding.c (coding_category_id_to_symbol): + * file-coding.c (detection_result_number_to_symbol): + * fileio.c: + * fns.c (concat): + * fns.c (Fsubseq): + * fns.c (mapcar1): + * fns.c (Fbase64_encode_region): + * fns.c (Fbase64_encode_string): + * fns.c (Fbase64_decode_region): + * fns.c (Fbase64_decode_string): + * font-lock.c (find_context): + * font-lock.c (context_to_symbol): + * frame-gtk.c (gtk_set_frame_pointer): + * frame-gtk.c (gtk_update_frame_external_traits): + * frame-x.c (x_wm_mark_shell_size_user_specified): + * frame-x.c (x_wm_mark_shell_position_user_specified): + * frame-x.c (x_wm_set_shell_iconic_p): + * frame-x.c (x_wm_set_cell_size): + * frame-x.c (x_wm_set_variable_size): + * frame-x.c (x_wm_store_class_hints): + * frame-x.c (x_wm_maybe_store_wm_command): + * frame-x.c (x_initialize_frame_size): + * frame-x.c (x_update_frame_external_traits): + * frame.c: + * frame.c (delete_frame_internal): + * frame.c (mouse_pixel_position_1): + * frame.c (change_frame_size_1): + * free-hook.c (check_free): + * free-hook.c (check_realloc): + * free-hook.c (note_block_input): + * free-hook.c (log_gcpro): + * gccache-gtk.c (gc_cache_lookup): + * glyphs-eimage.c (tiff_memory_write): + * glyphs-gtk.c (gtk_finalize_image_instance): + * glyphs-gtk.c (init_image_instance_from_gdk_pixmap): + * glyphs-gtk.c (init_image_instance_from_xbm_inline): + * glyphs-gtk.c (gtk_xpm_instantiate): + * glyphs-gtk.c (gtk_unmap_subwindow): + * glyphs-gtk.c (gtk_map_subwindow): + * glyphs-gtk.c (gtk_button_redisplay): + * glyphs-msw.c: + * glyphs-msw.c (init_image_instance_from_xbm_inline): + * glyphs-x.c (init_image_instance_from_xbm_inline): + * glyphs-x.c (extract_xpm_color_names): + * glyphs-x.c (x_xpm_instantiate): + * glyphs.c (get_image_instantiator_governing_domain): + * glyphs.c (print_image_instance): + * glyphs.c (image_instance_equal): + * glyphs.c (image_instance_hash): + * glyphs.c (encode_image_instance_type): + * glyphs.c (inherit_instantiate): + * glyphs.c (image_instantiate): + * glyphs.c (allocate_glyph): + * glyphs.c (Fglyph_type): + * glyphs.c (display_table_entry): + * gtk-glue.c (xemacs_list_to_gtklist): + * gtk-glue.c (xemacs_gtklist_to_list): + * gtk-glue.c (xemacs_list_to_array): + * gutter.c (SET_GUTTER_WAS_VISIBLE_FLAG): + * gutter.c (gutter_was_visible): + * gutter.c (get_gutter_coords): + * input-method-xlib.c (get_XIM_input): + * insdel.c (move_gap): + * intl-win32.c (determine_code_page): + * intl-win32.c (mswindows_multibyte_to_unicode_getprop): + * intl-win32.c (mswindows_multibyte_convert): + * keymap.c (keymap_lookup_directly): + * keymap.c (keymap_delete_inverse_internal): + * keymap.c (ensure_meta_prefix_char_keymapp): + * keymap.c (accessible_keymaps_mapper_1): + * keymap.c (where_is_recursive_mapper): + * lisp.h: + * lisp.h (ABORT): + * lisp.h (assert): + * lread.c (read_atom): + * lstream.c (Lstream_delete): + * lstream.c (Lstream_really_write): + * lstream.c (make_lisp_buffer_stream_1): + * macros.c (pop_kbd_macro_event): + * malloc.c (malloc): + * malloc.c (free): + * menubar-gtk.c (menu_descriptor_to_widget_1): + * menubar-gtk.c (menu_create_menubar): + * menubar-msw.c (prune_menubar): + * menubar-x.c (set_frame_menubar): + * mule-coding.c (charset_by_attributes_or_create_one): + * mule-coding.c (parse_iso2022_esc): + * mule-coding.c (iso2022_encode): + * native-gtk-toolbar.c (SET_TOOLBAR_WAS_VISIBLE_FLAG): + * number.c: + * number.c (get_number_type): + * objects-msw.c (mswindows_list_fonts): + * objects.c (color_instantiate): + * objects.c (font_instantiate): + * objects.c (face_boolean_instantiate): + * print.c (printing_major_badness): + * process-nt.c (nt_send_process): + * process-unix.c (unix_send_process): + * process.c (get_process): + * ralloc.c (obtain): + * ralloc.c (relinquish): + * ralloc.c (relocate_blocs): + * ralloc.c (resize_bloc): + * ralloc.c (r_alloc_free): + * ralloc.c (r_re_alloc): + * ralloc.c (r_alloc_thaw): + * ralloc.c (init_ralloc): + * ralloc.c (Free_Addr_Block): + * ralloc.c (r_alloc): + * rangetab.c (range_table_type_to_symbol): + * rangetab.c (print_range_table): + * rangetab.c (rangetab_instantiate): + * redisplay-gtk.c (gtk_output_display_block): + * redisplay-msw.c (mswindows_output_display_block): + * redisplay-output.c (get_next_display_block): + * redisplay-output.c (get_cursor_size_and_location): + * redisplay-output.c (redisplay_output_layout): + * redisplay-output.c (redisplay_clear_region): + * redisplay-tty.c (tty_output_display_block): + * redisplay-x.c (x_output_display_block): + * redisplay.c (add_propagation_runes): + * redisplay.c (add_glyph_rune): + * redisplay.c (add_margin_runes): + * redisplay.c (create_left_glyph_block): + * redisplay.c (create_right_glyph_block): + * redisplay.c (regenerate_window): + * redisplay.c (REGEN_INC_FIND_START_END): + * redisplay.c (point_in_line_start_cache): + * regex.c: + * regex.c (ABORT): + * regex.c (re_compile_fastmap): + * regex.c (re_match_2_internal): + * regex.c (regerror): + * scrollbar-gtk.c (gtk_scrollbar_loop): + * scrollbar-gtk.c (scrollbar_cb): + * scrollbar-x.c (x_update_scrollbar_instance_status): + * scrollbar-x.c (x_scrollbar_loop): + * search.c (search_command): + * search.c (Fmatch_data): + * select-x.c (motif_clipboard_cb): + * signal.c: + * signal.c (qxe_setitimer): + * signal.c (interrupt_signal): + * specifier.c (specifier_add_spec): + * specifier.c (specifier_instance): + * specifier.h: + * strftime.c (add_num_time_t): + * sunplay.c (init_device): + * symbols.c (do_symval_forwarding): + * symbols.c (store_symval_forwarding): + * symbols.c (Fset): + * symbols.c (Fbuilt_in_variable_type): + * symbols.c (handler_type_from_function_symbol): + * sysdep.c (init_baud_rate): + * sysproc.h: + * text.c: + * text.c (charbpos_to_bytebpos_func): + * text.c (bytebpos_to_charbpos_func): + * text.c (new_dfc_convert_now_damn_it): + * text.h: + * toolbar-common.c (__INTERNAL_MAPPED_P): + * toolbar-common.c (SET_TOOLBAR_WAS_VISIBLE_FLAG): + * toolbar-msw.c (SET_TOOLBAR_WAS_VISIBLE_FLAG): + * toolbar.c (get_toolbar_coords): + * ui-gtk.c (build_gtk_boxed): + * ui-gtk.c (describe_gtk_arg): + * ui-gtk.c (gtk_type_to_lisp): + * ui-gtk.c (lisp_to_gtk_type): + * ui-gtk.c (lisp_to_gtk_ret_type): + * ui-gtk.c (lisp_to_flag): + * unexnt.c (read_in_bss): + * unexnt.c (map_in_heap): + * unicode.c: + * unicode.c (create_new_from_unicode_table): + * unicode.c (sledgehammer_check_from_table): + * unicode.c (sledgehammer_check_to_table): + * unicode.c (set_unicode_conversion): + * unicode.c (unicode_to_ichar): + * unicode.c (encode_unicode_char_1): + * unicode.c (unicode_convert): + * unicode.c (unicode_getprop): + * win32.c (mswindows_lisp_error_1): + * window.c (real_window): + * window.c (window_display_lines): + * window.c (window_display_buffer): + * window.c (set_window_display_buffer): + * window.c (unshow_buffer): + * window.c (window_loop): + * window.c (Fget_lru_window): + * xgccache.c (gc_cache_lookup): + * s/windowsnt.h: + + abort() -> ABORT(). Eliminate preprocessor games with abort() + since it creates huge problems in VC7, solvable only by including + massive amounts of files in every compile (and not worth it). + +2005-01-21 Robert Royar <xemacs@frinabulax.org> + + * database.c: Repair typo in NetBSD fix. + +2005-01-21 Malcolm Purvis <malcolmp@xemacs.org> + + * database.c (dbm_type): + * database.c (dbm_subtype): Mark parameters as unused. + +2005-01-21 Aidan Kehoe <kehoea@parhasard.net> + + * database.c: Small warning fix for NetBSD, w.r.t. u_int_8_t being + redefined. + +2005-01-20 Malcolm Purvis <malcolmp@xemacs.org> + + * event-gtk.c: Recognise AltGr as a valid modifier. + +2005-01-12 Ville Skyttä <scop@xemacs.org> + + * console-x.h: #include X11/keysym.h before xintrinsic.h. + +2005-01-06 Zajcev Evgeny <zevlg@yandex.ru> + + * scrollbar.c (compute_scrollbar_instance_usage): + Only call device method compute_scrollbar_instance_usage() if it + is defined. + +2004-12-15 Stephen J. Turnbull <stephen@xemacs.org> + + * EmacsManager.c (EmacsManagerChangeSize): Respect XtGeometryNo. + +2004-12-07 Malcolm Purvis <malcolmp@xemacs.org> + + * Makefile.in.in: Always refer to make as $(MAKE) and use + $(RECURSIVE_MAKE_ARGS) for other parameters. This allows -j to + work in GNU Make while removing need for POSIX compatible make on + all systems. + +2004-12-06 Ben Wing <ben@xemacs.org> + + * rangetab.c (rangetab_instantiate): + Fix compile error. + +2004-12-05 Ben Wing <ben@xemacs.org> + + * elhash.c: + * elhash.c (find_htentry): + * elhash.c (inchash_eq): + * elhash.h: + * profile.c (create_profile_tables): + * profile.c (profile_record_consing): + * profile.c (profile_record_about_to_call): + Create inchash_eq() to allow direct incrementing of hash-table + entry. Use in profile.c to try to reduce profiling overhead. + Increase initial size of profile hash tables to reduce profiling + overhead. + + * buffer.c (init_initial_directory): + * device-msw.c (mswindows_handle_page_setup_dialog_box): + * dialog-msw.c (handle_directory_proc): + * dialog-msw.c (handle_file_dialog_box): + * dialog-msw.c: + * dired-msw.c (mswindows_format_file): + * dired-msw.c (mswindows_get_files): + * editfns.c (Ftemp_directory): + * event-msw.c (mswindows_wnd_proc): + * events.c (format_event_object): + * glyphs-msw.c (add_tab_item): + * glyphs-msw.c (add_tree_item): + * keymap.c (Fsingle_key_description): + * keymap.c (format_raw_keys): + * objects-msw.c (parse_font_spec): + * process-nt.c (nt_create_process): + * syswindows.h (build_tstr_string): + * syswindows.h (qxetcslen): + * text.c (eicmp_1): + * text.h (eicat_ascii): + * text.h (eicmp_ascii): + * text.h (eicpy_ascii): + * text.h (eicpy_ascii_len): + * text.h (eistr_ascii): + * text.h (eisub_ascii): + * text.h: + * unexnt.c (_start): + Rename xetcs* -> qxetcs* for consistency with qxestr*. + Rename ei*_c(_*) -> ei*_ascii(_*) since they work with ASCII-only + strings not "C strings", whatever those are. This is the last + place where "c" was incorrectly being used for "ascii". + + * dialog-msw.c (handle_directory_proc): + * dialog-msw.c (handle_directory_dialog_box): + * dumper.c: + * event-msw.c (mswindows_wnd_proc): + * fileio.c (Ffile_truename): + * glyphs-gtk.c (font_instantiate): + * glyphs-x.c (font_instantiate): + * nt.c (Fmswindows_short_file_name): + * nt.c (mswindows_link): + * process-nt.c (nt_create_process): + * realpath.c (readlink_and_correct_case): + * realpath.c (qxe_realpath): + * sysdep.c (qxe_allocating_getcwd): + * sysfile.h: + * unexcw.c (unexec): + * unexnext.c (unexec): + * unexnt.c (_start): + Try to avoid differences in systems that do or do not include + final null byte in PATH_MAX. Create PATH_MAX_INTERNAL and + PATH_MAX_EXTERNAL and use them everywhere. Rewrite code in + dumper.c to avoid use of PATH_MAX. When necessary in nt.c, + use _MAX_PATH instead of MAX_PATH to be consistent with + other places. + + * text.c (dfc_convert_to_internal_format): + Code to short-circuit when binary or Unicode was not working + due to EOL wrapping. Fix this code to work when either no + EOL autodetection or no CR's or LF's in the text. + + * lisp.h: + * rangetab.c: + * rangetab.c (range_table_symbol_to_type): + * rangetab.c (range_table_type_to_symbol): + * rangetab.c (print_range_table): + * rangetab.c (verify_range_table): + * rangetab.c (get_range_table): + * rangetab.c (Frange_table_type): + * rangetab.c (Fcopy_range_table): + * rangetab.c (put_range_table): + * rangetab.c (Fput_range_table): + * rangetab.c (Fremove_range_table): + * rangetab.c (rangetab_type_validate): + * rangetab.c (rangetab_instantiate): + * rangetab.c (syms_of_rangetab): + * rangetab.c (structure_type_create_rangetab): + * rangetab.h: + * rangetab.h (enum range_table_type): + * regex.c (vars_of_regex): + * search.c (vars_of_search): + Implement different types of ranges (open/closed start and end). + Change default to be start-closed, end-open. + +2004-11-12 Marcus Crestani <crestani@informatik.uni-tuebingen.de> + + * Makefile.in.in: Fix pdump build for Cygwin. + +2004-11-12 Ben Wing <ben@xemacs.org> + + * text.c (find_pos_of_existing_active_alloca_convert): + Two different occurrences of a string stringized from the exact + same parameter may not necessarily be the same string, so check + with strcmp. + +2004-11-12 Jerry James <james@xemacs.org> + + * lstream.c (Lstream_really_write): Don't call the flusher if the + writer returned an error. + +2004-11-11 Marcus Crestani <crestani@informatik.uni-tuebingen.de> + + * text.h: + * xemacs.def.in.in: rename new_dfc_convert_alloca to + new_dfc_convert_copy_data + +2004-11-07 Ben Wing <ben@xemacs.org> + + * frame-x.c (x_set_frame_properties): + Fix compile error. + +2004-10-27 Ben Wing <ben@xemacs.org> + + --------------------------------------------------------------- + MULE-RELATED WORK: + --------------------------------------------------------------- + + --------------------------- + byte-char conversion + --------------------------- + + * buffer.c: + * buffer.h (BUFFER_TEXT_LOOP): + * buffer.h (BYTE_BUF_CEILING_OF_IGNORE_ACCESSIBLE): + * buffer.h (BYTE_BUF_FLOOR_OF): + * buffer.h (NUM_CACHED_POSITIONS): + * buffer.h (struct buffer_text): + * buffer.h: + * insdel.c (BUF_GPT_ADDR): + * insdel.c (SET_BOTH_BUF_GPT): + * insdel.c (SET_BOTH_BUF_Z): + * insdel.c (buffer_delete_range): + * insdel.c (buffer_insert_string_1): + * insdel.c (gap_left): + * insdel.c (gap_right): + * insdel.c (init_buffer_text): + * insdel.c (make_gap): + * insdel.c (merge_gap_with_end_gap): + * insdel.c (move_gap): + * insdel.c: + * text.c (buffer_mule_signal_deleted_region): + * text.c (buffer_mule_signal_inserted_region): + * text.c (bytebpos_to_charbpos_func): + * text.c (charbpos_to_bytebpos_func): + * text.c (skip_ascii): + * text.c (skip_ascii_down): + Port FSF algorithm for byte-char conversion, replacing broken + previous version. Track the char position of the gap. Add + functions to do char-byte conversion downwards as well as upwards. + Move comments about algorithm workings to internals manual. + + --------------------------- + work on types + --------------------------- + + * alloc.c: + * alloc.c (gc_plist_hack): + * console-x-impl.h (struct x_frame): + * dump-data.c: + * dump-data.c (dumped_data_size): + * dump-data.c (dumped_data_max_size): + * dump-data.c (dumped_data_align_offset): + * dump-data.c (dumped_data_get): + * dump-data.h: + * dump-data.h (dumped_data_get): + * dumper.c: + * dumper.c (struct): + * dumper.c (PDUMP_READ): + * dumper.c (PDUMP_READ_ALIGNED): + * dumper.c (pdump_objects_unmark): + * dumper.c (pdump_register_sub): + * dumper.c (pdump_register_struct_contents): + * dumper.c (pdump_store_new_pointer_offsets): + * dumper.c (pdump_reloc_one): + * dumper.c (pdump_dump_root_struct_ptrs): + * dumper.c (pdump_dump_root_lisp_objects): + * dumper.c (pdump): + * dumper.c (pdump_load_check): + * dumper.c (pdump_load_finish): + * dialog-msw.c: + * dired-msw.c (mswindows_format_file): + * doc.c (get_doc_string): + * doc.c (Fsnarf_documentation): + * doc.c (kludgily_ignore_lost_doc_p): + * editfns.c: + * esd.c (esd_play_sound_data): + * event-gtk.h (emacs_shell_event_handler): + * event-msw.c (mswindows_dde_callback): + * events.c (format_event_object): + * file-coding.c (struct subsidiary_type): + * file-coding.c (setup_eol_coding_systems): + * file-coding.c (make_coding_system_1): + * file-coding.c (make_internal_coding_system): + * file-coding.h: + * fns.c (add_suffix_to_symbol): + * fns.c (add_prefix_to_symbol): + * glyphs-eimage.c (struct jpeg_unwind_data): + * glyphs-eimage.c (jpeg_instantiate_unwind): + * glyphs-eimage.c (jpeg_instantiate): + * glyphs-eimage.c (struct gif_unwind_data): + * glyphs-eimage.c (gif_instantiate_unwind): + * glyphs-eimage.c (gif_memory_storage): + * glyphs-eimage.c (gif_instantiate): + * glyphs-eimage.c (struct png_memory_storage): + * glyphs-eimage.c (struct png_unwind_data): + * glyphs-eimage.c (png_instantiate_unwind): + * glyphs-eimage.c (png_instantiate): + * glyphs-eimage.c (struct tiff_unwind_data): + * glyphs-eimage.c (tiff_instantiate_unwind): + * glyphs-eimage.c (tiff_memory_storage): + * glyphs-eimage.c (tiff_instantiate): + * glyphs-gtk.c (gtk_xpm_instantiate): + * glyphs-msw.c (convert_EImage_to_DIBitmap): + * glyphs-msw.c (mswindows_init_image_instance_from_eimage): + * glyphs-msw.c (set_mono_pixel): + * glyphs-msw.c (mswindows_initialize_image_instance_mask): + * glyphs-msw.c (xpm_to_eimage): + * glyphs-msw.c (mswindows_xpm_instantiate): + * glyphs-msw.c (xbm_create_bitmap_from_data): + * glyphs-msw.c (init_image_instance_from_xbm_inline): + * glyphs-msw.c (xbm_instantiate_1): + * glyphs-msw.c (mswindows_xbm_instantiate): + * glyphs-msw.c (mswindows_xface_instantiate): + * glyphs-shared.c (read_bitmap_data): + * glyphs-shared.c (read_bitmap_data_from_file): + * glyphs-x.c (convert_EImage_to_XImage): + * glyphs-x.c (x_init_image_instance_from_eimage): + * glyphs-x.c (pixmap_from_xbm_inline): + * glyphs-x.c (init_image_instance_from_xbm_inline): + * glyphs-x.c (xbm_instantiate_1): + * glyphs-x.c (x_xbm_instantiate): + * glyphs-x.c (x_xface_instantiate): + * glyphs.c (bitmap_to_lisp_data): + * glyphs.h: + * gui.c (gui_error): + * gui.c (gui_error_2): + * hpplay.c (player_error_internal): + * hpplay.c (play_sound_data): + * imgproc.c (get_histogram): + * imgproc.c (build_EImage_quantable): + * intl-win32.c (lang_to_langcode): + * intl-win32.c (sublang_to_langcode): + * intl-win32.c (int_from_hex): + * intl-win32.c (enum_locale_fn): + * lrecord.h (DECLARE_LRECORD): + * lrecord.h (DECLARE_MODULE_API_LRECORD): + * lrecord.h (DECLARE_EXTERNAL_LRECORD): + * lrecord.h (DECLARE_NONRECORD): + * lrecord.h (copy_sized_lcrecord): + * lrecord.h (zero_sized_lcrecord): + * lrecord.h (DUMPEDP): + * lstream.c (make_lisp_buffer_stream_1): + * keymap.c (define_key_check_and_coerce_keysym): + * lisp.h: + * libsst.c: + * linuxplay.c: + * linuxplay.c (linux_play_data_or_file): + * linuxplay.c (play_sound_data): + * miscplay.c: + * miscplay.c (waverequire): + * miscplay.c (parsewave): + * miscplay.c (parsesundecaudio): + * miscplay.c (sndcnv8U_2mono): + * miscplay.c (sndcnv8S_2mono): + * miscplay.c (sndcnv2monounsigned): + * miscplay.c (sndcnv2unsigned): + * miscplay.c (int2ulaw): + * miscplay.c (sndcnvULaw_2linear): + * miscplay.c (sndcnvULaw_2mono): + * miscplay.c (sndcnv16_2monoLE): + * miscplay.c (sndcnv16_2monoBE): + * miscplay.c (sndcnv2byteLE): + * miscplay.c (sndcnv2byteBE): + * miscplay.c (sndcnv2monobyteLE): + * miscplay.c (sndcnv2monobyteBE): + * miscplay.c (analyze_format): + * miscplay.h (parse_wave_complete): + * mule-coding.c (ccl_putprop): + * nas.c: + * nas.c (nas_play_sound_data): + * nas.c (SndOpenDataForReading): + * nas.c (cmpID): + * nas.c (dread): + * nas.c (dgetc): + * nas.c (readChunk): + * nas.c (WaveOpenDataForReading): + * nas.c (SoundOpenDataForReading): + * nt.c: + * nt.c (init_mswindows_environment): + * nt.c (mswindows_is_executable): + * nt.c (mswindows_executable_type): + * ntheap.c: + * ntheap.c (round_to_next): + * ntheap.c (get_data_start): + * ntheap.c (get_data_end): + * ntheap.c (allocate_heap): + * ntheap.c (sbrk): + * ntheap.c (recreate_heap): + * ntplay.c: + * ntplay.c (play_sound_file): + * ntplay.c (play_sound_data_1): + * ntplay.c (play_sound_data): + * objects-msw.c (colormap_t): + * objects-msw.c (fontmap_t): + * objects-msw.c (mswindows_string_to_color): + * objects-msw.c (mswindows_color_to_string): + * objects-msw.c (match_font): + * objects-msw.c (font_enum_callback_2): + * objects-msw.c (sort_font_list_function): + * objects-msw.c (parse_font_spec): + * objects-msw.c (mswindows_font_spec_matches_charset_stage_1): + * objects-tty.c (tty_initialize_font_instance): + * objects-x.c (x_font_instance_properties): + * print.c (printing_major_badness): + * process-nt.c (mswindows_compare_env): + * process-nt.c (get_internet_address): + * process.c: + * process.c (handle_signal): + * process.c (deactivate_process): + * redisplay.h: + * select-common.h (selection_data_to_lisp_data): + * select-common.h (lisp_data_to_selection_data): + * select-gtk.c (emacs_gtk_selection_handle): + * select-x.c (x_reply_selection_request): + * select-x.c (x_handle_selection_request): + * select-x.c (x_get_window_property): + * select-x.c (receive_incremental_selection): + * select-x.c (x_get_window_property_as_lisp_data): + * select-x.c (Fx_get_cutbuffer_internal): + * sgiplay.c: + * sgiplay.c (play_sound_file): + * sgiplay.c (play_sound_data): + * sgiplay.c (audio_initialize): + * sgiplay.c (play_internal): + * sgiplay.c (write_mulaw_8_chunk): + * sgiplay.c (write_linear_chunk): + * sgiplay.c (struct): + * sgiplay.c (parse_snd_header): + * sound.c: + * sound.c (report_sound_error): + * sound.c (Fplay_sound): + * sound.h: + * sunplay.c (init_device): + * sunplay.c (play_sound_file): + * sunplay.c (play_sound_data): + * sysfile.h: + * sysdep.c (retry_fopen): + * sysdep.c (qxe_fopen): + * sysdep.c (wcslen): + * syswindows.h (LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR): + * text.c (ascii_strcasecmp): + * text.c (qxestrcasecmp_ascii): + * text.c (ascii_strncasecmp): + * text.c (qxestrncasecmp_ascii): + * text.c (convert_ibyte_string_into_ichar_dynarr): + * text.c (convert_ibyte_string_into_ichar_string): + * text.c (eicmp_1): + * unexnt.c (unexec): + * unexnt.c (get_section_info): + * unexnt.c (copy_executable_and_dump_data_section): + * unexnt.c (dump_bss_and_heap): + * win32.c (urlify_filename): + * win32.c (mswindows_lisp_error_1): + * xgccache.c (gc_cache_lookup): + * text.c (qxesprintf): + Further work on types. This creates a full set of types for all + the basic semantics of `char' that I have so far identified, so that + its semantics can always be identified for the purposes of proper + Mule-safe code, and the raw use of `char' always avoided. + + (1) More type renaming, for consistency of naming. + + Char_ASCII -> Ascbyte + UChar_ASCII -> UAscbyte + Char_Binary -> CBinbyte + UChar_Binary -> Binbyte + SChar_Binary -> SBinbyte + + (2) Introduce Rawbyte, CRawbyte, Boolbyte, Chbyte, UChbyte, and + Bitbyte and use them. + + (3) New types Itext, Wexttext and Textcount for separating out + the concepts of bytes and textual units (different under UTF-16 + and UTF-32, which are potential internal encodings). + + (4) qxestr*_c -> qxestr*_ascii. + + * lisp.h (qxesscanf_ascii_1): + New; goes with other qxe() functions. #### Maybe goes in a + different section. + + * lisp.h: + Group generic int-type defs together with EMACS_INT defs. + + * lisp.h (EXTTEXT_ZTERM_SIZE): + * lisp.h (ITEXT_SIZE): + * lisp.h (NON_ASCII_INTERNAL_FORMAT): + * lisp.h (UTF16_IBYTE_FORMAT): + * lisp.h (WEXTTEXT_IS_WIDE) + New defns. + + * lisp.h (Boolean): + New type to replace places where int occurs as a boolean. + It's signed because occasionally people may want to use -1 as + an error value, and because unsigned ints are viral -- see comments + in the internals manual against using them. + + * dynarr.c: + * dynarr.c (Dynarr_realloc): + * dynarr.c (Dynarr_resize): + int -> Bytecount. + + --------------------------- + Mule-izing + --------------------------- + + * device-x.c: + * device-x.c (Fx_server_vendor): + * device-x.c (Fx_valid_keysym_name_p): + * device-x.c (Fx_get_font_path): + * device-x.c (Fx_set_font_path): + * device-x.c (reinit_console_type_create_device_x): + Partially Mule-ize. + + * dumper.c (see above): + * dumper.c (pdump_file_get): + * dumper.c (pdump_resource_get): + * dumper.c (pdump_file_free): + * dumper.c (pdump_ram_try): + * dumper.c (pdump_file_try): + * dumper.c (pdump_load): + * dumper.h: + Mule-ize. Use Rawbyte. Use stderr_out not printf. Use wext_*(). + + * sysdep.c: + * sysdep.c (retry_open_1): + * sysdep.c (retry_open): + * sysdep.c (wext_retry_open): + * syswindows.h: + * text.c (wcscmp_ascii): + * text.c (wcsncmp_ascii): + New Wexttext API for manipulation of external text that may be + Unicode (e.g. startup code under Windows). + + * emacs.c (make_arg_list_1): + * emacs.c (make_arg_list): + * emacs.c (make_argc_argv): + * emacs.c (free_argc_argv): + * emacs.c (init_cmdargs): + * emacs.c (argmatch): + * emacs.c (check_compatible_window_system): + * emacs.c (struct standard_args): + * emacs.c (sort_args): + * emacs.c (main): + * emacs.c (debug_can_access_memory): + * emacs.c (shut_down_emacs): + * emacs.c (guts_of_fatal_error_signal): + * emacs.c (assert_failed): + Mule-ize. Properly deal with argv in external encoding. + Use wext_*() and Wexttext. Use Rawbyte. + + #if 0 some old junk on SCO that is unlikely to be correct. + + Rewrite allocation code in run-temacs. + + * emacs.c: + * symsinit.h: + * win32.c (init_win32_very_very_early): + Rename win32 init function and call it even earlier, to + initialize mswindows_9x_p even earlier, for use in startup code + (XEUNICODE_P). + + * process.c (init_xemacs_process): + Use _wenviron not environ under Windows, to get Unicode environment + variables. + + * event-Xt.c (x_event_to_emacs_event): + Mule-ize drag-n-drop related stuff. + + * dragdrop.c (dnd_url_hexify_string): + * dragdrop.h: + * frame-x.c: + * frame-x.c (x_wm_set_cell_size): + * frame-x.c (x_wm_set_variable_size): + * frame-x.c (x_wm_hack_wm_protocols): + * frame-x.c (x_wm_store_class_hints): + * frame-x.c (x_wm_maybe_store_wm_command): + * frame-x.c (x_frame_window_state): + * frame-x.c (x_set_frame_text_value): + * frame-x.c (x_set_initial_frame_size): + * frame-x.c (x_set_frame_properties): + * frame-x.c (maybe_set_frame_title_format): + * frame-x.c (start_drag_internal_1): + * frame-x.c (x_cde_destroy_callback): + * frame-x.c (x_cde_convert_callback): + * frame-x.c (abort_current_drag): + * frame-x.c (Fcde_start_drag_internal): + * frame-x.c (x_cde_transfer_callback): + * frame-x.c (Foffix_start_drag_internal): + * frame-x.c (x_initialize_frame_size): + * frame-x.c (x_create_widgets): + * frame-x.c (xemacs_XtPopup): + * frame-x.c (x_popup_frame): + * frame-x.c (x_set_frame_icon): + * frame-x.c (x_set_frame_position): + * frame-x.c (x_delete_frame): + * frame-x.c (x_update_frame_external_traits): + Mule-ize. + + * text.h: + Add some more stand-in defines for particular kinds of conversion; + use in Mule-ization work in frame-x.c etc. + + --------------------------- + Freshening + --------------------------- + + * intl-auto-encap-win32.c: + * intl-auto-encap-win32.c (qxePeekConsoleInput): + * intl-auto-encap-win32.c (qxeReadConsoleInput): + * intl-auto-encap-win32.c (qxeWriteConsoleInput): + * intl-auto-encap-win32.c (qxeExtractAssociatedIcon): + * intl-auto-encap-win32.c (qxeShellExecuteEx): + * intl-auto-encap-win32.c (qxeSHQueryRecycleBin): + * intl-auto-encap-win32.c (qxeSHEmptyRecycleBin): + * intl-auto-encap-win32.c (qxeSHGetNewLinkInfo): + * intl-auto-encap-win32.c (qxeSHInvokePrinterCommand): + * intl-auto-encap-win32.c (qxewvsprintf): + * intl-auto-encap-win32.c (qxeLoadKeyboardLayout): + * intl-auto-encap-win32.c (qxeGetKeyboardLayoutName): + * intl-auto-encap-win32.c (qxeOpenDesktop): + * intl-auto-encap-win32.c (qxeEnumDesktops): + * intl-auto-encap-win32.c (qxeCreateWindowStation): + * intl-auto-encap-win32.c (qxeOpenWindowStation): + * intl-auto-encap-win32.c (qxeEnumWindowStations): + * intl-auto-encap-win32.c (qxeGetUserObjectInformation): + * intl-auto-encap-win32.c (qxeSetUserObjectInformation): + * intl-auto-encap-win32.c (qxeRegisterWindowMessage): + * intl-auto-encap-win32.c (qxeGetMessage): + * intl-auto-encap-win32.c (qxeDispatchMessage): + * intl-auto-encap-win32.c (qxePeekMessage): + * intl-auto-encap-win32.c (qxeSendMessageTimeout): + * intl-auto-encap-win32.c (qxeSendNotifyMessage): + * intl-auto-encap-win32.c (qxeSendMessageCallback): + * intl-auto-encap-win32.c (qxePostMessage): + * intl-auto-encap-win32.c (qxePostThreadMessage): + * intl-auto-encap-win32.c (qxeGetClassInfoEx): + * intl-auto-encap-win32.c (qxeCreateWindowEx): + * intl-auto-encap-win32.c (qxeCreateDialogParam): + * intl-auto-encap-win32.c (qxeCreateDialogIndirectParam): + * intl-auto-encap-win32.c (qxeDialogBoxParam): + * intl-auto-encap-win32.c (qxeDialogBoxIndirectParam): + * intl-auto-encap-win32.c (qxeSetDlgItemText): + * intl-auto-encap-win32.c (qxeGetDlgItemText): + * intl-auto-encap-win32.c (qxeSendDlgItemMessage): + * intl-auto-encap-win32.c (qxeCallMsgFilter): + * intl-auto-encap-win32.c (qxeRegisterClipboardFormat): + * intl-auto-encap-win32.c (qxeGetClipboardFormatName): + * intl-auto-encap-win32.c (qxeCharToOem): + * intl-auto-encap-win32.c (qxeOemToChar): + * intl-auto-encap-win32.c (qxeCharToOemBuff): + * intl-auto-encap-win32.c (qxeOemToCharBuff): + * intl-auto-encap-win32.c (qxeCharUpper): + * intl-auto-encap-win32.c (qxeCharUpperBuff): + * intl-auto-encap-win32.c (qxeCharLower): + * intl-auto-encap-win32.c (qxeCharLowerBuff): + * intl-auto-encap-win32.c (qxeCharNext): + * intl-auto-encap-win32.c (qxeCharPrev): + * intl-auto-encap-win32.c (qxeMapVirtualKey): + * intl-auto-encap-win32.c (qxeMapVirtualKeyEx): + * intl-auto-encap-win32.c (qxeLoadAccelerators): + * intl-auto-encap-win32.c (qxeCreateAcceleratorTable): + * intl-auto-encap-win32.c (qxeCopyAcceleratorTable): + * intl-auto-encap-win32.c (qxeTranslateAccelerator): + * intl-auto-encap-win32.c (qxeLoadMenu): + * intl-auto-encap-win32.c (qxeLoadMenuIndirect): + * intl-auto-encap-win32.c (qxeChangeMenu): + * intl-auto-encap-win32.c (qxeGetMenuString): + * intl-auto-encap-win32.c (qxeInsertMenu): + * intl-auto-encap-win32.c (qxeAppendMenu): + * intl-auto-encap-win32.c (qxeModifyMenu): + * intl-auto-encap-win32.c (qxeInsertMenuItem): + * intl-auto-encap-win32.c (qxeGetMenuItemInfo): + * intl-auto-encap-win32.c (qxeSetMenuItemInfo): + * intl-auto-encap-win32.c (qxeDrawText): + * intl-auto-encap-win32.c (qxeDrawTextEx): + * intl-auto-encap-win32.c (qxeGrayString): + * intl-auto-encap-win32.c (qxeDrawState): + * intl-auto-encap-win32.c (qxeTabbedTextOut): + * intl-auto-encap-win32.c (qxeGetTabbedTextExtent): + * intl-auto-encap-win32.c (qxeSetProp): + * intl-auto-encap-win32.c (qxeGetProp): + * intl-auto-encap-win32.c (qxeRemoveProp): + * intl-auto-encap-win32.c (qxeEnumPropsEx): + * intl-auto-encap-win32.c (qxeEnumProps): + * intl-auto-encap-win32.c (qxeSetWindowText): + * intl-auto-encap-win32.c (qxeGetWindowText): + * intl-auto-encap-win32.c (qxeGetWindowTextLength): + * intl-auto-encap-win32.c (qxeMessageBox): + * intl-auto-encap-win32.c (qxeMessageBoxEx): + * intl-auto-encap-win32.c (qxeMessageBoxIndirect): + * intl-auto-encap-win32.c (qxeGetWindowLong): + * intl-auto-encap-win32.c (qxeSetWindowLong): + * intl-auto-encap-win32.c (qxeGetClassLong): + * intl-auto-encap-win32.c (qxeSetClassLong): + * intl-auto-encap-win32.c (qxeFindWindow): + * intl-auto-encap-win32.c (qxeFindWindowEx): + * intl-auto-encap-win32.c (qxeGetClassName): + * intl-auto-encap-win32.c (qxeSetWindowsHookEx): + * intl-auto-encap-win32.c (qxeLoadBitmap): + * intl-auto-encap-win32.c (qxeLoadCursor): + * intl-auto-encap-win32.c (qxeLoadCursorFromFile): + * intl-auto-encap-win32.c (qxeLoadIcon): + * intl-auto-encap-win32.c (qxeLoadImage): + * intl-auto-encap-win32.c (qxeLoadString): + * intl-auto-encap-win32.c (qxeIsDialogMessage): + * intl-auto-encap-win32.c (qxeDlgDirList): + * intl-auto-encap-win32.c (qxeDlgDirSelectEx): + * intl-auto-encap-win32.c (qxeDlgDirListComboBox): + * intl-auto-encap-win32.c (qxeDlgDirSelectComboBoxEx): + * intl-auto-encap-win32.c (qxeDefFrameProc): + * intl-auto-encap-win32.c (qxeCreateMDIWindow): + * intl-auto-encap-win32.c (qxeWinHelp): + * intl-auto-encap-win32.c (qxeRegLoadKey): + * intl-auto-encap-win32.c (qxeRegOpenKey): + * intl-auto-encap-win32.c (qxeSetLocaleInfo): + * intl-auto-encap-win32.c (qxeCopyMetaFile): + * intl-auto-encap-win32.c (qxeCreateScalableFontResource): + * intl-auto-encap-win32.c (qxeGetCharWidth): + * intl-auto-encap-win32.c (qxeGetCharWidth32): + * intl-auto-encap-win32.c (qxeGetCharWidthFloat): + * intl-auto-encap-win32.c (qxeGetCharABCWidths): + * intl-auto-encap-win32.c (qxeGetCharABCWidthsFloat): + * intl-auto-encap-win32.c (qxeGetGlyphOutline): + * intl-auto-encap-win32.c (qxeGetMetaFile): + * intl-auto-encap-win32.c (qxeGetTextExtentPoint): + * intl-auto-encap-win32.c (qxeGetTextExtentPoint32): + * intl-auto-encap-win32.c (qxeGetTextExtentExPoint): + * intl-auto-encap-win32.c (qxeGetCharacterPlacement): + * intl-auto-encap-win32.c (qxeCopyEnhMetaFile): + * intl-auto-encap-win32.c (qxeCreateEnhMetaFile): + * intl-auto-encap-win32.c (qxeGetEnhMetaFile): + * intl-auto-encap-win32.c (qxeGetEnhMetaFileDescription): + * intl-auto-encap-win32.c (qxeTextOut): + * intl-auto-encap-win32.c (qxeExtTextOut): + * intl-auto-encap-win32.c (qxePolyTextOut): + * intl-auto-encap-win32.c (qxeGetTextFace): + * intl-auto-encap-win32.c (qxeGetKerningPairs): + * intl-auto-encap-win32.c (qxeEnumICMProfiles): + * intl-auto-encap-win32.c (qxeGetOpenFileName): + * intl-auto-encap-win32.c (qxeGetSaveFileName): + * intl-auto-encap-win32.c (qxeGetFileTitle): + * intl-auto-encap-win32.c (qxeChooseColor): + * intl-auto-encap-win32.c (qxeFindText): + * intl-auto-encap-win32.c (qxeReplaceText): + * intl-auto-encap-win32.c (qxeImmGetDescription): + * intl-auto-encap-win32.c (qxeImmGetIMEFileName): + * intl-auto-encap-win32.c (qxeMoveFile): + * intl-auto-encap-win32.c (qxeMoveFileEx): + * intl-auto-encap-win32.c (qxeGetNamedPipeHandleState): + * intl-auto-encap-win32.c (qxeCallNamedPipe): + * intl-auto-encap-win32.c (qxeWaitNamedPipe): + * intl-auto-encap-win32.c (qxeSetVolumeLabel): + * intl-auto-encap-win32.c (qxeGetVolumeInformation): + * intl-auto-encap-win32.c (qxeClearEventLog): + * intl-auto-encap-win32.c (qxeBackupEventLog): + * intl-auto-encap-win32.c (qxeOpenEventLog): + * intl-auto-encap-win32.c (qxeRegisterEventSource): + * intl-auto-encap-win32.c (qxeOpenBackupEventLog): + * intl-auto-encap-win32.c (qxeReadEventLog): + * intl-auto-encap-win32.c (qxeReportEvent): + * intl-auto-encap-win32.c (qxeAccessCheckAndAuditAlarm): + * intl-auto-encap-win32.c (qxeObjectOpenAuditAlarm): + * intl-auto-encap-win32.c (qxeObjectPrivilegeAuditAlarm): + * intl-auto-encap-win32.c (qxeObjectCloseAuditAlarm): + * intl-auto-encap-win32.c (qxeObjectDeleteAuditAlarm): + * intl-auto-encap-win32.c (qxePrivilegedServiceAuditAlarm): + * intl-auto-encap-win32.c (qxeSetFileSecurity): + * intl-auto-encap-win32.c (qxeGetFileSecurity): + * intl-auto-encap-win32.c (qxeFindFirstChangeNotification): + * intl-auto-encap-win32.c (qxeIsBadStringPtr): + * intl-auto-encap-win32.c (qxeLookupAccountSid): + * intl-auto-encap-win32.c (qxeLookupAccountName): + * intl-auto-encap-win32.c (qxeLookupPrivilegeValue): + * intl-auto-encap-win32.c (qxeLookupPrivilegeName): + * intl-auto-encap-win32.c (qxeLookupPrivilegeDisplayName): + * intl-auto-encap-win32.c (qxeBuildCommDCB): + * intl-auto-encap-win32.c (qxeBuildCommDCBAndTimeouts): + * intl-auto-encap-win32.c (qxeCommConfigDialog): + * intl-auto-encap-win32.c (qxeGetDefaultCommConfig): + * intl-auto-encap-win32.c (qxeSetDefaultCommConfig): + * intl-auto-encap-win32.c (qxeGetComputerName): + * intl-auto-encap-win32.c (qxeSetComputerName): + * intl-auto-encap-win32.c (qxeGetUserName): + * intl-auto-encap-win32.c (qxeLogonUser): + * intl-auto-encap-win32.c (qxeCreateProcessAsUser): + * intl-auto-encap-win32.c (qxesndPlaySound): + * intl-auto-encap-win32.c (qxePlaySound): + * intl-auto-encap-win32.c (qxemidiInGetErrorText): + * intl-auto-encap-win32.c (qxemmioInstallIOProc): + * intl-auto-encap-win32.c (qxemmioOpen): + * intl-auto-encap-win32.c (qxemmioRename): + * intl-auto-encap-win32.c (qxemciSendCommand): + * intl-auto-encap-win32.c (qxemciSendString): + * intl-auto-encap-win32.c (qxemciGetDeviceID): + * intl-auto-encap-win32.h: + * intl-auto-encap-win32.h (EnumPrinters): + * intl-auto-encap-win32.h (ResetPrinter): + * intl-auto-encap-win32.h (SetJob): + * intl-auto-encap-win32.h (GetJob): + * intl-auto-encap-win32.h (EnumJobs): + * intl-auto-encap-win32.h (AddPrinter): + * intl-auto-encap-win32.h (SetPrinter): + * intl-auto-encap-win32.h (GetPrinter): + * intl-auto-encap-win32.h (AddPrinterDriver): + * intl-auto-encap-win32.h (AddPrinterDriverEx): + * intl-auto-encap-win32.h (EnumPrinterDrivers): + * intl-auto-encap-win32.h (GetPrinterDriver): + * intl-auto-encap-win32.h (GetPrinterDriverDirectory): + * intl-auto-encap-win32.h (DeletePrinterDriver): + * intl-auto-encap-win32.h (DeletePrinterDriverEx): + * intl-auto-encap-win32.h (AddPerMachineConnection): + * intl-auto-encap-win32.h (DeletePerMachineConnection): + * intl-auto-encap-win32.h (EnumPerMachineConnections): + * intl-auto-encap-win32.h (AddPrintProcessor): + * intl-auto-encap-win32.h (EnumPrintProcessors): + * intl-auto-encap-win32.h (GetPrintProcessorDirectory): + * intl-auto-encap-win32.h (EnumPrintProcessorDatatypes): + * intl-auto-encap-win32.h (DeletePrintProcessor): + * intl-auto-encap-win32.h (StartDocPrinter): + * intl-auto-encap-win32.h (AddJob): + * intl-auto-encap-win32.h (AdvancedDocumentProperties): + * intl-auto-encap-win32.h (GetPrinterData): + * intl-auto-encap-win32.h (GetPrinterDataEx): + * intl-auto-encap-win32.h (EnumPrinterData): + * intl-auto-encap-win32.h (EnumPrinterDataEx): + * intl-auto-encap-win32.h (EnumPrinterKey): + * intl-auto-encap-win32.h (SetPrinterData): + * intl-auto-encap-win32.h (SetPrinterDataEx): + * intl-auto-encap-win32.h (DeletePrinterData): + * intl-auto-encap-win32.h (DeletePrinterDataEx): + * intl-auto-encap-win32.h (DeletePrinterKey): + * intl-auto-encap-win32.h (PrinterMessageBox): + * intl-auto-encap-win32.h (AddForm): + * intl-auto-encap-win32.h (DeleteForm): + * intl-auto-encap-win32.h (GetForm): + * intl-auto-encap-win32.h (SetForm): + * intl-auto-encap-win32.h (EnumForms): + * intl-auto-encap-win32.h (EnumMonitors): + * intl-auto-encap-win32.h (AddMonitor): + * intl-auto-encap-win32.h (DeleteMonitor): + * intl-auto-encap-win32.h (EnumPorts): + * intl-auto-encap-win32.h (AddPort): + * intl-auto-encap-win32.h (ConfigurePort): + * intl-auto-encap-win32.h (DeletePort): + * intl-auto-encap-win32.h (XcvData): + * intl-auto-encap-win32.h (SetPort): + * intl-auto-encap-win32.h (AddPrinterConnection): + * intl-auto-encap-win32.h (DeletePrinterConnection): + * intl-auto-encap-win32.h (AddPrintProvidor): + * intl-auto-encap-win32.h (DeletePrintProvidor): + * intl-auto-encap-win32.h (SetPrinterHTMLView): + * intl-auto-encap-win32.h (GetPrinterHTMLView): + * intl-auto-encap-win32.h (WNetAddConnection): + * intl-auto-encap-win32.h (WNetAddConnection2): + * intl-auto-encap-win32.h (WNetAddConnection3): + * intl-auto-encap-win32.h (WNetCancelConnection): + * intl-auto-encap-win32.h (WNetCancelConnection2): + * intl-auto-encap-win32.h (WNetGetConnection): + * intl-auto-encap-win32.h (WNetUseConnection): + * intl-auto-encap-win32.h (WNetConnectionDialog1): + * intl-auto-encap-win32.h (WNetDisconnectDialog1): + * intl-auto-encap-win32.h (WNetOpenEnum): + * intl-auto-encap-win32.h (WNetEnumResource): + * intl-auto-encap-win32.h (WNetGetUniversalName): + * intl-auto-encap-win32.h (WNetGetUser): + * intl-auto-encap-win32.h (WNetGetProviderName): + * intl-auto-encap-win32.h (WNetGetNetworkInformation): + * intl-auto-encap-win32.h (WNetGetLastError): + * intl-auto-encap-win32.h (MultinetGetConnectionPerformance): + * intl-auto-encap-win32.h (GetBinaryType): + * intl-auto-encap-win32.h (GetShortPathName): + * intl-auto-encap-win32.h (GetLongPathName): + * intl-auto-encap-win32.h (FreeEnvironmentStrings): + * intl-auto-encap-win32.h (FormatMessage): + * intl-auto-encap-win32.h (CreateMailslot): + * intl-auto-encap-win32.h (EncryptFile): + * intl-auto-encap-win32.h (DecryptFile): + * intl-auto-encap-win32.h (OpenRaw): + * intl-auto-encap-win32.h (QueryRecoveryAgents): + * intl-auto-encap-win32.h (lstrcmp): + * intl-auto-encap-win32.h (lstrcmpi): + * intl-auto-encap-win32.h (lstrcpyn): + * intl-auto-encap-win32.h (lstrcpy): + * intl-auto-encap-win32.h (lstrcat): + * intl-auto-encap-win32.h (lstrlen): + * intl-auto-encap-win32.h (CreateMutex): + * intl-auto-encap-win32.h (OpenMutex): + * intl-auto-encap-win32.h (CreateEvent): + * intl-auto-encap-win32.h (OpenEvent): + * intl-auto-encap-win32.h (CreateSemaphore): + * intl-auto-encap-win32.h (OpenSemaphore): + * intl-auto-encap-win32.h (CreateWaitableTimer): + * intl-auto-encap-win32.h (OpenWaitableTimer): + * intl-auto-encap-win32.h (CreateFileMapping): + * intl-auto-encap-win32.h (OpenFileMapping): + * intl-auto-encap-win32.h (GetLogicalDriveStrings): + * intl-auto-encap-win32.h (LoadLibrary): + * intl-auto-encap-win32.h (LoadLibraryEx): + * intl-auto-encap-win32.h (GetModuleFileName): + * intl-auto-encap-win32.h (GetModuleHandle): + * intl-auto-encap-win32.h (CreateProcess): + * intl-auto-encap-win32.h (FatalAppExit): + * intl-auto-encap-win32.h (GetStartupInfo): + * intl-auto-encap-win32.h (GetCommandLine): + * intl-auto-encap-win32.h (GetEnvironmentVariable): + * intl-auto-encap-win32.h (SetEnvironmentVariable): + * intl-auto-encap-win32.h (ExpandEnvironmentStrings): + * intl-auto-encap-win32.h (OutputDebugString): + * intl-auto-encap-win32.h (FindResource): + * intl-auto-encap-win32.h (FindResourceEx): + * intl-auto-encap-win32.h (EnumResourceTypes): + * intl-auto-encap-win32.h (EnumResourceNames): + * intl-auto-encap-win32.h (EnumResourceLanguages): + * intl-auto-encap-win32.h (BeginUpdateResource): + * intl-auto-encap-win32.h (UpdateResource): + * intl-auto-encap-win32.h (EndUpdateResource): + * intl-auto-encap-win32.h (GlobalAddAtom): + * intl-auto-encap-win32.h (GlobalFindAtom): + * intl-auto-encap-win32.h (GlobalGetAtomName): + * intl-auto-encap-win32.h (AddAtom): + * intl-auto-encap-win32.h (FindAtom): + * intl-auto-encap-win32.h (GetAtomName): + * intl-auto-encap-win32.h (GetProfileInt): + * intl-auto-encap-win32.h (GetProfileString): + * intl-auto-encap-win32.h (WriteProfileString): + * intl-auto-encap-win32.h (GetProfileSection): + * intl-auto-encap-win32.h (WriteProfileSection): + * intl-auto-encap-win32.h (GetPrivateProfileInt): + * intl-auto-encap-win32.h (GetPrivateProfileString): + * intl-auto-encap-win32.h (WritePrivateProfileString): + * intl-auto-encap-win32.h (GetPrivateProfileSection): + * intl-auto-encap-win32.h (WritePrivateProfileSection): + * intl-auto-encap-win32.h (GetPrivateProfileSectionNames): + * intl-auto-encap-win32.h (GetPrivateProfileStruct): + * intl-auto-encap-win32.h (WritePrivateProfileStruct): + * intl-auto-encap-win32.h (GetDriveType): + * intl-auto-encap-win32.h (GetSystemDirectory): + * intl-auto-encap-win32.h (GetTempPath): + * intl-auto-encap-win32.h (GetTempFileName): + * intl-auto-encap-win32.h (GetWindowsDirectory): + * intl-auto-encap-win32.h (SetCurrentDirectory): + * intl-auto-encap-win32.h (GetCurrentDirectory): + * intl-auto-encap-win32.h (GetDiskFreeSpace): + * intl-auto-encap-win32.h (GetDiskFreeSpaceEx): + * intl-auto-encap-win32.h (CreateDirectory): + * intl-auto-encap-win32.h (CreateDirectoryEx): + * intl-auto-encap-win32.h (RemoveDirectory): + * intl-auto-encap-win32.h (GetFullPathName): + * intl-auto-encap-win32.h (DefineDosDevice): + * intl-auto-encap-win32.h (QueryDosDevice): + * intl-auto-encap-win32.h (CreateFile): + * intl-auto-encap-win32.h (SetFileAttributes): + * intl-auto-encap-win32.h (GetFileAttributes): + * intl-auto-encap-win32.h (GetFileAttributesEx): + * intl-auto-encap-win32.h (GetCompressedFileSize): + * intl-auto-encap-win32.h (DeleteFile): + * intl-auto-encap-win32.h (FindFirstFileEx): + * intl-auto-encap-win32.h (SearchPath): + * intl-auto-encap-win32.h (CopyFile): + * intl-auto-encap-win32.h (CopyFileEx): + * intl-auto-encap-win32.h (MoveFile): + * intl-auto-encap-win32.h (MoveFileEx): + * intl-auto-encap-win32.h (MoveFileWithProgress): + * intl-auto-encap-win32.h (CreateHardLink): + * intl-auto-encap-win32.h (CreateNamedPipe): + * intl-auto-encap-win32.h (GetNamedPipeHandleState): + * intl-auto-encap-win32.h (CallNamedPipe): + * intl-auto-encap-win32.h (WaitNamedPipe): + * intl-auto-encap-win32.h (SetVolumeLabel): + * intl-auto-encap-win32.h (GetVolumeInformation): + * intl-auto-encap-win32.h (ClearEventLog): + * intl-auto-encap-win32.h (BackupEventLog): + * intl-auto-encap-win32.h (OpenEventLog): + * intl-auto-encap-win32.h (RegisterEventSource): + * intl-auto-encap-win32.h (OpenBackupEventLog): + * intl-auto-encap-win32.h (ReadEventLog): + * intl-auto-encap-win32.h (ReportEvent): + * intl-auto-encap-win32.h (AccessCheckAndAuditAlarm): + * intl-auto-encap-win32.h (AccessCheckByTypeAndAuditAlarm): + * intl-auto-encap-win32.h (AccessCheckByTypeResultListAndAuditAlarm): + * intl-auto-encap-win32.h (ObjectOpenAuditAlarm): + * intl-auto-encap-win32.h (ObjectPrivilegeAuditAlarm): + * intl-auto-encap-win32.h (ObjectCloseAuditAlarm): + * intl-auto-encap-win32.h (ObjectDeleteAuditAlarm): + * intl-auto-encap-win32.h (PrivilegedServiceAuditAlarm): + * intl-auto-encap-win32.h (SetFileSecurity): + * intl-auto-encap-win32.h (GetFileSecurity): + * intl-auto-encap-win32.h (FindFirstChangeNotification): + * intl-auto-encap-win32.h (ReadDirectoryChanges): + * intl-auto-encap-win32.h (IsBadStringPtr): + * intl-auto-encap-win32.h (LookupAccountSid): + * intl-auto-encap-win32.h (LookupAccountName): + * intl-auto-encap-win32.h (LookupPrivilegeValue): + * intl-auto-encap-win32.h (LookupPrivilegeName): + * intl-auto-encap-win32.h (LookupPrivilegeDisplayName): + * intl-auto-encap-win32.h (BuildCommDCB): + * intl-auto-encap-win32.h (BuildCommDCBAndTimeouts): + * intl-auto-encap-win32.h (CommConfigDialog): + * intl-auto-encap-win32.h (GetDefaultCommConfig): + * intl-auto-encap-win32.h (SetDefaultCommConfig): + * intl-auto-encap-win32.h (GetComputerName): + * intl-auto-encap-win32.h (SetComputerName): + * intl-auto-encap-win32.h (GetUserName): + * intl-auto-encap-win32.h (LogonUser): + * intl-auto-encap-win32.h (CreateProcessAsUser): + * intl-auto-encap-win32.h (GetCurrentHwProfile): + * intl-auto-encap-win32.h (GetVersionEx): + * intl-auto-encap-win32.h (CreateJobObject): + * intl-auto-encap-win32.h (OpenJobObject): + * intl-auto-encap-win32.h (qxemciGetErrorString): + Regenerate. + + --------------------------- + Unicode-work + --------------------------- + + * intl-win32.c (convert_multibyte_to_unicode_malloc): + * intl-win32.c (convert_unicode_to_multibyte_malloc): + * intl-win32.c (unicode_multibyte_convert_now_damn_it): + * intl-win32.c (unicode_multibyte_convert_size): + * intl-win32.c (unicode_multibyte_convert_copy_data): + * intl-win32.c (convert_multibyte_to_unicode_dynarr): + * intl-win32.c (convert_unicode_to_multibyte_dynarr): + * intl-win32.c (mswindows_multibyte_to_unicode_convert): + * syswindows.h: + Factor out common options to MultiByteToWideChar and + WideCharToMultiByte. Add convert_unicode_to_multibyte_malloc() + and convert_unicode_to_multibyte_dynarr() and use. Add stuff for + alloca() conversion of multibyte/unicode. + + * alloc.c (build_ext_string): + Use dfc_external_data_len() in case of unicode coding system. + + * alloc.c: + * mule-charset.c: + * mule-charset.c (make_charset): + * mule-charset.c (syms_of_mule_charset): + Don't zero out and reinit charset Unicode tables. This fucks up + dump-time loading. Anyway, either we load them at dump time or + run time, never both. + + * unicode.c (init_charset_unicode_tables): + * unicode.c (vars_of_unicode): + Dump the blank tables as well. + + --------------------------------------------------------------- + DOCUMENTATION, MOSTLY MULE-RELATED: + --------------------------------------------------------------- + + * EmacsFrame.c (Xt_StringToScrollBarPlacement): + * emodules.c: + * event-Xt.c (x_to_emacs_keysym): + * fileio.c (Fencrypt_string): + * input-method-xlib.c (EmacsXtCvtStringToXIMStyles): + * mule-wnnfns.c (Fwnn_open): + * redisplay-gtk.c (gtk_output_string): + * redisplay-gtk.c (gtk_text_width): + * redisplay-tty.c (init_tty_for_redisplay): + * redisplay-x.c (x_text_width): + * regex.c: + * sysdep.c (init_system_name): + Add comment about Mule work needed. + + * text.h (NEW_DFC_CONVERT_1_ALLOCA): + Add more documentation describing why DFC routines were not written + to return their value. Add some other DFC documentation. + + * console-msw.c: + * console-msw.h: + Add pointer to docs in win32.c. + + * emacs.c: + Add comments on sources of doc info. + + * text.c: + * text.c (NOTE): New. + * text.c (Note): New. + * charset.h (struct Lisp_Charset): + * unicode.c: + * intl-win32.c: + * intl-win32.c (NOTE): New. + * intl-win32.c (Abstract): New. + * intl-encap-win32.c: + * text.h: + * text.h (internal_format): + * file-coding.c (encode_decode_coding_region): + * file-coding.c: + * mule-coding.c (parse_iso2022_esc): + Collect background comments and related to text matters and + internationalization, and proposals for work to be done, in text.c + or Internals manual, stuff related to specific textual API's in + text.h, and stuff related to internal implementation of Unicode + conversion in unicode.c. Put lots of pointers to the comments to + make them easier to find. + + * s/mingw32.h: + * s/win32-common.h: + * s/win32-native.h: + * s/windowsnt.h: + * win32.c: + * win32.c (console-msw.h): New. + * win32.c (process-nt.c): New. + * win32.c (nt.c): New. + * win32.c (win32.c): New. + * win32.c (syswindows.h): New. + * win32.c (intl-win32.c): New. + * win32.c (intl-encap-win32.c): New. + * win32.c (intl-auto-encap-win32.c): New. + * win32.c (intl-auto-encap-win32.h): New. + Add bunches of new documentation on the different kinds of + builds and environments under Windows and how they work. + Collect this info in win32.c. Add pointers to these docs in + the relevant s/* files. + + * emacs.c (mswindows_handle_hardware_exceptions_1): + * emacs.c: + Document places with long comments. + Remove comment about exiting, move to internals manual, put + in pointer. + + * event-stream.c: + Move docs about event queues and focus to internals manual, put + in pointer. + + * events.h: + Move docs about event stream callbacks to internals manual, put + in pointer. + + * profile.c: + * redisplay.c (create_text_block): + * signal.c: + Move documentation to the Internals manual. + + * process-nt.c: + Add pointer to comment in win32-native.el. + + * lisp.h: + Add comments about some comment conventions. + + * lisp.h (xfree): + Add comment about the second argument. + + * device-msw.c (msprinter_init_device): + * redisplay-msw.c (mswindows_text_width_single_run): + @@#### comments are out-of-date. + + --------------------------------------------------------------- + PDUMP WORK (MOTIVATED BY UNICODE CHANGES) + --------------------------------------------------------------- + + * alloc.c (lispdesc_block_size_1): + * alloc.c (lispdesc_one_description_line_size): + * alloc.c (mark_struct_contents): + * buffer.c: + * buffer.c (complex_vars_of_buffer): + * buffer.c (vars_of_buffer): + * bytecode.c: + * console-impl.h (INITIALIZE_CONSOLE_TYPE): + * console.c (complex_vars_of_console): + * console.c (console_type_create): + * console.c: + * device.c: + * dumper.c (dump_add_root_block): + * dumper.c (dump_add_root_block_ptr): + * dumper.c (dump_add_root_lisp_object): + * dumper.c (dump_add_weak_object_chain): + * dumper.c (pdump_add_block): + * dumper.c (pdump_allocate_offset): + * dumper.c (pdump_block_list_elt): + * dumper.c (pdump_desc_list_elt): + * dumper.c (pdump_dump_data): + * dumper.c (pdump_dump_root_blocks): + * dumper.c (pdump_dump_rtables): + * dumper.c (pdump_get_block_list): + * dumper.c (pdump_register_block): + * dumper.c (pdump_register_block_contents): + * dumper.c (pdump_register_object): + * dumper.c (pdump_scan_by_alignment): + * alloc.c (lispdesc_one_description_line_size): + * alloc.c (kkcc_marking): + * dumper.c (pdump_register_sub): + * lrecord.h: + * lrecord.h (struct lrecord_implementation): + * lrecord.h (memory_description_type): + * elhash.c: + * emodules.h: + * events.c: + * extents.c: + * frame.c: + * glyphs.c: + * glyphs.h (INITIALIZE_DEVICE_IIFORMAT): + * glyphs.h (INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM): + * mule-charset.c (vars_of_mule_charset): + * mule-coding.c: + * objects.c: + * profile.c (vars_of_profile): + * rangetab.c: + * redisplay.c: + * specifier.c (specifier_type_create): + * specifier.c: + * specifier.h (INITIALIZE_SPECIFIER_TYPE): + * window.c: + * lstream.c (lstream_description): + * file-coding.h (INITIALIZE_CODING_SYSTEM_TYPE): + * file-coding.c (coding_system_description): + * file-coding.c (coding_system_type_create): + * lrecord.h (XD_DYNARR_DESC): + PDUMP: + + Properly implement dump_add_root_block(), which never worked before, + and is necessary for dumping Unicode tables. + + Pdump name changes for accuracy: + XD_STRUCT_PTR -> XD_BLOCK_PTR. + XD_STRUCT_ARRAY -> XD_BLOCK_ARRAY. + XD_C_STRING -> XD_ASCII_STRING. + *_structure_* -> *_block_*. + + * lrecord.h (XD_DYNARR_DESC): some comments added about + dump_add_root_block() vs dump_add_root_block_ptr(). + + * extents.c: + remove incorrect comment about pdump problems with gap array. + + --------------------------------------------------------------- + ALLOCATION + --------------------------------------------------------------- + + * abbrev.c (abbrev_oblookup): + * alloc.c (MALLOC_BEGIN): + * bytecode.c (compiled_function_instructions): + * casefiddle.c (casify_object): + * device-msw.c (Fmswindows_printer_list): + * device-x.c: + * dired-msw.c (mswindows_get_files): + * doc.c (Fsubstitute_command_keys): + * doc.c (unparesseuxify_doc_string): + * doc.c: + * doprnt.c (emacs_vsprintf_malloc): + * doprnt.c (emacs_vsprintf_malloc_lisp): + * dragdrop.c (dnd_url_hexify_string): + * dragdrop.c: + * editfns.c (Fformat_time_string): + * editfns.c (Finsert_char): + * editfns.c (get_home_directory): + * emodules.c (emodules_load): + * file-coding.c (setup_eol_coding_systems): + * fileio.c (Fdirectory_file_name): + * fileio.c (Ffile_name_directory): + * fileio.c (Fsubstitute_in_file_name): + * fileio.c (Fexpand_file_name): + * filelock.c (MAKE_LOCK_NAME): + * filelock.c (current_lock_owner): + * filelock.c (lock_file): + * filelock.c (lock_file_1): + * fns.c (mapcar1): + * glyphs-eimage.c (jpeg_instantiate): + * glyphs-eimage.c (gif_instantiate): + * glyphs-eimage.c (tiff_instantiate): + * glyphs-gtk.c (gtk_xpm_instantiate): + * glyphs-msw.c (mswindows_combo_box_property): + * glyphs-msw.c (mswindows_widget_property): + * glyphs-msw.c (convert_EImage_to_DIBitmap): + * glyphs-msw.c (mswindows_initialize_image_instance_mask): + * glyphs-msw.c (xbm_create_bitmap_from_data): + * glyphs-x.c (convert_EImage_to_XImage): + * glyphs-x.c (x_xface_instantiate): + * gui-msw.c (mswindows_translate_menu_or_dialog_item): + * gui-x.c (add_accel_and_to_external): + * imgproc.c (create_colorcell): + * imgproc.c (build_EImage_quantable): + * intl-win32.c (Fmswindows_get_valid_keyboard_layouts): + * intl-win32.c (convert_multibyte_to_unicode_malloc): + * intl-win32.c (wcsdup): + * lread.c (Fload_internal): + * lread.c (locate_file_map_suffixes): + * menubar-gtk.c (menu_descriptor_to_widget_1): + * menubar.c (Fnormalize_menu_item_name): + * nt.c (init_mswindows_environment): + * nt.c (get_cached_volume_information): + * nt.c (get_volume_info): + * nt.c (nt_get_resource): + * objects-msw.c (mswindows_string_to_color): + * objects-x.c (truename_via_random_props): + * print.c (output_string): + * process-nt.c (nt_create_process): + * process-unix.c (child_setup): + * process.c (init_xemacs_process): + * realpath.c (readlink_and_correct_case): + * redisplay.c (add_disp_table_entry_runes_1): + * search.c (Fregexp_quote): + * search.c (search_buffer): + * search.c (wordify): + * select-common.c (receive_incremental_selection): + * symbols.c (check_module_subr): + * sysdep.c (sys_subshell): + * syswindows.h (LOCAL_TO_WIN32_FILE_FORMAT): + * syswindows.h (WIN32_TO_LOCAL_FILE_FORMAT): + * text.c (convert_ichar_string_into_malloced_string): + * text.c (eito_malloc_1): + * text.h (EI_CASECHANGE): + * text.h (EI_ALLOC): + * text.h (eicpy_c): + * text.h (eicpyout_alloca_fmt): + * text.h (eito_alloca): + * text.h (LISP_STRING_TO_ALLOCA): + * ui-byhand.c (Fgtk_curve_get_vector): + * ui-byhand.c (Fgtk_curve_set_vector): + * text.h: + New macros {alloca,xnew}_{itext,{i,ext,raw,bin,asc}bytes} for + more convenient allocation of these commonly requested items. + Modify functions to use alloca_ibytes, alloca_array, alloca_extbytes, + xnew_ibytes, etc. also XREALLOC_ARRAY, xnew. + + * alloc.c (FREE_FIXED_TYPE): + * alloc.c (Fstring): + * alloc.c (MALLOC_BEGIN): + * alloc.c (free_managed_lcrecord): + * alloc.c (garbage_collect_1): + * alloc.c (init_alloc_once_early): + * alloc.c (xcalloc): + * alloc.c (xfree_1): + * alloc.c (xrealloc): + * alloc.c: + Rewrite the allocation functions to factor out repeated code. + Add assertions for freeing dumped data. + + * lisp.h (xmalloc_and_record_unwind): + * lisp.h (xfree): + Moved down and consolidated with other allocation stuff. + + * lisp.h: + * dynarr.c (stack_like_malloc): + * dynarr.c (stack_like_free): + New functions for allocation that's very efficient when mostly in + LIFO order. + + * lisp.h: + * text.c (find_pos_of_existing_active_alloca_convert): + * text.h (NEW_DFC_CONVERT_1_ALLOCA): + * text.c (new_dfc_convert_now_damn_it): + * text.c (new_dfc_convert_size): + * text.c (new_dfc_convert_copy_data): + * text.c (new_dfc_convert_malloc): + * text.h: + Factor out some stuff for general use by alloca()-conversion funs. + + * text.h (xmalloc_ibytes): + * lisp.h: + Fill out convenience routines for allocating various kinds of + bytes and put them in lisp.h. Use them in place of xmalloc(), + ALLOCA(). + + * text.h (SIZED_C_STRING_TO_EXTERNAL_MALLOC): + * text.h (C_STRING_TO_SIZED_EXTERNAL_MALLOC): + Fill out the convenience functions so the _MALLOC() kinds match + the alloca() kinds. + + --------------------------------------------------------------- + ERROR-CHECKING + --------------------------------------------------------------- + + * text.h (eicpy_c): + * text.h (eicpy_c_len): + * text.h (eicat_c): + * text.h (eisub_c): + Create ASSERT_ASCTEXT_ASCII() and ASSERT_ASCTEXT_ASCII_LEN() + from similar Eistring checkers and change the Eistring checkers to + use them instead. + + + --------------------------------------------------------------- + MACROS IN LISP.H + --------------------------------------------------------------- + + * lisp.h (GCDECL1): + * lisp.h (NNUNGCPRO): + * lisp.h (XGCDECL1): + * lisp.h (XGCPRO1): + * lisp.h (XUNGCPRO): + Redo GCPRO declarations. Create a "base" set of functions that can + be used to generate any kind of gcpro sets -- regular, ngcpro, + nngcpro, private ones used in GC_EXTERNAL_LIST_LOOP_2. + + * buffer.c (Fkill_buffer): + * callint.c (quotify_args): + * chartab.c (chartab_data_validate): + * console-msw.c: + * device-x.c: + * dialog-msw.c (handle_question_dialog_box): + * dired.c (file_name_completion): + * dired.c (Fdirectory_files): + * dired.c (file_name_completion_stat): + * extents.c (memoize_extent_face_internal): + * extents.c (report_extent_modification_mapper): + * ui-gtk.c (Fgtk_call_function): + * ui-gtk.c (Fgtk_import_function_internal): + * rangetab.c (rangetab_data_validate): + * nt.c (init_mswindows_environment): + * mule-coding.c (parse_charset_conversion_specs): + * minibuf.c (regexp_ignore_completion_p): + * menubar-msw.c (populate_or_checksum_helper): + * menubar.c (Fmenu_find_real_submenu): + * menubar-gtk.c (menu_create_menubar): + * lread.c (locate_file_without_hash): + * lread.c (Flocate_file): + * lread.c (Flocate_file_clear_hashing): + * lread.c (decode_mode): + * lread.c (locate_file): + * lisp.h (PROPERTY_LIST_LOOP): + * lisp.h (GC_EXTERNAL_LIST_LOOP_2): New. + * lisp.h (END_GC_EXTERNAL_LIST_LOOP): New. + * lisp.h (EXTERNAL_LIST_LOOP): Deleted. + * gutter.c (gutter_visible_validate): + * glyphs.c (decode_image_instance_type_list): + * glyphs.c (Fset_console_type_image_conversion_list): + * glyphs-widget.c (check_valid_instantiator_list): + * glyphs-widget.c (check_valid_item_list): + * fns.c (Freplace_list): + * fileio.c (Finsert_file_contents_internal): + * fileio.c (Ffind_file_name_handler): + * file-coding.c (Fset_coding_priority_list): + * file-coding.c (chain_putprop): + * specifier.c (display_table_validate): + Eliminate EXTERNAL_LIST_LOOP, which does not check for circularities. + Use EXTERNAL_LIST_LOOP_2 instead or EXTERNAL_LIST_LOOP_3 + or EXTERNAL_PROPERTY_LIST_LOOP_3 or GC_EXTERNAL_LIST_LOOP_2 + (new macro). Removed/redid comments on EXTERNAL_LIST_LOOP. + + + --------------------------------------------------------------- + SPACING FIXES + --------------------------------------------------------------- + + * callint.c (Fcall_interactively): + * hftctl.c (WR_REQ): + * number-gmp.c (init_number_gmp): + * process-unix.c (unix_deactivate_process): + Spacing fixes. + + + --------------------------------------------------------------- + FIX FOR GEOMETRY PROBLEM IN FIRST FRAME + --------------------------------------------------------------- + + * unicode.c (init_charset_unicode_tables): + Add workaround for newlib bug in sscanf() [should be fixed by + release 1.5.12 of Cygwin]. + * toolbar.c (update_frame_toolbars_geometry): + bug fix for problem of initial frame being 77 chars wide on Windows. + will be overridden by my other ws. + + --------------------------------------------------------------- + FIX FOR LEAKING PROCESS HANDLES: + --------------------------------------------------------------- + + + * process-nt.c (free_process_memory): + * process-nt.c (alloc_process_memory): + * process-nt.c (run_in_other_process): + * process-nt.c (send_signal_the_nt_way): + * process-nt.c (nt_finalize_process_data): + * process-nt.c (nt_create_process): + * process-nt.c (nt_deactivate_process): + * process-nt.c (process_type_create_nt): + Fixes for leaking handles. Inspired by work done by Adrian Aichner + <adrian@xemacs.org>. + + --------------------------------------------------------------- + FIX FOR CYGWIN BUG (Unicode-related): + --------------------------------------------------------------- + + * unicode.c (init_charset_unicode_tables): + Add workaround for newlib bug in sscanf() [should be fixed by + release 1.5.12 of Cygwin]. + + --------------------------------------------------------------- + WARNING FIXES: + --------------------------------------------------------------- + + * console-stream.c (init_console_stream): + `reinit' is unused. + + * compiler.h: + * event-msw.c (mswindows_wnd_proc): + * frame-msw.c (mswindows_frame_totally_visible_p): + * intl-encap-win32.c (qxeRegisterClass): + * intl-encap-win32.c (qxeRegisterClassEx): + * text.h (DFC_ALLOCA_USE_CONVERTED_DATA): + Add stuff to deal with ANSI-aliasing warnings I got. + + * regex.c: + * regex.c (itext_ichar): + Gather includes together to avoid warning. + + --------------------------------------------------------------- + CHANGES TO INITIALIZATION ROUTINES: + --------------------------------------------------------------- + + * buffer.c (vars_of_buffer): + * emacs.c (main_1): + * console.c (vars_of_console): + * debug.c (vars_of_debug): + * device-x.c (vars_of_device_x): + * device.c (vars_of_device): + * dragdrop.c (vars_of_dragdrop): + * emodules.c (vars_of_module): + * eval.c (vars_of_eval): + * eval.c (reinit_vars_of_eval): + * event-Xt.c (vars_of_event_Xt): + * event-gtk.c (vars_of_event_gtk): + * event-msw.c (vars_of_event_mswindows): + * event-stream.c (vars_of_event_stream): + * event-tty.c (vars_of_event_tty): + * events.c (vars_of_events): + * extents.c (vars_of_extents): + * faces.c (complex_vars_of_faces): + * file-coding.c (vars_of_file_coding): + * fileio.c (vars_of_fileio): + * font-lock.c (vars_of_font_lock): + * frame-msw.c (vars_of_frame_mswindows): + * glyphs-widget.c (vars_of_glyphs_widget): + * glyphs.c (vars_of_glyphs): + * glyphs.c (complex_vars_of_glyphs): + * gui-x.c (vars_of_gui_x): + * insdel.c (vars_of_insdel): + * lread.c (vars_of_lread): + * lstream.c (vars_of_lstream): + * menubar-gtk.c (vars_of_menubar_gtk): + * menubar-x.c (vars_of_menubar_x): + * minibuf.c (vars_of_minibuf): + * mule-wnnfns.c (vars_of_mule_wnn): + * objects-msw.c (vars_of_objects_mswindows): + * objects.c (vars_of_objects): + * print.c (vars_of_print): + * scrollbar-x.c (vars_of_scrollbar_x): + * search.c (vars_of_search): + * select-x.c (vars_of_select_x): + * text.c (reinit_vars_of_text): + * text.c (vars_of_text): + * undo.c (vars_of_undo): + * unicode.c (vars_of_unicode): + * window.c (vars_of_window): + * symsinit.h: + Call reinit_*() functions directly from emacs.c, for clarity. + Factor out some redundant init code. Move disallowed stuff + that had crept into vars_of_glyphs() into complex_vars_of_glyphs(). + Call init_eval_semi_early() from eval.c not in the middle of + vars_of_() in emacs.c since there should be no order dependency + in the latter calls. + + --------------------------------------------------------------- + ARMAGEDDON: + --------------------------------------------------------------- + + * alloc.c: + * emacs.c: + * lisp.h: + * print.c (debug_backtrace): + * print.c (debug_p3): + * print.c (debug_p4): + * print.c (debug_prin1): + * print.c (print_internal): + * print.c (printing_major_badness): + * print.c (struct debug_bindings ): + * print.c (write_string_to_stdio_stream_1): + * print.c (write_string_to_external_output_va): + * print.c (debug_prin1_exit): + * print.c (write_string_to_alternate_debugging_output): + Rename inhibit_non_essential_printing_operations to + inhibit_non_essential_conversion_operations. + + * text.c (dfc_convert_to_external_format): + * text.c (dfc_convert_to_internal_format): + Assert on !inhibit_non_essential_conversion_operations. + + * console-msw.c (Fmswindows_message_box): + * console-msw.c (GetConsoleHwnd): + * console-msw.c (mswindows_output_console_string): + * console-msw.c (write_string_to_mswindows_debugging_output): + * print.c (write_string_to_stdio_stream_1): + Don't do conversion in SetConsoleTitle or FindWindow to avoid + problems during armageddon. Put #errors for NON_ASCII_INTERNAL_FORMAT + in places where problems would arise. + + --------------------------------------------------------------- + CHANGES TO THE BUILD PROCEDURE: + --------------------------------------------------------------- + + * config.h.in: + * s/cxux.h: + * s/usg5-4-2.h: + * m/powerpc.h: + Add comment about correct ordering of this file. + Rearrange everything to follow this -- put all #undefs together + and before the s&m files. Add undefs for HAVE_ALLOCA, C_ALLOCA, + BROKEN_ALLOCA_IN_FUNCTION_CALLS, STACK_DIRECTION. Remove unused + HAVE_STPCPY, HAVE_GETWD, HAVE_SETLOCALE. + + * m/gec63.h: Deleted; totally broken, not used at all, not in FSF. + + * m/7300.h: + * m/acorn.h: + * m/alliant-2800.h: + * m/alliant.h: + * m/altos.h: + * m/altos.h (SWITCH_ENUM_BUG): + * m/amdahl.h: + * m/apollo.h: + * m/att3b.h: + * m/aviion.h: + * m/celerity.h: + * m/clipper.h: + * m/cnvrgnt.h: + * m/convex.h: + * m/cydra5.h: + * m/cydra5.h (DATA_START): + * m/delta.h: + * m/delta88k.h: + * m/dpx2.h: + * m/elxsi.h: + * m/ews4800r.h: + * m/gould.h: + * m/hp300bsd.h (LOAD_AVE_TYPE): + * m/hp800.h: + * m/hp9000s300.h: + * m/i860.h: + * m/ibmps2-aix.h: + * m/ibmps2-aix.h (LIBS_MACHINE): + * m/ibmrs6000.h: + * m/ibmrt-aix.h: + * m/ibmrt.h: + * m/intel386.h: + * m/intel386.h (SEGMENT_MASK): + * m/iris4d.h: + * m/iris5d.h: + * m/iris6d.h: + * m/irist.h: + * m/isi-ov.h: + * m/luna88k.h: + * m/m68k.h (ASSERT_VALID_POINTER): + * m/masscomp.h: + * m/mg1.h: + * m/mips-nec.h: + * m/mips-siemens.h: + * m/mips.h: + * m/news.h: + * m/nh3000.h: + * m/nh4000.h: + * m/ns32000.h: + * m/orion105.h: + * m/pfa50.h: + * m/plexus.h: + * m/pmax.h: + * m/powerpc.h: + * m/pyrmips.h (CANNOT_DUMP): + * m/sequent-ptx.h: + * m/sequent.h: + * m/sgi-challenge.h: + * m/symmetry.h: + * m/tad68k.h: + * m/tahoe.h: + * m/targon31.h: + * m/tekxd88.h: + * m/template.h: + * m/tower32.h: + * m/tower32v3.h: + * m/ustation.h: + * m/vax.h: + * m/wicat.h: + * m/xps100.h: + * m/xps100.h (TERMINFO): + Delete C_ALLOCA, HAVE_ALLOCA, STACK_DIRECTION, + BROKEN_ALLOCA_IN_FUNCTION_CALLS. All of this is auto-detected. + When in doubt, I followed recent FSF sources, which also have + these things deleted. + + +2002-04-05 Golubev I. N. <gin@mo.msk.ru> + + * .gdbinit (pptype): + Replace `ptype', which clashes with the gdb builtin `ptype'. + +2004-09-02 Yoshiki Hayashi <yoshiki@xemacs.org> + + * buffer.c (Frecord_buffer): Make sure the argument is buffer + to fix a crash. Also, check the buffer is live and it + really exists in buffer_list. If the buffer is not in the list, + prepend it. + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. diff --text -u 'xemacs-21.5.18/src/EmacsFrame.c' 'xemacs-21.5.19/src/EmacsFrame.c' Index: ./src/EmacsFrame.c --- ./src/EmacsFrame.c Tue Sep 21 04:19:34 2004 +++ ./src/EmacsFrame.c Tue Jan 25 08:33:45 2005 @@ -563,6 +563,7 @@ XrmValuePtr fromVal, XrmValuePtr toVal) { + /* !!#### needs work */ XrmQuark q; char *lowerName = (char *) ALLOCA (strlen ((char *) fromVal->addr) + 1); @@ -609,7 +610,7 @@ struct frame *f = ew->emacs_frame.frame; if (! XtIsSubclass (w, emacsFrameClass)) - abort (); + ABORT (); default_face_height_and_width (wrap_frame (f), &ch, &cw); if (FRAME_X_TOP_LEVEL_FRAME_P (f)) diff --text -u 'xemacs-21.5.18/src/EmacsManager.c' 'xemacs-21.5.19/src/EmacsManager.c' Index: ./src/EmacsManager.c --- ./src/EmacsManager.c Tue Sep 21 04:19:34 2004 +++ ./src/EmacsManager.c Wed Dec 22 19:59:09 2004 @@ -243,11 +243,15 @@ /* do nothing if we're already that size */ if (w->core.width != width || w->core.height != height) - if (XtMakeResizeRequest (w, width, height, &w->core.width, &w->core.height) - == XtGeometryAlmost) - XtMakeResizeRequest (w, w->core.width, w->core.height, NULL, NULL); - - Resize (w); + { + XtGeometryResult result = + XtMakeResizeRequest (w, width, height, &w->core.width, &w->core.height); + if (result == XtGeometryNo) + return; + if (result == XtGeometryAlmost) + XtMakeResizeRequest (w, w->core.width, w->core.height, NULL, NULL); + Resize (w); + } } diff --text -u 'xemacs-21.5.18/src/EmacsShell-sub.c' 'xemacs-21.5.19/src/EmacsShell-sub.c' Index: ./src/EmacsShell-sub.c --- ./src/EmacsShell-sub.c Fri Feb 14 16:38:30 2003 +++ ./src/EmacsShell-sub.c Tue Jan 25 08:33:46 2005 @@ -90,6 +90,8 @@ #include <X11/VendorP.h> #include "EmacsShellP.h" +#define ABORT abort + #if defined (DEFINE_TOP_LEVEL_EMACS_SHELL) #define EMACS_SHELL_WIDGET TopLevelEmacsShellWidget #define SUPERCLASS_WIDGET_CLASS topLevelShellWidgetClass @@ -286,7 +288,7 @@ } if (!gcer) - abort (); + ABORT (); /* call it to actually make the geometry request */ scer = (ShellClassExtensionRec *) gcer; @@ -304,7 +306,7 @@ XtGeometryResult result; if (reentrant) - abort (); + ABORT (); reentrant++; #ifdef DEBUG_GEOMETRY_MANAGEMENT diff --text -u 'xemacs-21.5.18/src/EmacsShell.c' 'xemacs-21.5.19/src/EmacsShell.c' Index: ./src/EmacsShell.c --- ./src/EmacsShell.c Fri Apr 13 03:23:22 2001 +++ ./src/EmacsShell.c Tue Jan 25 08:33:46 2005 @@ -34,6 +34,8 @@ #include "EmacsShell.h" #include "ExternalShell.h" +#define ABORT abort + #if 0 /* Not currently used */ /* The root_geometry_manager() method in Shell.c is fucked up with regard @@ -161,5 +163,5 @@ else if (XtIsSubclass (gw, transientEmacsShellWidgetClass)) TransientEmacsShellUpdateSizeHints (gw); else - abort (); + ABORT (); } diff --text -u 'xemacs-21.5.18/src/Makefile.in.in' 'xemacs-21.5.19/src/Makefile.in.in' Index: ./src/Makefile.in.in --- ./src/Makefile.in.in Fri Sep 10 20:58:33 2004 +++ ./src/Makefile.in.in Wed Jan 26 12:40:15 2005 @@ -33,10 +33,10 @@ ## Here are the things that we expect ../configure to edit. #ifdef USE_GNU_MAKE -RECURSIVE_MAKE=$(MAKE) +RECURSIVE_MAKE_ARGS= #else @SET_MAKE@ -RECURSIVE_MAKE=@RECURSIVE_MAKE@ +RECURSIVE_MAKE_ARGS=@RECURSIVE_MAKE_ARGS@ #endif PROGNAME=@PROGNAME@ @@ -377,15 +377,16 @@ cppflags = $(CPPFLAGS) -Demacs -I. $(c_switch_all) cflags = $(CFLAGS) $(cppflags) -#if defined (WIN32_NATIVE) || defined (CYGWIN) +#if defined (WIN32_NATIVE) ldflags = $(LDFLAGS) -mwindows -e _mainCRTStartup $(ld_switch_all) $(ld_dynamic_link_flags) -# if defined (CYGWIN) -ldflags += -Wl,--script=s/cygwin.sc -# endif #else ldflags = $(LDFLAGS) $(ld_switch_all) $(ld_dynamic_link_flags) #endif +#if defined (CYGWIN) && !defined (PDUMP) +ldflags += -Wl,--script=s/cygwin.sc +#endif + #ifdef SOLARIS2 %.o : %.c #else @@ -419,7 +420,11 @@ DUMP_ID = dump-id.o #ifndef WIN32_NATIVE DUMP_TARGET = $(PROGNAME) +#ifndef CYGWIN RAW_EXE = temacs +#else +RAW_EXE = temacs.exe +#endif #endif #else DUMP_TARGET = $(PROGNAME) @@ -521,19 +526,19 @@ #ifdef HAVE_X_WINDOWS lwlib_deps = $(lwlib_lib) $(lwlib_lib): - +cd ../lwlib && $(RECURSIVE_MAKE) + cd ../lwlib && $(MAKE) $(RECURSIVE_MAKE_ARGS) #endif /* HAVE_X_WINDOWS */ #ifdef DYNODUMP dynodump_deps = ../dynodump/dynodump.so ../dynodump/dynodump.so: - +cd ../dynodump && $(RECURSIVE_MAKE) + cd ../dynodump && $(MAKE) $(RECURSIVE_MAKE_ARGS) #endif /* DYNODUMP */ link_deps = $(start_files) $(objs) $(otherobjs) $(lwlib_deps) $(dynodump_deps) $(LIB_SRC)/make-dump-id: - +cd $(LIB_SRC) && $(RECURSIVE_MAKE) make-dump-id + cd $(LIB_SRC) && $(MAKE) $(RECURSIVE_MAKE_ARGS) make-dump-id dump-id.c: $(LIB_SRC)/make-dump-id $(link_deps) $(LIB_SRC)/make-dump-id @@ -569,7 +574,7 @@ obj_src = $(objs:.o=.c) $(LIB_SRC)/make-docfile: - +cd $(LIB_SRC) && $(RECURSIVE_MAKE) make-docfile + cd $(LIB_SRC) && $(MAKE) $(RECURSIVE_MAKE_ARGS) make-docfile $(LIB_SRC)/DOC: $(LIB_SRC)/make-docfile $(BLDSRC)/NEEDTODUMP $(temacs_deps) #ifdef QUICK_BUILD @@ -589,7 +594,7 @@ @$(RM) $@ && touch SATISFIED $(dump_temacs) @if test -f SATISFIED; then $(RM) SATISFIED; else $(RM) $@; \ - $(RECURSIVE_MAKE) $@; fi + $(MAKE) $(RECURSIVE_MAKE_ARGS) $@; fi #else @$(RM) $@ $(dump_temacs) @@ -611,7 +616,7 @@ if ! test -f dump-size; then \ $(LIB_SRC)/insert-data-in-exec -s $(DUMP_TARGET).dmp > dump-size ; \ $(RM) dump-data.o $(DUMP_TARGET) $(DUMP_TARGET).dmp $(RAW_EXE);\ - $(RECURSIVE_MAKE) $@; \ + $(MAKE) $(RECURSIVE_MAKE_ARGS) $@; \ fi #endif @@ -654,7 +659,7 @@ .PHONY: all-elc all-elc: - +cd .. && $(RECURSIVE_MAKE) + cd .. && $(MAKE) $(RECURSIVE_MAKE_ARGS) ######################################################################### ## Subsidiary dependency rules ## @@ -682,10 +687,10 @@ cd $(LIB_SRC)/ && $(msgfmt) -o emacs.mo emacs.po $(LIB_SRC)/make-msgfile: - +cd $(LIB_SRC) && $(RECURSIVE_MAKE) make-msgfile + cd $(LIB_SRC) && $(MAKE) $(RECURSIVE_MAKE_ARGS) make-msgfile $(LIB_SRC)/make-po: - +cd $(LIB_SRC) && $(RECURSIVE_MAKE) make-po + cd $(LIB_SRC) && $(MAKE) $(RECURSIVE_MAKE_ARGS) make-po #endif /* I18N3 */ @@ -941,7 +946,7 @@ rtc_patch_area -o $@ rtcmacs: $(temacs_deps) rtc_patch.o - $(RM) $(RAW_EXE); $(RECURSIVE_MAKE) $(RAW_EXE) RTC_patch_objs=rtc_patch.o + $(RM) $(RAW_EXE); $(MAKE) $(RECURSIVE_MAKE_ARGS) $(RAW_EXE) RTC_patch_objs=rtc_patch.o mv $(RAW_EXE) rtcmacs .PHONY: run-rtcmacs diff --text -u 'xemacs-21.5.18/src/abbrev.c' 'xemacs-21.5.19/src/abbrev.c' Index: ./src/abbrev.c --- ./src/abbrev.c Wed Jun 5 18:54:52 2002 +++ ./src/abbrev.c Fri Nov 5 08:06:15 2004 @@ -231,7 +231,7 @@ if (wordend <= wordstart) return 0; - p = word = (Ibyte *) ALLOCA (MAX_ICHAR_LEN * (wordend - wordstart)); + p = word = alloca_ibytes (MAX_ICHAR_LEN * (wordend - wordstart)); for (idx = wordstart; idx < wordend; idx++) { Ichar c = BUF_FETCH_CHAR (buf, idx); diff --text -u 'xemacs-21.5.18/src/alloc.c' 'xemacs-21.5.19/src/alloc.c' Index: ./src/alloc.c --- ./src/alloc.c Tue Sep 21 04:19:34 2004 +++ ./src/alloc.c Fri Feb 4 01:14:04 2005 @@ -1,7 +1,7 @@ /* Storage allocation and gc for XEmacs Lisp interpreter. Copyright (C) 1985-1998 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 1996, 2001, 2002, 2003 Ben Wing. + Copyright (C) 1995, 1996, 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -196,7 +196,7 @@ /* "Garbage collecting" */ Lisp_Object Vgc_message; Lisp_Object Vgc_pointer_glyph; -static const Char_ASCII gc_default_message[] = "Garbage collecting"; +static const Ascbyte gc_default_message[] = "Garbage collecting"; Lisp_Object Qgarbage_collecting; static Lisp_Object QSin_garbage_collection; @@ -311,29 +311,74 @@ minimum_address_seen = (char *) val; } -/* like malloc and realloc but check for no memory left. */ - #ifdef ERROR_CHECK_MALLOC static int in_malloc; extern int regex_malloc_disallowed; -#endif + +#define MALLOC_BEGIN() \ +do \ +{ \ + assert (!in_malloc); \ + assert (!regex_malloc_disallowed); \ + in_malloc = 1; \ +} \ +while (0) + +#define FREE_OR_REALLOC_BEGIN(block) \ +do \ +{ \ + /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an \ + error until much later on for many system mallocs, such as \ + the one that comes with Solaris 2.3. FMH!! */ \ + assert (block != (void *) 0xDEADBEEF); \ + /* You cannot free something within dumped space, because there is \ + no longer any sort of malloc structure associated with the block. \ + If you are tripping this, you may need to conditionalize on \ + DUMPEDP. */ \ + assert (!DUMPEDP (block)); \ + MALLOC_BEGIN (); \ +} \ +while (0) + +#define MALLOC_END() \ +do \ +{ \ + in_malloc = 0; \ +} \ +while (0) + +#else /* ERROR_CHECK_MALLOC */ + +#define MALLOC_BEGIN(block) +#define FREE_OR_REALLOC_BEGIN(block) +#define MALLOC_END() + +#endif /* ERROR_CHECK_MALLOC */ + +static void +malloc_after (void *val, Bytecount size) +{ + if (!val && size != 0) + memory_full (); + set_alloc_mins_and_maxes (val, size); +} + +/* like malloc, calloc, realloc, free but: + + -- check for no memory left + -- set internal mins and maxes + -- with error-checking on, check for reentrancy, invalid freeing, etc. +*/ #undef xmalloc void * xmalloc (Bytecount size) { void *val; -#ifdef ERROR_CHECK_MALLOC - assert (!in_malloc); - assert (!regex_malloc_disallowed); - in_malloc = 1; -#endif + MALLOC_BEGIN (); val = malloc (size); -#ifdef ERROR_CHECK_MALLOC - in_malloc = 0; -#endif - if (!val && (size != 0)) memory_full (); - set_alloc_mins_and_maxes (val, size); + MALLOC_END (); + malloc_after (val, size); return val; } @@ -342,18 +387,10 @@ xcalloc (Elemcount nelem, Bytecount elsize) { void *val; -#ifdef ERROR_CHECK_MALLOC - assert (!in_malloc); - assert (!regex_malloc_disallowed); - in_malloc = 1; -#endif + MALLOC_BEGIN (); val= calloc (nelem, elsize); -#ifdef ERROR_CHECK_MALLOC - in_malloc = 0; -#endif - - if (!val && (nelem != 0)) memory_full (); - set_alloc_mins_and_maxes (val, nelem * elsize); + MALLOC_END (); + malloc_after (val, nelem * elsize); return val; } @@ -367,18 +404,10 @@ void * xrealloc (void *block, Bytecount size) { -#ifdef ERROR_CHECK_MALLOC - assert (!in_malloc); - assert (!regex_malloc_disallowed); - in_malloc = 1; -#endif + FREE_OR_REALLOC_BEGIN (block); block = realloc (block, size); -#ifdef ERROR_CHECK_MALLOC - in_malloc = 0; -#endif - - if (!block && (size != 0)) memory_full (); - set_alloc_mins_and_maxes (block, size); + MALLOC_END (); + malloc_after (block, size); return block; } @@ -386,19 +415,11 @@ xfree_1 (void *block) { #ifdef ERROR_CHECK_MALLOC - /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an - error until much later on for many system mallocs, such as - the one that comes with Solaris 2.3. FMH!! */ - assert (block != (void *) 0xDEADBEEF); assert (block); - assert (!in_malloc); - assert (!regex_malloc_disallowed); - in_malloc = 1; #endif /* ERROR_CHECK_MALLOC */ + FREE_OR_REALLOC_BEGIN (block); free (block); -#ifdef ERROR_CHECK_MALLOC - in_malloc = 0; -#endif + MALLOC_END (); } #ifdef ERROR_CHECK_GC @@ -531,7 +552,7 @@ break; } else if (next == 0) - abort (); + ABORT (); else header = next; } @@ -953,6 +974,7 @@ #define FREE_FIXED_TYPE(type, structtype, ptr) do { \ structtype *FFT_ptr = (ptr); \ gc_checking_assert (!LRECORD_FREE_P (FFT_ptr)); \ + gc_checking_assert (!DUMPEDP (FFT_ptr)); \ ADDITIONAL_FREE_##type (FFT_ptr); \ deadbeef_memory (FFT_ptr, sizeof (structtype)); \ PUT_FIXED_TYPE_ON_FREE_LIST (type, structtype, FFT_ptr); \ @@ -2498,7 +2520,7 @@ */ (int nargs, Lisp_Object *args)) { - Ibyte *storage = alloca_array (Ibyte, nargs * MAX_ICHAR_LEN); + Ibyte *storage = alloca_ibytes (nargs * MAX_ICHAR_LEN); Ibyte *p = storage; for (; nargs; nargs--, args++) @@ -2583,7 +2605,9 @@ build_ext_string (const Extbyte *str, Lisp_Object coding_system) { /* Some strlen's crash and burn if passed null. */ - return make_ext_string ((const Extbyte *) str, (str ? strlen(str) : 0), + return make_ext_string ((const Extbyte *) str, + (str ? dfc_external_data_len (str, coding_system) : + 0), coding_system); } @@ -2638,7 +2662,7 @@ */ const struct memory_description free_description[] = { - { XD_LISP_OBJECT, offsetof (struct free_lcrecord_header, chain), 0, 0, + { XD_LISP_OBJECT, offsetof (struct free_lcrecord_header, chain), 0, { 0 }, XD_FLAG_FREE_LISP_OBJECT }, { XD_END } }; @@ -2650,7 +2674,7 @@ struct free_lcrecord_header); const struct memory_description lcrecord_list_description[] = { - { XD_LISP_OBJECT, offsetof (struct lcrecord_list, free), 0, 0, + { XD_LISP_OBJECT, offsetof (struct lcrecord_list, free), 0, { 0 }, XD_FLAG_FREE_LISP_OBJECT }, { XD_END } }; @@ -2792,6 +2816,9 @@ gc_checking_assert (detagged_lisp_object_size (lheader) == list->size); /* Make sure the object isn't already freed. */ gc_checking_assert (!free_header->lcheader.free); + /* Freeing stuff in dumped memory is bad. If you trip this, you + may need to check for this before freeing. */ + gc_checking_assert (!OBJECT_DUMPED_P (lcrecord)); if (implementation->finalizer) implementation->finalizer (lheader, 0); @@ -2891,7 +2918,7 @@ #ifdef DEBUG_XEMACS static const struct memory_description staticpro_one_name_description_1[] = { - { XD_C_STRING, 0 }, + { XD_ASCII_STRING, 0 }, { XD_END } }; @@ -3069,7 +3096,7 @@ pdump_backtrace (); #endif count = 0; /* warning suppression */ - abort (); + ABORT (); } count += delta; return count; @@ -3114,18 +3141,19 @@ return sizeof (Lisp_Object); case XD_OPAQUE_PTR: return sizeof (void *); - case XD_STRUCT_PTR: + case XD_BLOCK_PTR: { EMACS_INT val = lispdesc_indirect_count (desc1->data1, desc, obj); return val * sizeof (void *); } - case XD_STRUCT_ARRAY: + case XD_BLOCK_ARRAY: { EMACS_INT val = lispdesc_indirect_count (desc1->data1, desc, obj); return (val * - lispdesc_structure_size - (rdata, lispdesc_indirect_description (obj, desc1->data2))); + lispdesc_block_size + (rdata, + lispdesc_indirect_description (obj, desc1->data2.descr))); } case XD_OPAQUE_DATA_PTR: return sizeof (void *); @@ -3135,7 +3163,7 @@ description, use it; else compute size based on current union constant. */ const struct sized_memory_description *sdesc = - lispdesc_indirect_description (obj, desc1->data2); + lispdesc_indirect_description (obj, desc1->data2.descr); if (sdesc->size) return sdesc->size; else @@ -3152,7 +3180,7 @@ description, use it; else compute size based on maximum of all possible structures. */ const struct sized_memory_description *sdesc = - lispdesc_indirect_description (obj, desc1->data2); + lispdesc_indirect_description (obj, desc1->data2.descr); if (sdesc->size) return sdesc->size; else @@ -3173,7 +3201,7 @@ return max_size; } } - case XD_C_STRING: + case XD_ASCII_STRING: return sizeof (void *); case XD_DOC_STRING: return sizeof (void *); @@ -3191,7 +3219,7 @@ return sizeof (long); default: stderr_out ("Unsupported dump type : %d\n", desc1->type); - abort (); + ABORT (); } return 0; @@ -3217,18 +3245,15 @@ i.e. by trapping SIGSEGV and SIGBUS.) */ Bytecount -lispdesc_structure_size (const void *obj, - const struct sized_memory_description *sdesc) +lispdesc_block_size_1 (const void *obj, Bytecount size, + const struct memory_description *desc) { EMACS_INT max_offset = -1; int max_offset_pos = -1; int pos; - const struct memory_description *desc; - - if (sdesc->size) - return sdesc->size; - desc = sdesc->description; + if (size) + return size; for (pos = 0; desc[pos].type != XD_END; pos++) { @@ -3236,7 +3261,7 @@ if (offset == max_offset) { stderr_out ("Two relocatable elements at same offset?\n"); - abort (); + ABORT (); } else if (offset > max_offset) { @@ -3405,7 +3430,7 @@ { int i; Bytecount elsize; - elsize = lispdesc_structure_size (data, sdesc); + elsize = lispdesc_block_size (data, sdesc); for (i = 0; i < count; i++) { @@ -3454,7 +3479,7 @@ case XD_LO_LINK: case XD_OPAQUE_PTR: case XD_OPAQUE_DATA_PTR: - case XD_C_STRING: + case XD_ASCII_STRING: case XD_DOC_STRING: break; case XD_LISP_OBJECT: @@ -3491,23 +3516,23 @@ } break; } - case XD_STRUCT_PTR: + case XD_BLOCK_PTR: { EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc, data); const struct sized_memory_description *sdesc = - lispdesc_indirect_description (data, desc1->data2); + lispdesc_indirect_description (data, desc1->data2.descr); const char *dobj = * (const char **) rdata; if (dobj) mark_struct_contents (dobj, sdesc, count); break; } - case XD_STRUCT_ARRAY: + case XD_BLOCK_ARRAY: { EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc, data); const struct sized_memory_description *sdesc = - lispdesc_indirect_description (data, desc1->data2); + lispdesc_indirect_description (data, desc1->data2.descr); mark_struct_contents (rdata, sdesc, count); break; @@ -3521,7 +3546,7 @@ default: stderr_out ("Unsupported description type : %d\n", desc1->type); - abort (); + ABORT (); } } } @@ -3544,7 +3569,7 @@ /* this code should never be reached when configured for KKCC */ stderr_out ("KKCC: Invalid mark_object call.\n"); stderr_out ("Replace mark_object with kkcc_gc_stack_push_lisp_object.\n"); - abort (); + ABORT (); #else /* not USE_KKCC */ tail_recurse: @@ -4669,7 +4694,7 @@ /***** Now we actually start the garbage collection. */ gc_in_progress = 1; - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; gc_generation_number[0]++; @@ -4751,6 +4776,7 @@ mark_object (catch->tag); mark_object (catch->val); mark_object (catch->actual_tag); + mark_object (catch->backtrace); } } @@ -4833,7 +4859,7 @@ #endif recompute_need_to_garbage_collect (); - inhibit_non_essential_printing_operations = 0; + inhibit_non_essential_conversion_operations = 0; gc_in_progress = 0; run_post_gc_actions (); @@ -4887,7 +4913,7 @@ /* Debugging aids. */ static Lisp_Object -gc_plist_hack (const Char_ASCII *name, int value, Lisp_Object tail) +gc_plist_hack (const Ascbyte *name, int value, Lisp_Object tail) { /* C doesn't have local functions (or closures, or GC, or readable syntax, or portable numeric datatypes, or bit-vectors, or characters, or @@ -5394,11 +5420,11 @@ staticpros = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); Dynarr_resize (staticpros, 1410); /* merely a small optimization */ - dump_add_root_struct_ptr (&staticpros, &staticpros_description); + dump_add_root_block_ptr (&staticpros, &staticpros_description); #ifdef DEBUG_XEMACS staticpro_names = Dynarr_new2 (char_ptr_dynarr, char *); Dynarr_resize (staticpro_names, 1410); /* merely a small optimization */ - dump_add_root_struct_ptr (&staticpro_names, &staticpro_names_description); + dump_add_root_block_ptr (&staticpro_names, &staticpro_names_description); #endif init_lcrecord_lists (); diff --text -u 'xemacs-21.5.18/src/alloca.c' 'xemacs-21.5.19/src/alloca.c' Index: ./src/alloca.c --- ./src/alloca.c Wed Oct 1 00:26:39 2003 +++ ./src/alloca.c Tue Jan 25 08:33:46 2005 @@ -339,7 +339,7 @@ a fatal error if "trailer" is null. */ if (trailer == 0) - abort (); + ABORT (); /* Discard segments that do not contain our argument address. */ @@ -348,7 +348,7 @@ block = (long *) trailer->this_address; size = trailer->this_size; if (block == 0 || size == 0) - abort (); + ABORT (); trailer = (struct stk_trailer *) trailer->link; if ((block <= address) && (address < (block + size))) break; @@ -367,7 +367,7 @@ do { if (trailer->this_size <= 0) - abort (); + ABORT (); result += trailer->this_size; trailer = (struct stk_trailer *) trailer->link; } diff --text -u 'xemacs-21.5.18/src/backtrace.h' 'xemacs-21.5.19/src/backtrace.h' Index: ./src/backtrace.h --- ./src/backtrace.h Thu Feb 13 18:57:05 2003 +++ ./src/backtrace.h Sat Jan 29 18:15:58 2005 @@ -141,6 +141,8 @@ /* Stores the actual tag used in `throw'; the same as TAG, unless TAG is Vcatch_everything_tag. */ Lisp_Object actual_tag; + /* A backtrace prior to the throw, used with Vcatch_everything_tag. */ + Lisp_Object backtrace; Lisp_Object val; struct catchtag *next; struct gcpro *gcpro; diff --text -u 'xemacs-21.5.18/src/buffer.c' 'xemacs-21.5.19/src/buffer.c' Index: ./src/buffer.c --- ./src/buffer.c Tue Sep 14 23:32:45 2004 +++ ./src/buffer.c Fri Feb 4 01:14:04 2005 @@ -1,7 +1,7 @@ /* Buffer manipulation primitives for XEmacs. Copyright (C) 1985-1989, 1992-1995 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 1996, 2000, 2001, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -244,10 +244,10 @@ { XD_LISP_OBJECT, offsetof (struct buffer, extent_info) }, - { XD_STRUCT_PTR, offsetof (struct buffer, text), - 1, &buffer_text_description }, - { XD_STRUCT_PTR, offsetof (struct buffer, syntax_cache), - 1, &syntax_cache_description }, + { XD_BLOCK_PTR, offsetof (struct buffer, text), + 1, { &buffer_text_description } }, + { XD_BLOCK_PTR, offsetof (struct buffer, syntax_cache), + 1, { &syntax_cache_description } }, { XD_LISP_OBJECT, offsetof (struct buffer, indirect_children) }, { XD_LISP_OBJECT, offsetof (struct buffer, base_buffer) }, @@ -559,7 +559,7 @@ Lisp_Object cons = Frassq (buf, Vbuffer_alist); Lisp_Object frmcons, devcons, concons; if (NILP (cons)) - return; /* abort() ? */ + return; /* ABORT() ? */ Vbuffer_alist = delq_no_quit (cons, Vbuffer_alist); FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) @@ -1139,7 +1139,7 @@ /* This function can call lisp */ Lisp_Object buf; REGISTER struct buffer *b; - struct gcpro gcpro1, gcpro2; + struct gcpro gcpro1; if (NILP (buffer)) buf = Fcurrent_buffer (); @@ -1190,22 +1190,23 @@ if (BUFFER_LIVE_P (b)) { int speccount = specpdl_depth (); - Lisp_Object tail = Qnil; - GCPRO2 (buf, tail); + GCPRO1 (buf); record_unwind_protect (save_excursion_restore, save_excursion_save ()); Fset_buffer (buf); - /* First run the query functions; if any query is answered no, - don't kill the buffer. */ - EXTERNAL_LIST_LOOP (tail, Vkill_buffer_query_functions) - { - if (NILP (call0 (Fcar (tail)))) - { - UNGCPRO; - return unbind_to (speccount); - } - } + { + /* First run the query functions; if any query is answered no, + don't kill the buffer. */ + EXTERNAL_LIST_LOOP_2 (arg, Vkill_buffer_query_functions) + { + if (NILP (call0 (arg))) + { + UNGCPRO; + return unbind_to (speccount); + } + } + } /* Then run the hooks. */ run_hook (Qkill_buffer_hook); @@ -1374,38 +1375,60 @@ { REGISTER Lisp_Object lynk, prev; struct frame *f = selected_frame (); + int buffer_found = 0; + CHECK_BUFFER (buffer); + if (!BUFFER_LIVE_P (XBUFFER (buffer))) + return Qnil; prev = Qnil; for (lynk = Vbuffer_alist; CONSP (lynk); lynk = XCDR (lynk)) { if (EQ (XCDR (XCAR (lynk)), buffer)) - break; + { + buffer_found = 1; + break; + } prev = lynk; } - /* Effectively do Vbuffer_alist = delq_no_quit (lynk, Vbuffer_alist) */ - if (NILP (prev)) - Vbuffer_alist = XCDR (Vbuffer_alist); + if (buffer_found) + { + /* Effectively do Vbuffer_alist = delq_no_quit (lynk, Vbuffer_alist) */ + if (NILP (prev)) + Vbuffer_alist = XCDR (Vbuffer_alist); + else + XCDR (prev) = XCDR (XCDR (prev)); + XCDR (lynk) = Vbuffer_alist; + Vbuffer_alist = lynk; + } else - XCDR (prev) = XCDR (XCDR (prev)); - XCDR (lynk) = Vbuffer_alist; - Vbuffer_alist = lynk; + Vbuffer_alist = Fcons (Fcons (Fbuffer_name(buffer), buffer), Vbuffer_alist); /* That was the global one. Now do the same thing for the per-frame buffer-alist. */ + buffer_found = 0; prev = Qnil; for (lynk = f->buffer_alist; CONSP (lynk); lynk = XCDR (lynk)) { if (EQ (XCDR (XCAR (lynk)), buffer)) - break; + { + buffer_found = 1; + break; + } prev = lynk; } - /* Effectively do f->buffer_alist = delq_no_quit (lynk, f->buffer_alist) */ - if (NILP (prev)) - f->buffer_alist = XCDR (f->buffer_alist); + if (buffer_found) + { + /* Effectively do f->buffer_alist = delq_no_quit (lynk, f->buffer_alist) */ + if (NILP (prev)) + f->buffer_alist = XCDR (f->buffer_alist); + else + XCDR (prev) = XCDR (XCDR (prev)); + XCDR (lynk) = f->buffer_alist; + f->buffer_alist = lynk; + } else - XCDR (prev) = XCDR (XCDR (prev)); - XCDR (lynk) = f->buffer_alist; - f->buffer_alist = lynk; + f->buffer_alist = Fcons (Fcons (Fbuffer_name(buffer), buffer), + f->buffer_alist); return Qnil; } @@ -1807,25 +1830,33 @@ intern_converting_underscores_to_dashes (#field), plist) ADD_INT (bufz); ADD_INT (z); +#ifdef OLD_BYTE_CHAR ADD_INT (mule_bufmin); ADD_INT (mule_bufmax); ADD_INT (mule_bytmin); ADD_INT (mule_bytmax); ADD_INT (mule_shifter); ADD_BOOL (mule_three_p); +#endif ADD_BOOL (entirely_one_byte_p); ADD_INT (num_ascii_chars); ADD_INT (num_8_bit_fixed_chars); ADD_INT (num_16_bit_fixed_chars); + ADD_INT (cached_charpos); + ADD_INT (cached_bytepos); + ADD_INT (next_cache_pos); + { - Lisp_Object pos[16]; + Lisp_Object pos[NUM_CACHED_POSITIONS]; int i; - for (i = 0; i < 16; i++) + for (i = 0; i < b->text->next_cache_pos; i++) pos[i] = make_int (b->text->mule_charbpos_cache[i]); - plist = cons3 (Flist (16, pos), intern ("mule-charbpos-cache"), plist); - for (i = 0; i < 16; i++) + plist = cons3 (Flist (b->text->next_cache_pos, pos), + intern ("mule-charbpos-cache"), plist); + for (i = 0; i < b->text->next_cache_pos; i++) pos[i] = make_int (b->text->mule_bytebpos_cache[i]); - plist = cons3 (Flist (16, pos), intern ("mule-bytebpos-cache"), plist); + plist = cons3 (Flist (b->text->next_cache_pos, pos), + intern ("mule-bytebpos-cache"), plist); } #undef ADD_INT #undef ADD_BOOL @@ -1941,8 +1972,6 @@ vars_of_buffer (void) { /* This function can GC */ - reinit_vars_of_buffer (); - staticpro (&QSFundamental); staticpro (&QSscratch); @@ -2309,8 +2338,8 @@ syms = XBUFFER (Vbuffer_local_symbols); buffer_defaults_saved_slots = &defs->BUFFER_SLOTS_FIRST_NAME; buffer_local_symbols_saved_slots = &syms->BUFFER_SLOTS_FIRST_NAME; - dump_add_root_struct_ptr (&buffer_defaults_saved_slots, &buffer_slots_description); - dump_add_root_struct_ptr (&buffer_local_symbols_saved_slots, &buffer_slots_description); + dump_add_root_block_ptr (&buffer_defaults_saved_slots, &buffer_slots_description); + dump_add_root_block_ptr (&buffer_local_symbols_saved_slots, &buffer_slots_description); DEFVAR_BUFFER_DEFAULTS ("default-modeline-format", modeline_format /* Default value of `modeline-format' for buffers that don't override it. @@ -2790,7 +2819,7 @@ if ((XINT (buffer_local_flags.slot) != -2 && \ XINT (buffer_local_flags.slot) != -3) \ != !(NILP (XBUFFER (Vbuffer_local_symbols)->slot))) \ - abort (); + ABORT (); #include "bufslots.h" { @@ -2883,7 +2912,7 @@ Extbyte *modname = mswindows_get_module_file_name (); assert (modname); - p = xetcsrchr (modname, '\\'); + p = qxetcsrchr (modname, '\\'); assert (p); XECOPY_TCHAR (p, '\0'); diff --text -u 'xemacs-21.5.18/src/buffer.h' 'xemacs-21.5.19/src/buffer.h' Index: ./src/buffer.h --- ./src/buffer.h Fri Oct 15 02:26:22 2004 +++ ./src/buffer.h Fri Nov 5 08:06:16 2004 @@ -2,7 +2,7 @@ Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 2001, 2002 Ben Wing. + Copyright (C) 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -74,12 +74,16 @@ extent-parent and extent-children. */ +#define NUM_CACHED_POSITIONS 50 +#define NUM_MOVED_POSITIONS 10 + struct buffer_text { Ibyte *beg; /* Actual address of buffer contents. */ Bytebpos gpt; /* Index of gap in buffer. */ + Charbpos bufgpt; /* Equivalent as a Charbpos. */ Bytebpos z; /* Index of end of buffer. */ - Charbpos bufz; /* Equivalent as a Charbpos. */ + Charbpos bufz; /* Equivalent as a Charbpos. */ Bytecount gap_size;/* Size of buffer's gap */ Bytecount end_gap_size;/* Size of buffer's end gap */ long modiff; /* This counts buffer-modification events @@ -90,6 +94,8 @@ time buffer visited or saved a file. */ #ifdef MULE + +#ifdef OLD_BYTE_CHAR /* We keep track of a "known" region for very fast access. This information is text-only so it goes here. We update this at each change to the buffer, so if it's entirely ASCII, these will always @@ -97,11 +103,16 @@ Charbpos mule_bufmin, mule_bufmax; Bytebpos mule_bytmin, mule_bytmax; int mule_shifter, mule_three_p; +#endif + + /* And we also cache NUM_CACHED_POSITIONS positions for fairly fast + access near those positions. */ + Charbpos mule_charbpos_cache[NUM_CACHED_POSITIONS]; + Bytebpos mule_bytebpos_cache[NUM_CACHED_POSITIONS]; + int next_cache_pos; - /* And we also cache 16 positions for fairly fast access near those - positions. */ - Charbpos mule_charbpos_cache[16]; - Bytebpos mule_bytebpos_cache[16]; + Charbpos cached_charpos; + Bytebpos cached_bytepos; /* True if all chars fit into one byte; == (format == FORMAT_8_BIT_FIXED || @@ -117,7 +128,7 @@ /* Currently we only handle 8 bit fixed and default */ Internal_Format format; -#endif +#endif /* MULE */ /* Similar to the above, we keep track of positions for which line number has last been calculated. See line-number.c. */ @@ -312,6 +323,10 @@ #define BYTE_BUF_Z(buf) ((buf)->text->z + 0) #define BUF_Z(buf) ((buf)->text->bufz + 0) +/* Gap location. */ +#define BYTE_BUF_GPT(buf) ((buf)->text->gpt + 0) +#define BUF_GPT(buf) ((buf)->text->bufgpt + 0) + /* Point. */ #define BYTE_BUF_PT(buf) ((buf)->pt + 0) #define BUF_PT(buf) ((buf)->bufpt + 0) @@ -536,69 +551,14 @@ /* Converting between byte and character positions */ /*----------------------------------------------------------------------*/ -#ifdef MULE +/* -/* The basic algorithm we use is to keep track of a known region of - characters in each buffer, all of which are of the same width. We keep - track of the boundaries of the region in both Charbpos and Bytebpos - coordinates and also keep track of the char width, which is 1 - 4 bytes. - If the position we're translating is not in the known region, then we - invoke a function to update the known region to surround the position in - question. This assumes locality of reference, which is usually the - case. - - Note that the function to update the known region can be simple or - complicated depending on how much information we cache. In addition to - the known region, we always cache the correct conversions for point, - BEGV, and ZV, and in addition to this we cache 16 positions where the - conversion is known. We only look in the cache or update it when we - need to move the known region more than a certain amount (currently 50 - chars), and then we throw away a "random" value and replace it with the - newly calculated value. - - Finally, we maintain an extra flag that tracks whether the buffer is - entirely ASCII, to speed up the conversions even more. This flag is - actually of dubious value because in an entirely-ASCII buffer the known - region will always span the entire buffer (in fact, we update the flag - based on this fact), and so all we're saving is a few machine cycles. - - A potentially smarter method than what we do with known regions and - cached positions would be to keep some sort of pseudo-extent layer over - the buffer; maybe keep track of the charbpos/bytebpos correspondence at the - beginning of each line, which would allow us to do a binary search over - the pseudo-extents to narrow things down to the correct line, at which - point you could use a linear movement method. This would also mesh well - with efficiently implementing a line-numbering scheme. However, you - have to weigh the amount of time spent updating the cache vs. the - savings that result from it. In reality, we modify the buffer far less - often than we access it, so a cache of this sort that provides - guaranteed LOG (N) performance (or perhaps N * LOG (N), if we set a - maximum on the cache size) would indeed be a win, particularly in very - large buffers. If we ever implement this, we should probably set a - reasonably high minimum below which we use the old method, because the - time spent updating the fancy cache would likely become dominant when - making buffer modifications in smaller buffers. - - Note also that we have to multiply or divide by the char width in order - to convert the positions. We do some tricks to avoid ever actually - having to do a multiply or divide, because that is typically an - expensive operation (esp. divide). Multiplying or dividing by 1, 2, or - 4 can be implemented simply as a shift left or shift right, and we keep - track of a shifter value (0, 1, or 2) indicating how much to shift. - Multiplying by 3 can be implemented by doubling and then adding the - original value. Dividing by 3, alas, cannot be implemented in any - simple shift/subtract method, as far as I know; so we just do a table - lookup. For simplicity, we use a table of size 128K, which indexes the - "divide-by-3" values for the first 64K non-negative numbers. (Note that - we can increase the size up to 384K, i.e. indexing the first 192K - non-negative numbers, while still using shorts in the array.) This also - means that the size of the known region can be at most 64K for - width-three characters. - - !!#### We should investigate the algorithm in GNU Emacs. I think it - does something similar, but it may differ in some details, and it's - worth seeing if anything can be gleaned. - */ +Info on Byte-Char conversion: + + (Info-goto-node "(internals)Byte-Char Position Conversion") +*/ + +#ifdef MULE Bytebpos charbpos_to_bytebpos_func (struct buffer *buf, Charbpos x); Charbpos bytebpos_to_charbpos_func (struct buffer *buf, Bytebpos x); @@ -623,11 +583,13 @@ retval = (Bytebpos) (x << 1); else if (BUF_FORMAT (buf) == FORMAT_32_BIT_FIXED) retval = (Bytebpos) (x << 2); +#ifdef OLD_BYTE_CHAR else if (x >= buf->text->mule_bufmin && x <= buf->text->mule_bufmax) retval = (buf->text->mule_bytmin + ((x - buf->text->mule_bufmin) << buf->text->mule_shifter) + (buf->text->mule_three_p ? (x - buf->text->mule_bufmin) : (Bytebpos) 0)); +#endif /* OLD_BYTE_CHAR */ else retval = charbpos_to_bytebpos_func (buf, x); #else @@ -654,11 +616,13 @@ retval = (Charbpos) (x >> 1); else if (BUF_FORMAT (buf) == FORMAT_32_BIT_FIXED) retval = (Charbpos) (x >> 2); +#ifdef OLD_BYTE_CHAR else if (x >= buf->text->mule_bytmin && x <= buf->text->mule_bytmax) retval = (buf->text->mule_bufmin + ((buf->text->mule_three_p ? three_to_one_table[x - buf->text->mule_bytmin] : (x - buf->text->mule_bytmin) >> buf->text->mule_shifter))); +#endif /* OLD_BYTE_CHAR */ else retval = bytebpos_to_charbpos_func (buf, x); #else @@ -1071,41 +1035,42 @@ representation is changed to have multiple gaps in it. */ - /* Return the maximum position in the buffer it is safe to scan forwards past N to. This is used to prevent buffer scans from running into the gap (e.g. search.c). All characters between N and CEILING_OF(N) are located contiguous in memory. Note that the character *at* CEILING_OF(N) is not contiguous in memory. */ #define BYTE_BUF_CEILING_OF(b, n) \ - ((n) < (b)->text->gpt && (b)->text->gpt < BYTE_BUF_ZV (b) ? \ - (b)->text->gpt : BYTE_BUF_ZV (b)) -#define BUF_CEILING_OF(b, n) \ - bytebpos_to_charbpos (b, BYTE_BUF_CEILING_OF (b, charbpos_to_bytebpos (b, n))) + ((n) < BYTE_BUF_GPT (b) && BYTE_BUF_GPT (b) < BYTE_BUF_ZV (b) ? \ + BYTE_BUF_GPT (b) : BYTE_BUF_ZV (b)) +#define BUF_CEILING_OF(b, n) \ + ((n) < BUF_GPT (b) && BUF_GPT (b) < BUF_ZV (b) ? \ + BUF_GPT (b) : BUF_ZV (b)) /* Return the minimum position in the buffer it is safe to scan backwards past N to. All characters between FLOOR_OF(N) and N are located contiguous in memory. Note that the character *at* N may not be contiguous in memory. */ -#define BYTE_BUF_FLOOR_OF(b, n) \ - (BYTE_BUF_BEGV (b) < (b)->text->gpt && (b)->text->gpt < (n) ? \ - (b)->text->gpt : BYTE_BUF_BEGV (b)) -#define BUF_FLOOR_OF(b, n) \ - bytebpos_to_charbpos (b, BYTE_BUF_FLOOR_OF (b, charbpos_to_bytebpos (b, n))) +#define BYTE_BUF_FLOOR_OF(b, n) \ + (BYTE_BUF_BEGV (b) < BYTE_BUF_GPT (b) && BYTE_BUF_GPT (b) < (n) ? \ + BYTE_BUF_GPT (b) : BYTE_BUF_BEGV (b)) +#define BUF_FLOOR_OF(b, n) \ + (BUF_BEGV (b) < BUF_GPT (b) && BUF_GPT (b) < (n) ? \ + BUF_GPT (b) : BUF_BEGV (b)) #define BYTE_BUF_CEILING_OF_IGNORE_ACCESSIBLE(b, n) \ - ((n) < (b)->text->gpt && (b)->text->gpt < BYTE_BUF_Z (b) ? \ - (b)->text->gpt : BYTE_BUF_Z (b)) -#define BUF_CEILING_OF_IGNORE_ACCESSIBLE(b, n) \ - bytebpos_to_charbpos \ - (b, BYTE_BUF_CEILING_OF_IGNORE_ACCESSIBLE (b, charbpos_to_bytebpos (b, n))) - -#define BYTE_BUF_FLOOR_OF_IGNORE_ACCESSIBLE(b, n) \ - (BYTE_BUF_BEG (b) < (b)->text->gpt && (b)->text->gpt < (n) ? \ - (b)->text->gpt : BYTE_BUF_BEG (b)) -#define BUF_FLOOR_OF_IGNORE_ACCESSIBLE(b, n) \ - bytebpos_to_charbpos \ - (b, BYTE_BUF_FLOOR_OF_IGNORE_ACCESSIBLE (b, charbpos_to_bytebpos (b, n))) + ((n) < BYTE_BUF_GPT (b) && BYTE_BUF_GPT (b) < BYTE_BUF_Z (b) ? \ + BYTE_BUF_GPT (b) : BYTE_BUF_Z (b)) +#define BUF_CEILING_OF_IGNORE_ACCESSIBLE(b, n) \ + ((n) < BUF_GPT (b) && BUF_GPT (b) < BUF_Z (b) ? \ + BUF_GPT (b) : BUF_Z (b)) + +#define BYTE_BUF_FLOOR_OF_IGNORE_ACCESSIBLE(b, n) \ + (BYTE_BUF_BEG (b) < BYTE_BUF_GPT (b) && BYTE_BUF_GPT (b) < (n) ? \ + BYTE_BUF_GPT (b) : BYTE_BUF_BEG (b)) +#define BUF_FLOOR_OF_IGNORE_ACCESSIBLE(b, n) \ + (BUF_BEG (b) < BUF_GPT (b) && BUF_GPT (b) < (n) ? \ + BUF_GPT (b) : BUF_BEG (b)) /* Iterate over contiguous chunks of text in buffer BUF, starting at POS, of length LEN. Evaluates POS and LEN only once, but BUF multiply. In @@ -1117,7 +1082,7 @@ NOTE: This must be surrounded with braces! */ #define BUFFER_TEXT_LOOP(buf, pos, len, runptr, runlen) \ -Ibyte *runptr; \ +Ibyte *runptr; \ Bytecount runlen; \ Bytebpos BTL_pos = (pos); \ Bytebpos BTL_len = (len); \ diff --text -u 'xemacs-21.5.18/src/bytecode.c' 'xemacs-21.5.19/src/bytecode.c' Index: ./src/bytecode.c --- ./src/bytecode.c Tue Sep 21 04:19:35 2004 +++ ./src/bytecode.c Fri Feb 4 01:14:04 2005 @@ -1377,7 +1377,7 @@ case Bcatch: { Lisp_Object arg = POP; - TOP = internal_catch (TOP, Feval, arg, 0, 0); + TOP = internal_catch (TOP, Feval, arg, 0, 0, 0); break; } @@ -1602,7 +1602,7 @@ } default: - abort(); + ABORT(); break; } return stack_ptr; @@ -1973,7 +1973,7 @@ break; default: - abort(); + ABORT(); break; } } @@ -2049,7 +2049,8 @@ program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (f->instructions)); optimize_byte_code (f->instructions, f->constants, program, &program_length, &varbind_count); - f->specpdl_depth = XINT (Flength (f->arglist)) + varbind_count; + f->specpdl_depth = (unsigned short) (XINT (Flength (f->arglist)) + + varbind_count); f->instructions = make_opaque (program, program_length * sizeof (Opbyte)); } @@ -2178,8 +2179,8 @@ static const struct memory_description compiled_function_description[] = { { XD_INT, offsetof (Lisp_Compiled_Function, args_in_array) }, - { XD_STRUCT_PTR, offsetof (Lisp_Compiled_Function, args), - XD_INDIRECT (0, 0), &lisp_object_description }, + { XD_BLOCK_PTR, offsetof (Lisp_Compiled_Function, args), + XD_INDIRECT (0, 0), { &lisp_object_description } }, { XD_LISP_OBJECT, offsetof (Lisp_Compiled_Function, instructions) }, { XD_LISP_OBJECT, offsetof (Lisp_Compiled_Function, constants) }, { XD_LISP_OBJECT, offsetof (Lisp_Compiled_Function, arglist) }, @@ -2228,7 +2229,7 @@ Lisp_Opaque *opaque = XOPAQUE (f->instructions); Ibyte * const buffer = - alloca_array (Ibyte, OPAQUE_SIZE (opaque) * MAX_ICHAR_LEN); + alloca_ibytes (OPAQUE_SIZE (opaque) * MAX_ICHAR_LEN); Ibyte *bp = buffer; const Opbyte * const program = (const Opbyte *) OPAQUE_DATA (opaque); @@ -2514,7 +2515,7 @@ f->constants = XCDR (tem); return function; } - abort (); + ABORT (); return Qnil; /* not (usually) reached */ } diff --text -u 'xemacs-21.5.18/src/callint.c' 'xemacs-21.5.19/src/callint.c' Index: ./src/callint.c --- ./src/callint.c Tue Sep 21 04:19:35 2004 +++ ./src/callint.c Fri Nov 5 08:06:16 2004 @@ -236,9 +236,8 @@ static Lisp_Object quotify_args (Lisp_Object expr) { - Lisp_Object tail; - EXTERNAL_LIST_LOOP (tail, expr) - XSETCAR (tail, Fquote_maybe (XCAR (tail))); + EXTERNAL_LIST_LOOP_3 (elt, expr, tail) + XSETCAR (tail, Fquote_maybe (elt)); return expr; } @@ -387,7 +386,7 @@ goto lose; } - /* FSFmacs makes an ALLOCA () copy of prompt_data here. + /* FSFmacs makes an ALLOCA() copy of prompt_data here. We're more intelligent about this and just reset prompt_data as necessary. */ /* If either specs or prompt_data is set to a string, use it. */ diff --text -u 'xemacs-21.5.18/src/casefiddle.c' 'xemacs-21.5.19/src/casefiddle.c' Index: ./src/casefiddle.c --- ./src/casefiddle.c Wed Jun 5 18:55:00 2002 +++ ./src/casefiddle.c Fri Nov 5 08:06:16 2004 @@ -51,8 +51,7 @@ { Lisp_Object syntax_table = buf->mirror_syntax_table; Ibyte *storage = - alloca_array (Ibyte, XSTRING_LENGTH (string_or_char) * - MAX_ICHAR_LEN); + alloca_ibytes (XSTRING_LENGTH (string_or_char) * MAX_ICHAR_LEN); Ibyte *newp = storage; Ibyte *oldp = XSTRING_DATA (string_or_char); Ibyte *endp = oldp + XSTRING_LENGTH (string_or_char); diff --text -u 'xemacs-21.5.18/src/charset.h' 'xemacs-21.5.19/src/charset.h' Index: ./src/charset.h --- ./src/charset.h Mon Nov 18 15:52:37 2002 +++ ./src/charset.h Tue Jan 25 08:33:47 2005 @@ -194,40 +194,15 @@ Lisp_Object ccl_program; - /* Unicode translation tables. See unicode.c for the format of these tables. - - NOTE ABOUT DUMPING: We don't currently dump these tables. For one - thing, they're big, and it's very fast to recreate them (a fraction of - a second on modern processors); for another, there isn't currently - support in pdump for this. (At one point I started writing it, in the - form of XD_UNION, but thought better of it.) In order to avoid pdump - problems (and to make the dump data smaller), we free all the tables - at dump time (using the disksave finalization method), set them to - zero, and reinit them to blank when we start up again; they will be - reloaded when `init-mule-at-startup' is called. - - #### This creates a problem w.r.t. user-defined charsets. It would be - inconvenient to require all dumped user-defined charsets to be - reloaded at init time, but that's what currently needs to be done. - The solution is either to go ahead and create pdump support for - dumping the tables, and use it just for these; or to copy the data in - them into a compressed format, write it out to pdump as a single - opaque block, and undo the operation at startup. - - #### There's another problem, having to do with starting up in a - non-ISO-8859-1 directory. We don't load the tables until after we've - parsed the current directories, and we run into a real bootstrapping - problem trying to solve this. Either we'll have to dump all the - tables as-is or make some special provisions for writing extra binary - data into the pdump data, and do the compressed trick mentioned above - for all the tables. */ + /* Unicode translation tables. See unicode.c for the format of these + tables, and discussion of how they are initialized. + */ void *to_unicode_table; void *from_unicode_table; int from_unicode_levels; - unsigned char unicode_table_loaded; - - /* Final byte of this character set in ISO2022 designating escape sequence */ + /* Final byte of this character set in ISO2022 designating escape + sequence */ Ibyte final; /* Number of bytes (1 - 4) required in the internal representation @@ -453,7 +428,7 @@ #ifdef ENABLE_COMPOSITE_CHARS return LEADING_BYTE_COMPOSITE; #else - abort(); + ABORT(); return 0; #endif /* ENABLE_COMPOSITE_CHARS */ } @@ -477,7 +452,7 @@ #ifdef ENABLE_COMPOSITE_CHARS #error Not yet implemented #else - abort(); + ABORT(); return 0; #endif /* ENABLE_COMPOSITE_CHARS */ } diff --text -u 'xemacs-21.5.18/src/chartab.c' 'xemacs-21.5.19/src/chartab.c' Index: ./src/chartab.c --- ./src/chartab.c Tue Sep 21 04:19:35 2004 +++ ./src/chartab.c Tue Jan 25 08:33:47 2005 @@ -195,7 +195,7 @@ { switch (type) { - default: abort(); + default: ABORT(); case CHAR_TABLE_TYPE_GENERIC: return Qgeneric; case CHAR_TABLE_TYPE_SYNTAX: return Qsyntax; case CHAR_TABLE_TYPE_DISPLAY: return Qdisplay; @@ -261,7 +261,7 @@ check_int_range (outrange->row, 32, 127); break; default: - abort (); + ABORT (); } } else @@ -294,7 +294,7 @@ case CHARTAB_RANGE_CHAR: return make_char (range->ch); default: - abort (); + ABORT (); } return Qnil; /* not reached */ } @@ -514,7 +514,7 @@ break; default: - abort (); + ABORT (); def = Qnil; break; } @@ -877,7 +877,7 @@ #endif /* not MULE */ default: - abort (); + ABORT (); } if (UNBOUNDP (retval)) @@ -972,7 +972,7 @@ break; default: - abort (); + ABORT (); } return 0; /* not (usually) reached */ @@ -1426,7 +1426,7 @@ } default: - abort (); + ABORT (); } return 0; @@ -1499,17 +1499,11 @@ chartab_data_validate (Lisp_Object UNUSED (keyword), Lisp_Object value, Error_Behavior UNUSED (errb)) { - Lisp_Object rest; - /* #### should deal with ERRB */ - EXTERNAL_LIST_LOOP (rest, value) + EXTERNAL_PROPERTY_LIST_LOOP_3 (range, data, value) { - Lisp_Object range = XCAR (rest); struct chartab_range dummy; - rest = XCDR (rest); - if (!CONSP (rest)) - signal_error (Qlist_formation_error, "Invalid list format", value); if (CONSP (range)) { if (!CONSP (XCDR (range)) @@ -1567,7 +1561,7 @@ Fput_char_table (make_char (i), val, chartab); } else - abort (); + ABORT (); } else Fput_char_table (range, val, chartab); diff --text -u 'xemacs-21.5.18/src/cm.c' 'xemacs-21.5.19/src/cm.c' Index: ./src/cm.c --- ./src/cm.c Tue Sep 21 04:19:35 2004 +++ ./src/cm.c Tue Jan 25 08:33:48 2005 @@ -101,7 +101,7 @@ if (curX == FrameCols) { if (!MagicWrap || curY >= FrameRows - 1) - abort (); + ABORT (); if (termscript) putc ('\r', termscript); putchar ('\r'); diff --text -u 'xemacs-21.5.18/src/cmdloop.c' 'xemacs-21.5.19/src/cmdloop.c' Index: ./src/cmdloop.c --- ./src/cmdloop.c Tue Sep 21 04:19:35 2004 +++ ./src/cmdloop.c Sat Jan 29 18:15:59 2005 @@ -1,6 +1,6 @@ /* Editor command loop. Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. - Copyright (C) 1995, 1996, 2001, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2001, 2002, 2003 Ben Wing. This file is part of XEmacs. @@ -290,7 +290,7 @@ Otherwise, this function will return normally when all command- line arguments have been processed, the user's initialization file has been read in, and the first frame has been created. */ - internal_catch (Qtop_level, top_level_1, Qnil, 0, 0); + internal_catch (Qtop_level, top_level_1, Qnil, 0, 0, 0); /* If an error occurred during startup and the initial console wasn't created, then die now (the error was already printed out @@ -310,7 +310,7 @@ MARK_MODELINE_CHANGED; /* Now invoke the command loop. It never returns; however, a throw to 'top-level will place us at the end of this loop. */ - internal_catch (Qtop_level, command_loop_2, Qnil, 0, 0); + internal_catch (Qtop_level, command_loop_2, Qnil, 0, 0, 0); /* #### wrong with selected-console? */ /* We don't actually call clear_echo_area() here, partially at least because that runs Lisp code and it may be unsafe @@ -373,7 +373,7 @@ specbind (Qstandard_output, Qt); specbind (Qstandard_input, Qt); - val = internal_catch (Qexit, command_loop_2, Qnil, 0, 0); + val = internal_catch (Qexit, command_loop_2, Qnil, 0, 0, 0); if (EQ (val, Qt)) /* Turn abort-recursive-edit into a quit. */ @@ -440,8 +440,7 @@ if (NILP (catch_errors)) Fcommand_loop_1 (); else - internal_catch (Qtop_level, - cold_load_command_loop, Qnil, 0, 0); + internal_catch (Qtop_level, cold_load_command_loop, Qnil, 0, 0, 0); goto loop; RETURN_NOT_REACHED (Qnil); } diff --text -u 'xemacs-21.5.18/src/compiler.h' 'xemacs-21.5.19/src/compiler.h' Index: ./src/compiler.h --- ./src/compiler.h Fri Oct 15 02:26:22 2004 +++ ./src/compiler.h Tue Jan 25 08:33:48 2005 @@ -1,6 +1,7 @@ /* Compiler-specific definitions for XEmacs. Copyright (C) 1998-1999, 2003 Free Software Foundation, Inc. Copyright (C) 1994 Richard Mlynarik. + Copyright (C) 1995, 1996, 2000-2004 Ben Wing. This file is part of XEmacs. @@ -98,6 +99,12 @@ # endif /* __GNUC__ */ #endif /* GCC_VERSION */ +#ifdef _MSC_VER +#define MSC_VERSION _MSC_VER +#else +#define MSC_VERSION 0 +#endif + /* GCC < 2.6.0 could only declare one attribute per function. In that case, we define DOESNT_RETURN in preference to PRINTF_ARGS, which is only used for checking args against the string spec. */ @@ -123,7 +130,17 @@ # define DOESNT_RETURN_TYPE(rettype) rettype volatile # define DECLARE_DOESNT_RETURN_TYPE(rettype,decl) rettype volatile decl # endif /* GCC_VERSION >= NEED_GCC (2, 5, 0) */ -# else /* not gcc */ +# elif (MSC_VERSION >= 1200) +/* MSVC 6.0 has a mechanism to declare functions which never return */ +# define DOESNT_RETURN_TYPE(rettype) __declspec(noreturn) rettype +# define DECLARE_DOESNT_RETURN_TYPE(rettype,decl) \ + __declspec(noreturn) rettype XCDECL decl +# if (MSC_VERSION >= 1300) +/* VC++ 7 issues warnings about return statements in __declspec(noreturn) + functions; this problem didn't exist under VC++ 6 */ +# define RETURN_NOT_REACHED(value) DO_NOTHING +# endif +# else /* not gcc, VC++ */ # define DOESNT_RETURN_TYPE(rettype) rettype # define DECLARE_DOESNT_RETURN_TYPE(rettype,decl) rettype decl # endif /* GCC_VERSION > NEED_GCC (0, 0, 0) */ @@ -144,8 +161,8 @@ /* More ways to shut up compiler. This works in Fcommand_loop_1(), where there's an infinite loop in a function returning a Lisp object. */ -#if defined (_MSC_VER) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || \ - (defined (DEC_ALPHA) && defined (OSF1)) +#if (defined (_MSC_VER) && MSC_VERSION < 1300) || defined (__SUNPRO_C) || \ + defined (__SUNPRO_CC) || (defined (DEC_ALPHA) && defined (OSF1)) # define DO_NOTHING_DISABLING_NO_RETURN_WARNINGS if (0) return Qnil #else # define DO_NOTHING_DISABLING_NO_RETURN_WARNINGS DO_NOTHING @@ -233,4 +250,44 @@ # define MODULE_API #endif +/* Under "strict-aliasing" assumptions, you're not necessarily allowed to + access the same memory address as two different types. The proper way + around that is with a union. The macros below help out, e.g. the + definition of XE_MAKEPOINTS(val) is + + ANSI_ALIASING_TYPEDEF (POINTS, POINTS); + #define XE_MAKEPOINTS(l) ANSI_ALIASING_CAST (POINTS, l) + + replacing + + BAD!!! #define XE_MAKEPOINTS(l) (* (POINTS *) &(l)) + + On the other hand, if you are just casting from one pointer to the other + in order to pass a pointer to another function, it's probably OK to just + trick GCC by inserting an intermediate cast to (void *), to avoid + warnings about "dereferencing type-punned pointer". #### I don't know + how kosher this is, but do strict-aliasing rules really apply across + functions? + + Note that the input to e.g. VOIDP_CAST must be an lvalue (i.e. not + &(something)), but the value of the macro is also an lvalue, so in place + of `(void **) &foo' you could write `& VOIDP_CAST (foo)' if you are + subsequently dereferencing the value or don't feel comfortable doing a + trick like `(void **) (void *) &foo'. + + Unfortunately, it does not work to just define the union type on the fly in + the cast -- otherwise, we could avoid the need for a typedef. Or rather, + it does work under gcc but not under Visual C++. + + --ben + */ + +#define ANSI_ALIASING_TYPEDEF(name, type) typedef union { char c; type p; } *ANSI_ALIASING_##name +#define ANSI_ALIASING_CAST(name, val) (((ANSI_ALIASING_##name) &(val))->p) +ANSI_ALIASING_TYPEDEF (voidp, void *); +/* VOIDP_CAST: Cast an lvalue to (void *) in a way that is ANSI-aliasing + safe and will not result in GCC warnings. The result is still an + lvalue, so you can assign to it or take its address. */ +#define VOIDP_CAST(l) ANSI_ALIASING_CAST (voidp, l) + #endif /* INCLUDED_compiler_h */ diff --text -u 'xemacs-21.5.18/src/config.h.in' 'xemacs-21.5.19/src/config.h.in' Index: ./src/config.h.in --- ./src/config.h.in Sat Sep 11 14:28:41 2004 +++ ./src/config.h.in Fri Feb 4 01:30:35 2005 @@ -1,6 +1,6 @@ /* XEmacs site configuration template file. -*- C -*- Copyright (C) 1986, 1991-1994, 1998, 1999 Free Software Foundation, Inc. - Copyright (C) 2000, 2001, 2002 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -27,6 +27,21 @@ #ifndef _SRC_CONFIG_H_ #define _SRC_CONFIG_H_ +/* The proper format of this file: + +1. All #undef statements that are changed by configure should go together, + BEFORE the inclusion of the s&m files, and need to be bracketed by + #ifndef WIN32_NO_CONFIGURE. There is currently only one exception to + this: SYSTEM_TYPE. + +2. All other code, except for the things that may be referenced in s&m + files (there is very very little of this) need to go AFTER the inclusion + of s&m files. + +Together, this ensures that the s&m files can override configure +determinations as necessary, and we will properly notice this. +*/ + /* This file now serves both as config.h.in and simply as config.h under Windows NT. Under Windows NT, there is no configure script that @@ -133,12 +148,6 @@ /* Allow the configurer to specify if she wants site-modules. */ #undef INHIBIT_SITE_MODULES -/* This will be removed in 19.15. */ -/* Hah! Try 20.3 ... */ -/* Hah! Try never ... */ -/* If at first you don't succeed, try, try again. */ -/* #define LOSING_BYTECODE */ - /* Undefine on systems which don't have processes */ #undef HAVE_UNIX_PROCESSES @@ -160,6 +169,30 @@ /* Use a debugging malloc? -- experimental */ #undef USE_DEBUG_MALLOC +/* Use the relocating allocator for buffer space? */ +#undef REL_ALLOC + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Is alloca() broken when part of an argument to a function call? */ +#undef BROKEN_ALLOCA_IN_FUNCTION_CALLS + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + /* Compile in TTY support? */ #undef HAVE_TTY @@ -185,18 +218,6 @@ #undef NARROWPROTO #endif /* HAVE_X_WINDOWS */ -#endif /* WIN32_NO_CONFIGURE */ - -#ifdef HAVE_X_WINDOWS -/* The following should always be defined, no matter what xmkmf thinks. */ -#ifndef NeedFunctionPrototypes -#define NeedFunctionPrototypes 1 -#endif -#ifndef FUNCPROTO -#define FUNCPROTO 15 -#endif -#endif /* HAVE_X_WINDOWS */ - /* Defines for building Gtk applications */ #undef HAVE_GNOME #undef HAVE_GTK @@ -205,22 +226,6 @@ #undef HAVE_GLADE_H #undef LIBGLADE_XML_TXTDOMAIN -/* Define HAVE_WINDOW_SYSTEM if any windowing system is available. */ -#if defined (HAVE_GTK) || defined (HAVE_X_WINDOWS) || defined (HAVE_MS_WINDOWS) /* || defined (HAVE_NEXTSTEP) */ -#define HAVE_WINDOW_SYSTEM -#endif - -#if defined (HAVE_GTK) || defined (HAVE_X_WINDOWS) -#define HAVE_XLIKE -#endif - -/* Define HAVE_UNIXOID_EVENT_LOOP if we use select() to wait for events. */ -#if defined (HAVE_X_WINDOWS) || defined (HAVE_TTY) || defined (HAVE_MSG_SELECT) -#define HAVE_UNIXOID_EVENT_LOOP -#endif - -#ifndef WIN32_NO_CONFIGURE /* Defined in xemacs.mak or s/windowsnt.h: */ - /* XFree86 has a different prototype for this function */ #undef HAVE_XREGISTERIMINSTANTIATECALLBACK #undef XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE @@ -343,6 +348,9 @@ /* Can `gettimeofday' accept two arguments? */ #undef GETTIMEOFDAY_ONE_ARGUMENT +/* Is scanf() broken? (Under certain versions of Cygwin) */ +#undef CYGWIN_SCANF_BUG + #undef HAVE_MMAP #undef HAVE_STRCOLL #undef HAVE_GETPGRP @@ -350,6 +358,7 @@ #undef HAVE_INVERSE_HYPERBOLIC +/* Functions in the big list of functions checked for */ #undef HAVE_CBRT #undef HAVE_CLOSEDIR #undef HAVE_DUP2 @@ -357,14 +366,15 @@ #undef HAVE_FMOD #undef HAVE_FPATHCONF #undef HAVE_FREXP +#undef HAVE_FSYNC #undef HAVE_FTIME +#undef HAVE_FTRUNCATE #undef HAVE_GETADDRINFO #undef HAVE_GETHOSTNAME #undef HAVE_GETNAMEINFO #undef HAVE_GETPAGESIZE #undef HAVE_GETRLIMIT #undef HAVE_GETTIMEOFDAY -#undef HAVE_GETWD #undef HAVE_GETCWD #undef HAVE_LINK #undef HAVE_LOGB @@ -376,7 +386,6 @@ #undef HAVE_POLL #undef HAVE_RANDOM #undef HAVE_READLINK -#undef HAVE_REALPATH #undef HAVE_RENAME #undef HAVE_RES_INIT #undef HAVE_RINT @@ -388,21 +397,24 @@ #undef HAVE_SIGBLOCK #undef HAVE_SIGHOLD #undef HAVE_SIGPROCMASK -#undef HAVE_SIGSETJMP #undef HAVE_SNPRINTF -#undef HAVE_STPCPY #undef HAVE_STRERROR #undef HAVE_STRLWR #undef HAVE_STRUPR #undef HAVE_SYMLINK #undef HAVE_TZSET #undef HAVE_ULIMIT +#undef HAVE_UMASK #undef HAVE_USLEEP +#undef HAVE_VLIMIT +#undef HAVE_VSNPRINTF +#undef HAVE_WAITPID +#undef HAVE_WCSCMP +#undef HAVE_WCSLEN + #undef HAVE_UTIME #undef HAVE_UTIMES -#undef HAVE_WAITPID -#undef HAVE_VSNPRINTF -#undef HAVE_VLIMIT +#undef HAVE_SIGSETJMP /* Many flavors of PTY support */ #undef HAVE_GETPT /* glibc's easy pty allocation function */ @@ -428,9 +440,6 @@ #undef HAVE_SYSVIPC #undef HAVE_LOCKF #undef HAVE_FLOCK -#undef HAVE_FSYNC -#undef HAVE_FTRUNCATE -#undef HAVE_UMASK #undef SYSV_SYSTEM_DIR #undef NONSYSTEM_DIR_LIBRARY @@ -667,29 +676,126 @@ #undef gid_t #undef socklen_t -#endif /* WIN32_NO_CONFIGURE */ +/* Enhanced numeric support */ +#undef WITH_NUMBER_TYPES +#undef WITH_GMP +#undef WITH_MP +#undef MP_PREFIX +#undef HAVE_MP_MOVE -/* USER_FULL_NAME returns a string that is the user's full name. - It can assume that the variable `pw' points to the password file - entry for this user. +#undef SIZEOF_SHORT +#undef SIZEOF_INT +#undef SIZEOF_LONG +#undef SIZEOF_LONG_LONG +#undef SIZEOF_VOID_P +#undef SIZEOF_DOUBLE - At some sites, the pw_gecos field contains the user's full name. - If neither this nor any other field contains the right thing, use - pw_name, giving the user's login name, since that is better than - nothing. */ -#define USER_FULL_NAME pw->pw_gecos +/* some systems (Cygwin) typedef u?intptr_t in <sys/types.h> + but the standard is <inttypes.h> + ugliness due to last-resort conditional typedef'ing in lisp.h */ +#undef HAVE_INTPTR_T_IN_SYS_TYPES_H -#if (defined (QUANTIFY) || defined (PURIFY)) && !defined (XLIB_ILLEGAL_ACCESS) -#define XLIB_ILLEGAL_ACCESS 1 -#endif +/* Does the keyword `inline' exist? */ +#undef inline -#define XEMACS_WANTS_C_ALLOCA +/* movemail options */ +/* Should movemail use POP3 for mail access? */ +#undef MAIL_USE_POP +/* Should movemail use kerberos for POP authentication? */ +#undef KERBEROS +/* Should movemail use hesiod for getting POP server host? */ +#undef HESIOD +/* Determine type of mail locking. */ +#undef MAIL_LOCK_LOCKF +#undef MAIL_LOCK_FLOCK +#undef MAIL_LOCK_DOT +#undef MAIL_LOCK_LOCKING +#undef MAIL_LOCK_MMDF + +#undef HAVE_MKSTEMP + +#undef PREFIX_USER_DEFINED +#undef EXEC_PREFIX_USER_DEFINED +#undef MODULEDIR_USER_DEFINED +#undef SITEMODULEDIR_USER_DEFINED +#undef DOCDIR_USER_DEFINED +#undef LISPDIR_USER_DEFINED +#undef PACKAGE_PATH_USER_DEFINED +#undef SITELISPDIR_USER_DEFINED +#undef ARCHLIBDIR_USER_DEFINED +#undef ETCDIR_USER_DEFINED +#undef INFODIR_USER_DEFINED +#undef INFOPATH_USER_DEFINED + +#undef PDUMP + +/* Define DYNODUMP if it is necessary to properly dump on this system. + Currently this is only Solaris 2.x, for x < 6. */ +#undef DYNODUMP + +/* Compile in support for Sun Sparcworks/WorkShop? */ +#undef SUNPRO + +/* Sun SparcStations, SGI machines, and HP9000s700s have built-in + support for playing sound files. (On Suns, the sound support is + usually found in /usr/demo/SOUND - you may need to install the + "SUNWaudmo" package.) */ +#undef HAVE_NATIVE_SOUND + +/* Native sound may be provided via soundcard.h, in various directories */ +#undef SOUNDCARD_H_FILE + +/* Compile in support for NAS (Network Audio System)? + NAS_NO_ERROR_JUMP means that the NAS libraries don't include some + error handling changes. */ +#undef HAVE_NAS_SOUND +#undef NAS_NO_ERROR_JUMP + +/* Compile in support for ESD (Enlightened Sound Daemon)? */ +#undef HAVE_ESD_SOUND + +/* Compile in support for SunPro usage-tracking code? */ +#undef USAGE_TRACKING + +/* Compile in support for Tooltalk? */ +#undef TOOLTALK +/* tt_c.h might be in "Tt" or "desktop" subdirectories */ +#undef TT_C_H_FILE + +/* Toolkits used by lwlib for various widgets... */ + +#undef LWLIB_USES_MOTIF +#undef LWLIB_USES_ATHENA +#undef LWLIB_MENUBARS_LUCID +#undef LWLIB_MENUBARS_MOTIF +#undef LWLIB_SCROLLBARS_LUCID +#undef LWLIB_SCROLLBARS_MOTIF +#undef LWLIB_SCROLLBARS_ATHENA +#undef LWLIB_SCROLLBARS_ATHENA3D +#undef LWLIB_DIALOGS_MOTIF +#undef LWLIB_DIALOGS_ATHENA +#undef LWLIB_DIALOGS_ATHENA3D +#undef LWLIB_TABS_LUCID +#undef LWLIB_WIDGETS_MOTIF +#undef LWLIB_WIDGETS_ATHENA +#undef HAVE_ATHENA_3D + +/* Other things that can be disabled by configure. */ +#undef HAVE_MENUBARS +#undef HAVE_SCROLLBARS +#undef HAVE_DIALOGS +#undef HAVE_TOOLBARS +#undef HAVE_WIDGETS + +#endif /* WIN32_NO_CONFIGURE */ /* alloca twiddling. Because we might be #including alloca.h here, feature test macros - such as _XOPEN_SOURCE must be defined above. */ + such as _XOPEN_SOURCE must be defined above. + + #### This really should go below the inclusion of s&m files, like + everything else. */ -#undef HAVE_ALLOCA_H #ifndef NOT_C_CODE #if defined (__CYGWIN__) /* We get complaints about redefinitions if we just use the __GNUC__ @@ -748,6 +854,24 @@ } #endif +/* This will be removed in 19.15. */ +/* Hah! Try 20.3 ... */ +/* Hah! Try never ... */ +/* If at first you don't succeed, try, try again. */ +/* #define LOSING_BYTECODE */ + +/* USER_FULL_NAME returns a string that is the user's full name. + It can assume that the variable `pw' points to the password file + entry for this user. + + At some sites, the pw_gecos field contains the user's full name. + If neither this nor any other field contains the right thing, use + pw_name, giving the user's login name, since that is better than + nothing. */ +#define USER_FULL_NAME pw->pw_gecos + +#define XEMACS_WANTS_C_ALLOCA + /* s&m files shouldn't be required to define anything, or even to exist. If the s&m files don't define SYSTEM_TYPE, configure will select an appropriate default value. */ @@ -773,75 +897,23 @@ #define SIGRETURN return #endif -#ifndef WIN32_NO_CONFIGURE /* Defined in xemacs.mak or s/windowsnt.h: */ - -/* Use the relocating allocator for buffer space? */ -#undef REL_ALLOC - -/* Define DYNODUMP if it is necessary to properly dump on this system. - Currently this is only Solaris 2.x, for x < 6. */ -#undef DYNODUMP - -/* Compile in support for Sun Sparcworks/WorkShop? */ -#undef SUNPRO - -/* Sun SparcStations, SGI machines, and HP9000s700s have built-in - support for playing sound files. (On Suns, the sound support is - usually found in /usr/demo/SOUND - you may need to install the - "SUNWaudmo" package.) */ -#undef HAVE_NATIVE_SOUND - -/* Native sound may be provided via soundcard.h, in various directories */ -#undef SOUNDCARD_H_FILE - -/* Compile in support for NAS (Network Audio System)? - NAS_NO_ERROR_JUMP means that the NAS libraries don't include some - error handling changes. */ -#undef HAVE_NAS_SOUND -#undef NAS_NO_ERROR_JUMP - -/* Compile in support for ESD (Enlightened Sound Daemon)? */ -#undef HAVE_ESD_SOUND - -/* Compile in support for SunPro usage-tracking code? */ -#undef USAGE_TRACKING - -/* Compile in support for Tooltalk? */ -#undef TOOLTALK -/* tt_c.h might be in "Tt" or "desktop" subdirectories */ -#undef TT_C_H_FILE - -/* Toolkits used by lwlib for various widgets... */ - -#undef LWLIB_USES_MOTIF -#undef LWLIB_USES_ATHENA -#undef LWLIB_MENUBARS_LUCID -#undef LWLIB_MENUBARS_MOTIF -#undef LWLIB_SCROLLBARS_LUCID -#undef LWLIB_SCROLLBARS_MOTIF -#undef LWLIB_SCROLLBARS_ATHENA -#undef LWLIB_SCROLLBARS_ATHENA3D -#undef LWLIB_DIALOGS_MOTIF -#undef LWLIB_DIALOGS_ATHENA -#undef LWLIB_DIALOGS_ATHENA3D -#undef LWLIB_TABS_LUCID -#undef LWLIB_WIDGETS_MOTIF -#undef LWLIB_WIDGETS_ATHENA -#undef HAVE_ATHENA_3D - -/* Other things that can be disabled by configure. */ -#undef HAVE_MENUBARS -#undef HAVE_SCROLLBARS -#undef HAVE_DIALOGS -#undef HAVE_TOOLBARS -#undef HAVE_WIDGETS - -#endif /* WIN32_NO_CONFIGURE */ +/* Define HAVE_WINDOW_SYSTEM if any windowing system is available. */ +#if defined (HAVE_GTK) || defined (HAVE_X_WINDOWS) || defined (HAVE_MS_WINDOWS) /* || defined (HAVE_NEXTSTEP) */ +#define HAVE_WINDOW_SYSTEM +#endif #if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_DIALOGS) || defined (HAVE_TOOLBARS) || defined (HAVE_WIDGETS) #define HAVE_GUI_OBJECTS #endif +#if defined (HAVE_MENUBARS) || defined (HAVE_DIALOGS) +#define HAVE_POPUPS +#endif + +#if defined (HAVE_GTK) || defined (HAVE_X_WINDOWS) +#define HAVE_XLIKE +#endif + /* For the moment, Athena widgets and dialogs may be very unstable and not working well, but things under Windows work much better. configure by default tries to turn Windows widgets and dialogs on, but the Athena @@ -854,8 +926,23 @@ #define HAVE_X_DIALOGS #endif -#if defined (HAVE_MENUBARS) || defined (HAVE_DIALOGS) -#define HAVE_POPUPS +#ifdef HAVE_X_WINDOWS +/* The following should always be defined, no matter what xmkmf thinks. */ +#ifndef NeedFunctionPrototypes +#define NeedFunctionPrototypes 1 +#endif +#ifndef FUNCPROTO +#define FUNCPROTO 15 +#endif +#endif /* HAVE_X_WINDOWS */ + +#if (defined (QUANTIFY) || defined (PURIFY)) && !defined (XLIB_ILLEGAL_ACCESS) +#define XLIB_ILLEGAL_ACCESS 1 +#endif + +/* Define HAVE_UNIXOID_EVENT_LOOP if we use select() to wait for events. */ +#if defined (HAVE_X_WINDOWS) || defined (HAVE_TTY) || defined (HAVE_MSG_SELECT) +#define HAVE_UNIXOID_EVENT_LOOP #endif /* If you are using SunOS 4.1.1 and X11r5, then you need this patch. @@ -891,25 +978,6 @@ #define listen Rlisten #endif /* HAVE_SOCKS && !DO_NOT_SOCKSIFY */ -#ifndef WIN32_NO_CONFIGURE /* Defined in xemacs.mak or s/windowsnt.h: */ - -#undef SIZEOF_SHORT -#undef SIZEOF_INT -#undef SIZEOF_LONG -#undef SIZEOF_LONG_LONG -#undef SIZEOF_VOID_P -#undef SIZEOF_DOUBLE - -/* some systems (Cygwin) typedef u?intptr_t in <sys/types.h> - but the standard is <inttypes.h> - ugliness due to last-resort conditional typedef'ing in lisp.h */ -#undef HAVE_INTPTR_T_IN_SYS_TYPES_H - -/* Does the keyword `inline' exist? */ -#undef inline - -#endif /* WIN32_NO_CONFIGURE */ - #ifndef BITS_PER_CHAR #define BITS_PER_CHAR 8 #endif @@ -920,13 +988,6 @@ #define VOID_P_BITS (SIZEOF_VOID_P * BITS_PER_CHAR) #define DOUBLE_BITS (SIZEOF_DOUBLE * BITS_PER_CHAR) -/* Enhanced numeric support */ -#undef WITH_NUMBER_TYPES -#undef WITH_GMP -#undef WITH_MP -#undef MP_PREFIX -#undef HAVE_MP_MOVE - /* Use `INLINE_HEADER' to define inline functions in .h files. Use `inline static' to define inline functions in .c files. See the Internals manual for examples and more information. */ @@ -957,7 +1018,6 @@ # if defined (__cplusplus) /* Avoid C++ keywords used as ordinary C identifiers */ # define new c_new -# define this c_this # define catch c_catch # define EXTERN_C extern "C" @@ -988,41 +1048,6 @@ # define JMP_BUF jmp_buf #endif -#ifndef WIN32_NO_CONFIGURE /* Defined in xemacs.mak or s/windowsnt.h: */ - -/* movemail options */ -/* Should movemail use POP3 for mail access? */ -#undef MAIL_USE_POP -/* Should movemail use kerberos for POP authentication? */ -#undef KERBEROS -/* Should movemail use hesiod for getting POP server host? */ -#undef HESIOD -/* Determine type of mail locking. */ -#undef MAIL_LOCK_LOCKF -#undef MAIL_LOCK_FLOCK -#undef MAIL_LOCK_DOT -#undef MAIL_LOCK_LOCKING -#undef MAIL_LOCK_MMDF - -#undef HAVE_MKSTEMP - -#undef PREFIX_USER_DEFINED -#undef EXEC_PREFIX_USER_DEFINED -#undef MODULEDIR_USER_DEFINED -#undef SITEMODULEDIR_USER_DEFINED -#undef DOCDIR_USER_DEFINED -#undef LISPDIR_USER_DEFINED -#undef PACKAGE_PATH_USER_DEFINED -#undef SITELISPDIR_USER_DEFINED -#undef ARCHLIBDIR_USER_DEFINED -#undef ETCDIR_USER_DEFINED -#undef INFODIR_USER_DEFINED -#undef INFOPATH_USER_DEFINED - -#undef PDUMP - -#endif /* WIN32_NO_CONFIGURE */ - /* For the moment, we go ahead and keep this, since it's used in mouse.el. #### font-lock does its own version using parse-partial-sexp. We should merge the two. */ diff --text -u 'xemacs-21.5.18/src/console-impl.h' 'xemacs-21.5.19/src/console-impl.h' Index: ./src/console-impl.h --- ./src/console-impl.h Sat Sep 20 10:14:29 2003 +++ ./src/console-impl.h Fri Jan 28 11:58:51 2005 @@ -192,6 +192,7 @@ int depth); Lisp_Object (*color_instance_rgb_components_method) (Lisp_Color_Instance *); int (*valid_color_name_p_method) (struct device *, Lisp_Object color); + Lisp_Object (*color_list_method) (void); /* font methods */ int (*initialize_font_instance_method) (Lisp_Font_Instance *, @@ -206,7 +207,7 @@ Lisp_Object (*font_instance_truename_method) (Lisp_Font_Instance *, Error_Behavior errb); Lisp_Object (*font_instance_properties_method) (Lisp_Font_Instance *); - Lisp_Object (*list_fonts_method) (Lisp_Object pattern, + Lisp_Object (*font_list_method) (Lisp_Object pattern, Lisp_Object device, Lisp_Object maxnumber); Lisp_Object (*find_charset_font_method) (Lisp_Object device, @@ -382,7 +383,7 @@ add_entry_to_console_type_list (Q##type, type##_console_methods); \ type##_console_methods->image_conversion_list = Qnil; \ staticpro_nodump (&type##_console_methods->image_conversion_list); \ - dump_add_root_struct_ptr (&type##_console_methods, &console_methods_description); \ + dump_add_root_block_ptr (&type##_console_methods, &console_methods_description); \ } while (0) #define REINITIALIZE_CONSOLE_TYPE(type) do { \ diff --text -u 'xemacs-21.5.18/src/console-msw.c' 'xemacs-21.5.19/src/console-msw.c' Index: ./src/console-msw.c --- ./src/console-msw.c Tue Sep 21 04:19:36 2004 +++ ./src/console-msw.c Fri Nov 5 08:06:18 2004 @@ -29,6 +29,8 @@ Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0 */ +/* See win32.c for info about the different Windows files in XEmacs. */ + #include <config.h> #include "lisp.h" @@ -92,8 +94,7 @@ GetConsoleHwnd (void) { HWND hwndFound; - Ibyte newtitleint[200]; - Extbyte *newtitle; + Ascbyte newtitle[100]; Extbyte *oldtitle; int numchars; @@ -112,14 +113,12 @@ /* format a "unique" new title */ - qxesprintf (newtitleint, "%ld/%ld", GetTickCount (), - GetCurrentProcessId ()); - - C_STRING_TO_TSTR (newtitleint, newtitle); + sprintf (newtitle, "%ld/%ld", GetTickCount (), GetCurrentProcessId ()); - /* change current window title */ + /* change current window title; we may be called during armageddon + so don't do any conversion */ - qxeSetConsoleTitle (newtitle); + SetConsoleTitleA (newtitle); /* ensure window title has been updated */ @@ -127,7 +126,7 @@ /* look for NewWindowTitle */ - hwndFound = qxeFindWindow (NULL, newtitle); + hwndFound = FindWindowA (NULL, newtitle); /* restore original window title */ @@ -242,7 +241,7 @@ mswindows_ensure_console_buffered (); mswindows_show_console (); - if (initialized && !inhibit_non_essential_printing_operations) + if (initialized && !inhibit_non_essential_conversion_operations) { const Extbyte *extptr; Bytecount extlen; @@ -253,7 +252,10 @@ extlen / XETCHAR_SIZE, &num_written, NULL); } else - return WriteConsoleA (mswindows_console_buffer, (char *) ptr, len, +#ifdef NON_ASCII_INTERNAL_FORMAT +#error Do something here +#endif + return WriteConsoleA (mswindows_console_buffer, (Chbyte *) ptr, len, &num_written, NULL); } @@ -285,7 +287,7 @@ write_string_to_mswindows_debugging_output (const Ibyte *str, Bytecount len) { const Extbyte *extptr; - if (initialized && !inhibit_non_essential_printing_operations) + if (initialized && !inhibit_non_essential_conversion_operations) { TO_EXTERNAL_FORMAT (DATA, (str, len), C_STRING_ALLOCA, extptr, @@ -294,6 +296,9 @@ } else { +#ifdef NON_ASCII_INTERNAL_FORMAT +#error Do something here +#endif /* STR may not be null-terminated so make it that way. */ Extbyte *ext = alloca_extbytes (len + 1); memcpy (ext, str, len); @@ -505,7 +510,6 @@ no effect. */ (message_, flags, title)) { - Lisp_Object tail; Extbyte *msgout; Extbyte *titleout = 0; UINT sty = 0; @@ -525,44 +529,45 @@ LISP_STRING_TO_TSTR (title, titleout); } - EXTERNAL_LIST_LOOP (tail, flags) - { - Lisp_Object st = XCAR (tail); - CHECK_SYMBOL (st); - if (0) - ; + { + EXTERNAL_LIST_LOOP_2 (st, flags) + { + CHECK_SYMBOL (st); + if (0) + ; #define FROB(sym, val) else if (EQ (st, sym)) sty |= val - FROB (Qabortretryignore, MB_ABORTRETRYIGNORE); - FROB (Qapplmodal, MB_APPLMODAL); - FROB (Qdefault_desktop_only, MB_DEFAULT_DESKTOP_ONLY); - FROB (Qdefbutton1, MB_DEFBUTTON1); - FROB (Qdefbutton2, MB_DEFBUTTON2); - FROB (Qdefbutton3, MB_DEFBUTTON3); - FROB (Qdefbutton4, MB_DEFBUTTON4); - FROB (Qhelp, MB_HELP); - FROB (Qiconasterisk, MB_ICONASTERISK); - FROB (Qiconexclamation, MB_ICONEXCLAMATION); - FROB (Qiconhand, MB_ICONHAND); - FROB (Qiconinformation, MB_ICONINFORMATION); - FROB (Qiconquestion, MB_ICONQUESTION); - FROB (Qiconstop, MB_ICONSTOP); - FROB (Qok, MB_OK); - FROB (Qokcancel, MB_OKCANCEL); - FROB (Qretrycancel, MB_RETRYCANCEL); - FROB (Qright, MB_RIGHT); - FROB (Qrtlreading, MB_RTLREADING); - FROB (Qservice_notification, MB_SERVICE_NOTIFICATION); - FROB (Qsetforeground, MB_SETFOREGROUND); - FROB (Qsystemmodal, MB_SYSTEMMODAL); - FROB (Qtaskmodal, MB_TASKMODAL); - FROB (Qtopmost, MB_TOPMOST); - FROB (Qyesno, MB_YESNO); - FROB (Qyesnocancel, MB_YESNOCANCEL); + FROB (Qabortretryignore, MB_ABORTRETRYIGNORE); + FROB (Qapplmodal, MB_APPLMODAL); + FROB (Qdefault_desktop_only, MB_DEFAULT_DESKTOP_ONLY); + FROB (Qdefbutton1, MB_DEFBUTTON1); + FROB (Qdefbutton2, MB_DEFBUTTON2); + FROB (Qdefbutton3, MB_DEFBUTTON3); + FROB (Qdefbutton4, MB_DEFBUTTON4); + FROB (Qhelp, MB_HELP); + FROB (Qiconasterisk, MB_ICONASTERISK); + FROB (Qiconexclamation, MB_ICONEXCLAMATION); + FROB (Qiconhand, MB_ICONHAND); + FROB (Qiconinformation, MB_ICONINFORMATION); + FROB (Qiconquestion, MB_ICONQUESTION); + FROB (Qiconstop, MB_ICONSTOP); + FROB (Qok, MB_OK); + FROB (Qokcancel, MB_OKCANCEL); + FROB (Qretrycancel, MB_RETRYCANCEL); + FROB (Qright, MB_RIGHT); + FROB (Qrtlreading, MB_RTLREADING); + FROB (Qservice_notification, MB_SERVICE_NOTIFICATION); + FROB (Qsetforeground, MB_SETFOREGROUND); + FROB (Qsystemmodal, MB_SYSTEMMODAL); + FROB (Qtaskmodal, MB_TASKMODAL); + FROB (Qtopmost, MB_TOPMOST); + FROB (Qyesno, MB_YESNO); + FROB (Qyesnocancel, MB_YESNOCANCEL); #undef FROB - else - invalid_constant ("Unrecognized flag", st); - } + else + invalid_constant ("Unrecognized flag", st); + } + } { int retval = qxeMessageBox (NULL, msgout, titleout, sty); diff --text -u 'xemacs-21.5.18/src/console-msw.h' 'xemacs-21.5.19/src/console-msw.h' Index: ./src/console-msw.h --- ./src/console-msw.h Sun Mar 9 11:27:40 2003 +++ ./src/console-msw.h Fri Nov 5 08:06:18 2004 @@ -35,6 +35,8 @@ #ifndef INCLUDED_console_msw_h_ #define INCLUDED_console_msw_h_ +/* See win32.c for info about the different Windows files in XEmacs. */ + #include "console.h" #include "syswindows.h" @@ -82,6 +84,9 @@ int height; } XEMACS_RECT_WH; +ANSI_ALIASING_TYPEDEF (POINTS, POINTS); +#define XE_MAKEPOINTS(l) ANSI_ALIASING_CAST (POINTS, l) + /* * Random globals */ diff --text -u 'xemacs-21.5.18/src/console-stream.c' 'xemacs-21.5.19/src/console-stream.c' Index: ./src/console-stream.c --- ./src/console-stream.c Wed Oct 20 12:43:00 2004 +++ ./src/console-stream.c Tue Jan 25 08:33:48 2005 @@ -227,25 +227,25 @@ static void stream_window_output_begin (struct window *UNUSED (w)) { - abort (); + ABORT (); } static void stream_window_output_end (struct window *UNUSED (w)) { - abort (); + ABORT (); } static void stream_frame_output_begin (struct frame *UNUSED (f)) { - abort (); + ABORT (); } static void stream_frame_output_end (struct frame *UNUSED (f)) { - abort (); + ABORT (); } static void @@ -257,7 +257,7 @@ int UNUSED (cursor_width), int UNUSED (cursor_height)) { - abort (); + ABORT (); } static void @@ -268,7 +268,7 @@ Lisp_Object UNUSED (bcolor), Lisp_Object UNUSED (background_pixmap)) { - abort (); + ABORT (); } static int diff --text -u 'xemacs-21.5.18/src/console-x-impl.h' 'xemacs-21.5.19/src/console-x-impl.h' Index: ./src/console-x-impl.h --- ./src/console-x-impl.h Sun Mar 9 11:27:40 2003 +++ ./src/console-x-impl.h Fri Nov 5 08:06:18 2004 @@ -260,7 +260,7 @@ /* This flag tells us if the menubar contents are up-to-date with respect to the current menubar structure. If we want to actually pull down a menu and this is false, then we need to update things. */ - char menubar_contents_up_to_date; + Boolbyte menubar_contents_up_to_date; /* The icon pixmaps; these are Lisp_Image_Instance objects, or Qnil. */ Lisp_Object icon_pixmap; @@ -279,7 +279,7 @@ #endif /* HAVE_TOOLBARS */ /* geometry string that ought to be freed. */ - char *geom_free_me_please; + Ascbyte *geom_free_me_please; #ifdef HAVE_XIM XPoint xic_spot; /* Spot Location cache */ diff --text -u 'xemacs-21.5.18/src/console-x.h' 'xemacs-21.5.19/src/console-x.h' Index: ./src/console-x.h --- ./src/console-x.h Sun Mar 9 11:27:40 2003 +++ ./src/console-x.h Mon Jan 17 19:10:18 2005 @@ -36,11 +36,14 @@ #ifdef HAVE_X_WINDOWS #include "console.h" +/* must come before Xutil.h, which is included indirectly from xintrinsic.h, + to avoid breakage in keysym-parsing macros from X11R6, at least X.org as + of 2005-01-17, and probably XFree86 too from reports on c.e.x */ +#include <X11/keysym.h> #include "xintrinsic.h" #include "../lwlib/lwlib.h" #include <X11/cursorfont.h> -#include <X11/keysym.h> #include <X11/Xatom.h> #include <X11/StringDefs.h> diff --text -u 'xemacs-21.5.18/src/console.c' 'xemacs-21.5.19/src/console.c' Index: ./src/console.c --- ./src/console.c Wed Oct 20 02:19:07 2004 +++ ./src/console.c Fri Feb 4 01:14:04 2005 @@ -115,9 +115,9 @@ static const struct memory_description console_data_description_1 []= { #ifdef HAVE_TTY - { XD_STRUCT_PTR, tty_console, 1, &tty_console_data_description}, + { XD_BLOCK_PTR, tty_console, 1, { &tty_console_data_description} }, #endif - { XD_STRUCT_PTR, stream_console, 1, &stream_console_data_description}, + { XD_BLOCK_PTR, stream_console, 1, { &stream_console_data_description} }, { XD_END } }; @@ -129,10 +129,10 @@ { XD_INT, offsetof (struct console, contype) }, #define MARKED_SLOT(x) { XD_LISP_OBJECT, offsetof (struct console, x) }, #include "conslots.h" - { XD_STRUCT_PTR, offsetof (struct console, conmeths), 1, - &console_methods_description }, + { XD_BLOCK_PTR, offsetof (struct console, conmeths), 1, + { &console_methods_description } }, { XD_UNION, offsetof (struct console, console_data), - XD_INDIRECT (0, 0), &console_data_description }, + XD_INDIRECT (0, 0), { &console_data_description } }, { XD_END } }; @@ -260,7 +260,7 @@ if (EQ (type, Qstream)) return stream_console; - abort (); /* should never happen */ + ABORT (); /* should never happen */ return dead_console; } @@ -1227,7 +1227,8 @@ static const struct memory_description cte_description_1[] = { { XD_LISP_OBJECT, offsetof (console_type_entry, symbol) }, - { XD_STRUCT_PTR, offsetof (console_type_entry, meths), 1, &console_methods_description }, + { XD_BLOCK_PTR, offsetof (console_type_entry, meths), 1, + { &console_methods_description } }, { XD_END } }; @@ -1263,7 +1264,7 @@ console_type_create (void) { the_console_type_entry_dynarr = Dynarr_new (console_type_entry); - dump_add_root_struct_ptr (&the_console_type_entry_dynarr, &cted_description); + dump_add_root_block_ptr (&the_console_type_entry_dynarr, &cted_description); Vconsole_type_list = Qnil; staticpro (&Vconsole_type_list); @@ -1289,8 +1290,6 @@ void vars_of_console (void) { - reinit_vars_of_console (); - DEFVAR_LISP ("create-console-hook", &Vcreate_console_hook /* Function or functions to call when a console is created. One argument, the newly-created console. @@ -1474,8 +1473,8 @@ syms = XCONSOLE (Vconsole_local_symbols); console_defaults_saved_slots = &defs->CONSOLE_SLOTS_FIRST_NAME; console_local_symbols_saved_slots = &syms->CONSOLE_SLOTS_FIRST_NAME; - dump_add_root_struct_ptr (&console_defaults_saved_slots, &console_slots_description); - dump_add_root_struct_ptr (&console_local_symbols_saved_slots, &console_slots_description); + dump_add_root_block_ptr (&console_defaults_saved_slots, &console_slots_description); + dump_add_root_block_ptr (&console_local_symbols_saved_slots, &console_slots_description); DEFVAR_CONSOLE_DEFAULTS ("default-function-key-map", function_key_map /* Default value of `function-key-map' for consoles that don't override it. @@ -1566,6 +1565,6 @@ if ((XINT (console_local_flags.slot) != -2 && \ XINT (console_local_flags.slot) != -3) \ != !(NILP (XCONSOLE (Vconsole_local_symbols)->slot))) \ - abort (); + ABORT (); #include "conslots.h" } diff --text -u 'xemacs-21.5.18/src/data.c' 'xemacs-21.5.19/src/data.c' Index: ./src/data.c --- ./src/data.c Tue Sep 21 04:19:36 2004 +++ ./src/data.c Fri Feb 4 01:14:04 2005 @@ -2589,9 +2589,9 @@ static const struct memory_description weak_list_description[] = { { XD_LISP_OBJECT, offsetof (struct weak_list, list), - 0, 0, XD_FLAG_NO_KKCC }, + 0, { 0 }, XD_FLAG_NO_KKCC }, { XD_LO_LINK, offsetof (struct weak_list, next_weak), - 0, 0, XD_FLAG_NO_KKCC }, + 0, { 0 }, XD_FLAG_NO_KKCC }, { XD_END } }; @@ -2733,7 +2733,7 @@ break; default: - abort (); + ABORT (); } if (need_to_mark_elem && ! marked_p (elem)) @@ -2897,7 +2897,7 @@ case WEAK_LIST_VALUE_ASSOC: return Qvalue_assoc; case WEAK_LIST_FULL_ASSOC: return Qfull_assoc; default: - abort (); + ABORT (); } return Qnil; /* not (usually) reached */ @@ -3299,11 +3299,11 @@ is marked here. */ static const struct memory_description ephemeron_description[] = { { XD_LISP_OBJECT, offsetof(struct ephemeron, key), - 0, 0, XD_FLAG_NO_KKCC }, + 0, { 0 }, XD_FLAG_NO_KKCC }, { XD_LISP_OBJECT, offsetof(struct ephemeron, cons_chain), - 0, 0, XD_FLAG_NO_KKCC }, + 0, { 0 }, XD_FLAG_NO_KKCC }, { XD_LISP_OBJECT, offsetof(struct ephemeron, value), - 0, 0, XD_FLAG_NO_KKCC }, + 0, { 0 }, XD_FLAG_NO_KKCC }, { XD_END } }; diff --text -u 'xemacs-21.5.18/src/database.c' 'xemacs-21.5.19/src/database.c' Index: ./src/database.c --- ./src/database.c Tue Sep 21 04:19:37 2004 +++ ./src/database.c Sat Jan 22 05:07:06 2005 @@ -47,7 +47,7 @@ #ifdef HAVE_INTTYPES_H #define __BIT_TYPES_DEFINED__ #include <inttypes.h> -#ifndef __FreeBSD__ +#if !defined(__FreeBSD__) && !defined(__NetBSD__) typedef uint8_t u_int8_t; typedef uint16_t u_int16_t; typedef uint32_t u_int32_t; @@ -327,13 +327,13 @@ } static Lisp_Object -dbm_type (Lisp_Database *db) +dbm_type (Lisp_Database *UNUSED (db)) { return Qdbm; } static Lisp_Object -dbm_subtype (Lisp_Database *db) +dbm_subtype (Lisp_Database *UNUSED (db)) { return Qnil; } diff --text -u 'xemacs-21.5.18/src/debug.c' 'xemacs-21.5.19/src/debug.c' Index: ./src/debug.c --- ./src/debug.c Fri Feb 21 15:56:56 2003 +++ ./src/debug.c Fri Nov 5 08:06:19 2004 @@ -207,5 +207,4 @@ void vars_of_debug (void) { - reinit_vars_of_debug (); } diff --text -u 'xemacs-21.5.18/src/debug.h' 'xemacs-21.5.19/src/debug.h' Index: ./src/debug.h --- ./src/debug.h Sun Jan 12 20:08:10 2003 +++ ./src/debug.h Tue Jan 25 08:33:49 2005 @@ -64,7 +64,7 @@ stderr_out ("Assertion failed in %s at line %d\n", \ __FILE__, __LINE__); \ else \ - abort (); \ + ABORT (); \ } \ } \ } while (0) diff --text -u 'xemacs-21.5.18/src/depend' 'xemacs-21.5.19/src/depend' Index: ./src/depend --- ./src/depend Thu Sep 23 06:54:47 2004 +++ ./src/depend Sat Jan 29 07:52:28 2005 @@ -145,7 +145,7 @@ extents.o: $(LISP_H) backtrace.h buffer.h bufslots.h casetab.h charset.h chartab.h console.h debug.h device.h elhash.h extents-impl.h extents.h faces.h frame.h glyphs.h gutter.h insdel.h keymap.h opaque.h process.h profile.h redisplay.h scrollbar.h specifier.h window-impl.h window.h winslots.h faces.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h conslots.h console-impl.h console.h device-impl.h device.h devslots.h elhash.h extents-impl.h extents.h faces.h frame-impl.h frame.h frameslots.h glyphs.h objects-impl.h objects.h redisplay.h scrollbar.h specifier.h window-impl.h window.h winslots.h file-coding.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h coding-system-slots.h elhash.h file-coding.h insdel.h lstream.h opaque.h -fileio.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h coding-system-slots.h console.h device.h events.h file-coding.h frame.h insdel.h intl-auto-encap-win32.h lstream.h ndir.h process.h redisplay.h scrollbar.h sysdep.h sysdir.h sysfile.h sysproc.h syspwd.h syssignal.h systime.h syswindows.h window-impl.h window.h winslots.h +fileio.o: $(LISP_H) backtrace.h buffer.h bufslots.h casetab.h charset.h chartab.h coding-system-slots.h console.h device.h events.h file-coding.h frame.h insdel.h intl-auto-encap-win32.h lstream.h ndir.h process.h profile.h redisplay.h scrollbar.h sysdep.h sysdir.h sysfile.h sysproc.h syspwd.h syssignal.h systime.h syswindows.h window-impl.h window.h winslots.h filelock.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h ndir.h paths.h sysdir.h sysfile.h sysproc.h syspwd.h syssignal.h systime.h filemode.o: $(LISP_H) sysfile.h floatfns.o: $(LISP_H) sysfloat.h syssignal.h @@ -203,13 +203,13 @@ offix.o: offix-cursors.h offix-types.h offix.h xintrinsic.h opaque.o: $(LISP_H) opaque.h print.o: $(LISP_H) backtrace.h buffer.h bufslots.h bytecode.h casetab.h charset.h chartab.h conslots.h console-impl.h console-msw.h console-stream-impl.h console-stream.h console-tty-impl.h console-tty.h console.h device-impl.h device.h devslots.h extents.h frame.h insdel.h intl-auto-encap-win32.h lstream.h opaque.h redisplay.h sysfile.h systty.h syswindows.h -process-nt.o: $(LISP_H) console-msw.h console.h hash.h intl-auto-encap-win32.h lstream.h process-slots.h process.h procimpl.h sysfile.h sysproc.h syssignal.h systime.h syswindows.h +process-nt.o: $(LISP_H) console-msw.h console.h events.h hash.h intl-auto-encap-win32.h lstream.h process-slots.h process.h procimpl.h sysfile.h sysproc.h syssignal.h systime.h syswindows.h process-unix.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h coding-system-slots.h console.h events.h file-coding.h frame.h hash.h lstream.h ndir.h opaque.h process-slots.h process.h procimpl.h redisplay.h scrollbar.h sysdep.h sysdir.h sysfile.h sysproc.h syssignal.h systime.h systty.h syswait.h window.h -process.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h coding-system-slots.h commands.h console.h device.h events.h file-coding.h frame.h hash.h insdel.h lstream.h opaque.h process-slots.h process.h procimpl.h redisplay.h scrollbar.h sysdep.h sysfile.h sysproc.h syssignal.h systime.h systty.h syswait.h window.h +process.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h coding-system-slots.h commands.h console.h device.h events.h file-coding.h frame.h hash.h insdel.h intl-auto-encap-win32.h lstream.h opaque.h process-slots.h process.h procimpl.h redisplay.h scrollbar.h sysdep.h sysfile.h sysproc.h syssignal.h systime.h systty.h syswait.h syswindows.h window.h profile.o: $(LISP_H) backtrace.h bytecode.h elhash.h hash.h profile.h syssignal.h systime.h ralloc.o: $(LISP_H) getpagesize.h rangetab.o: $(LISP_H) rangetab.h -realpath.o: $(LISP_H) intl-auto-encap-win32.h ndir.h sysdir.h sysfile.h syswindows.h +realpath.o: $(LISP_H) backtrace.h intl-auto-encap-win32.h ndir.h profile.h sysdir.h sysfile.h syswindows.h redisplay-output.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h conslots.h console-impl.h console.h device-impl.h device.h devslots.h faces.h frame-impl.h frame.h frameslots.h glyphs.h gutter.h redisplay.h scrollbar.h specifier.h window-impl.h window.h winslots.h redisplay.o: $(LISP_H) backtrace.h buffer.h bufslots.h casetab.h charset.h chartab.h coding-system-slots.h commands.h conslots.h console-impl.h console-tty.h console.h debug.h device-impl.h device.h devslots.h elhash.h events.h extents-impl.h extents.h faces.h file-coding.h frame-impl.h frame.h frameslots.h glyphs.h gui.h gutter.h insdel.h line-number.h menubar.h objects-impl.h objects.h opaque.h process.h profile.h redisplay.h scrollbar.h specifier.h sysfile.h systime.h systty.h toolbar.h window-impl.h window.h winslots.h regex.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h regex.h syntax.h @@ -263,6 +263,6 @@ unicode.o: $(LISP_H) charset.h coding-system-slots.h file-coding.h opaque.h sysfile.h vm-limit.o: $(LISP_H) mem-limits.h widget.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h -win32.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h console-msw.h console.h intl-auto-encap-win32.h sysfile.h sysproc.h syssignal.h systime.h syswindows.h +win32.o: $(LISP_H) backtrace.h buffer.h bufslots.h casetab.h charset.h chartab.h console-msw.h console.h hash.h intl-auto-encap-win32.h profile.h sysfile.h sysproc.h syssignal.h systime.h syswindows.h window.o: $(LISP_H) buffer.h bufslots.h casetab.h charset.h chartab.h commands.h conslots.h console-impl.h console.h device-impl.h device.h devslots.h elhash.h faces.h frame-impl.h frame.h frameslots.h glyphs.h gutter.h objects.h redisplay.h scrollbar.h specifier.h window-impl.h window.h winslots.h xmu.o: $(CONFIG_H) diff --text -u 'xemacs-21.5.18/src/device-msw.c' 'xemacs-21.5.19/src/device-msw.c' Index: ./src/device-msw.c --- ./src/device-msw.c Tue Sep 21 04:19:37 2004 +++ ./src/device-msw.c Tue Jan 25 08:33:49 2005 @@ -501,7 +501,7 @@ DEVICE_MSPRINTER_DEVMODE (d) = Qnil; DEVICE_MSPRINTER_NAME (d) = Qnil; -#if 0 /* @@#### deleted in new ikeyama ws */ +#if 0 /* #### deleted in new ikeyama ws */ /* We do not use printer font list as we do with the display device. Rather, we allow GDI to pick the closest match to the display font. */ @@ -848,7 +848,7 @@ if (EQ (prop, Qright_margin)) return 1440; if (EQ (prop, Qtop_margin)) return 720; if (EQ (prop, Qbottom_margin)) return 720; - abort (); + ABORT (); return 0; } @@ -916,7 +916,7 @@ qxeGetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_IMEASURE, measure, sizeof (measure) / XETCHAR_SIZE); - data = xetcscmp (measure, XETEXT ("0")); + data = qxetcscmp (measure, XETEXT ("0")); memset (&pd, 0, sizeof (pd)); pd.lStructSize = sizeof (pd); @@ -1298,7 +1298,7 @@ if (GetLastError () != ERROR_INSUFFICIENT_BUFFER) signal_enum_printer_error (); - data_buf = (BYTE *) ALLOCA (bytes_needed); + data_buf = alloca_array (BYTE, bytes_needed); ok = qxeEnumPrinters (enum_flags, NULL, enum_level, data_buf, bytes_needed, &bytes_needed, &num_printers); if (!ok) diff --text -u 'xemacs-21.5.18/src/device-tty.c' 'xemacs-21.5.19/src/device-tty.c' Index: ./src/device-tty.c --- ./src/device-tty.c Tue Sep 21 04:19:37 2004 +++ ./src/device-tty.c Tue Jan 25 08:33:49 2005 @@ -87,7 +87,7 @@ case TTY_INIT_SUCCESS: break; default: - abort (); + ABORT (); } init_one_device (d); diff --text -u 'xemacs-21.5.18/src/device-x.c' 'xemacs-21.5.19/src/device-x.c' Index: ./src/device-x.c --- ./src/device-x.c Fri Oct 15 02:26:23 2004 +++ ./src/device-x.c Fri Feb 4 01:30:35 2005 @@ -1,7 +1,7 @@ /* Device functions for X windows. Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. Copyright (C) 1994, 1995 Free Software Foundation, Inc. - Copyright (C) 2001, 2002 Ben Wing. + Copyright (C) 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -157,7 +157,7 @@ (STRINGP (Vinvocation_name) ? (char *) XSTRING_DATA (Vinvocation_name) : FALLBACK_RESOURCE_NAME), DisplayString (dpy) ? DisplayString (dpy) : "???"); - abort(); + ABORT(); } #undef FALLBACK_RESOURCE_NAME @@ -456,7 +456,7 @@ vi_in.visualid = XVisualIDFromVisual (visual); vi_out = XGetVisualInfo (dpy, /*VisualScreenMask|*/VisualIDMask, &vi_in, &out_count); - if (! vi_out) abort (); + if (! vi_out) ABORT (); d = vi_out [0].depth; XFree ((char *) vi_out); return d; @@ -494,6 +494,7 @@ static void x_init_device (struct device *d, Lisp_Object UNUSED (props)) { + /* !!#### */ Lisp_Object display; Display *dpy; Widget app_shell; @@ -651,8 +652,7 @@ { LISP_STRING_TO_EXTERNAL (Vx_app_defaults_directory, data_dir, Qfile_name); - path = (Extbyte *) ALLOCA (strlen (data_dir) + strlen (locale) + - 7); + path = alloca_extbytes (strlen (data_dir) + strlen (locale) + 7); sprintf (path, "%s%s/Emacs", data_dir, locale); if (!access (path, R_OK)) XrmCombineFileDatabase (path, &db, False); @@ -660,8 +660,7 @@ else if (STRINGP (Vdata_directory) && XSTRING_LENGTH (Vdata_directory) > 0) { LISP_STRING_TO_EXTERNAL (Vdata_directory, data_dir, Qfile_name); - path = (Extbyte *) ALLOCA (strlen (data_dir) + 13 + strlen (locale) + - 7); + path = alloca_extbytes (strlen (data_dir) + 13 + strlen (locale) + 7); sprintf (path, "%sapp-defaults/%s/Emacs", data_dir, locale); if (!access (path, R_OK)) XrmCombineFileDatabase (path, &db, False); @@ -1239,16 +1238,17 @@ char *fake_class, char *name, char *class_) { char *stack [100][2]; - Widget this; + Widget this_widget; int count = 0; char *name_tail, *class_tail; if (widget) { - for (this = widget; this; this = XtParent (this)) + for (this_widget = widget; this_widget; + this_widget = XtParent (this_widget)) { - stack [count][0] = this->core.name; - stack [count][1] = XtClass (this)->core_class.class_name; + stack [count][0] = this_widget->core.name; + stack [count][1] = XtClass (this_widget)->core_class.class_name; count++; } count--; @@ -1721,9 +1721,9 @@ (device)) { Display *dpy = get_x_display (device); - char *vendor = ServerVendor (dpy); + Extbyte *vendor = ServerVendor (dpy); - return build_string (vendor ? vendor : ""); + return build_ext_string (vendor ? vendor : "", Qx_hpc_encoding); } DEFUN ("x-server-version", Fx_server_version, 0, 1, 0, /* @@ -1748,7 +1748,7 @@ */ (keysym)) { - const char *keysym_ext; + const Extbyte *keysym_ext; CHECK_STRING (keysym); LISP_STRING_TO_EXTERNAL (keysym, keysym_ext, Qctext); @@ -1952,7 +1952,8 @@ { Display *dpy = get_x_display (device); int ndirs_return; - const char **directories = (const char **) XGetFontPath (dpy, &ndirs_return); + const Extbyte **directories = + (const Extbyte **) XGetFontPath (dpy, &ndirs_return); Lisp_Object font_path = Qnil; if (!directories) @@ -1983,25 +1984,29 @@ (font_path, device)) { Display *dpy = get_x_display (device); - Lisp_Object path_entry; - const char **directories; + Extbyte **directories; int i=0,ndirs=0; - EXTERNAL_LIST_LOOP (path_entry, font_path) - { - CHECK_STRING (XCAR (path_entry)); - ndirs++; - } + { + EXTERNAL_LIST_LOOP_2 (path_entry, font_path) + { + CHECK_STRING (path_entry); + ndirs++; + } + } - directories = alloca_array (const char *, ndirs); + directories = alloca_array (Extbyte *, ndirs); - EXTERNAL_LIST_LOOP (path_entry, font_path) - { - LISP_STRING_TO_EXTERNAL (XCAR (path_entry), directories[i++], Qfile_name); - } + { + EXTERNAL_LIST_LOOP_2 (path_entry, font_path) + { + LISP_STRING_TO_EXTERNAL (path_entry, directories[i++], + Qfile_name); + } + } expect_x_error (dpy); - XSetFontPath (dpy, (char **) directories, ndirs); + XSetFontPath (dpy, directories, ndirs); signal_if_x_error (dpy, 1/*resumable_p*/); return Qnil; @@ -2051,7 +2056,7 @@ reinit_console_type_create_device_x (void) { /* Initialize variables to speed up X resource interactions */ - const Char_ASCII *valid_resource_chars = + const Ascbyte *valid_resource_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; while (*valid_resource_chars) valid_resource_char_p[(unsigned int) (*valid_resource_chars++)] = 1; @@ -2083,8 +2088,6 @@ void vars_of_device_x (void) { - reinit_vars_of_device_x (); - DEFVAR_LISP ("x-emacs-application-class", &Vx_emacs_application_class /* The X application class of the XEmacs process. This controls, among other things, the name of the `app-defaults' file diff --text -u 'xemacs-21.5.18/src/device.c' 'xemacs-21.5.19/src/device.c' Index: ./src/device.c --- ./src/device.c Tue Sep 21 04:19:38 2004 +++ ./src/device.c Fri Feb 4 01:14:04 2005 @@ -93,14 +93,14 @@ static const struct memory_description device_data_description_1 []= { #ifdef HAVE_GTK - { XD_STRUCT_PTR, gtk_console, 1, >k_device_data_description}, + { XD_BLOCK_PTR, gtk_console, 1, { >k_device_data_description} }, #endif #ifdef HAVE_MS_WINDOWS - { XD_STRUCT_PTR, mswindows_console, 1, &mswindows_device_data_description}, - { XD_STRUCT_PTR, msprinter_console, 1, &msprinter_device_data_description}, + { XD_BLOCK_PTR, mswindows_console, 1, { &mswindows_device_data_description} }, + { XD_BLOCK_PTR, msprinter_console, 1, { &msprinter_device_data_description} }, #endif #ifdef HAVE_X_WINDOWS - { XD_STRUCT_PTR, x_console, 1, &x_device_data_description}, + { XD_BLOCK_PTR, x_console, 1, { &x_device_data_description} }, #endif { XD_END } }; @@ -114,10 +114,10 @@ #define MARKED_SLOT(x) { XD_LISP_OBJECT, offsetof (struct device, x) }, #include "devslots.h" - { XD_STRUCT_PTR, offsetof (struct device, devmeths), 1, - &console_methods_description }, + { XD_BLOCK_PTR, offsetof (struct device, devmeths), 1, + { &console_methods_description } }, { XD_UNION, offsetof (struct device, device_data), - XD_INDIRECT (0, 0), &device_data_description }, + XD_INDIRECT (0, 0), { &device_data_description } }, { XD_END } }; @@ -1477,8 +1477,6 @@ void vars_of_device (void) { - reinit_vars_of_device (); - DEFVAR_LISP ("create-device-hook", &Vcreate_device_hook /* Function or functions to call when a device is created. One argument, the newly-created device. diff --text -u 'xemacs-21.5.18/src/dialog-msw.c' 'xemacs-21.5.19/src/dialog-msw.c' Index: ./src/dialog-msw.c --- ./src/dialog-msw.c Tue Sep 21 04:19:38 2004 +++ ./src/dialog-msw.c Mon Dec 6 12:52:03 2004 @@ -1,6 +1,6 @@ /* Implements elisp-programmable dialog boxes -- MS Windows interface. Copyright (C) 1998 Kirill M. Katsnelson <kkm@kis.ru> - Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -297,7 +297,7 @@ static struct { DWORD errmess; - Char_ASCII *errname; + Ascbyte *errname; } common_dialog_errors[] = { { CDERR_DIALOGFAILURE, "CDERR_DIALOGFAILURE" }, @@ -344,7 +344,7 @@ CALLBACK handle_directory_proc (HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData) { - Extbyte szDir[MAX_PATH * MAX_XETCHAR_SIZE]; + Extbyte szDir[PATH_MAX_EXTERNAL]; struct param_data *pd = (struct param_data *) lpData; switch (msg) @@ -365,7 +365,7 @@ if (pd->validate) return TRUE; else - pd->unknown_fname = xetcsdup ((Extbyte *) lParam); + pd->unknown_fname = qxetcsdup ((Extbyte *) lParam); break; default: @@ -430,7 +430,7 @@ pidl = qxeSHBrowseForFolder (&bi); if (pidl) { - Extbyte *szDir = alloca_extbytes (MAX_PATH * MAX_XETCHAR_SIZE); + Extbyte *szDir = alloca_extbytes (PATH_MAX_EXTERNAL); if (qxeSHGetPathFromIDList (pidl, szDir)) ret = tstr_to_local_file_format (szDir); @@ -466,7 +466,7 @@ ofn.hwndOwner = FRAME_MSWINDOWS_HANDLE (f); ofn.lpstrFile = (XELPTSTR) fnbuf; ofn.nMaxFile = sizeof (fnbuf) / XETCHAR_SIZE; - xetcscpy (fnbuf, XETEXT ("")); + qxetcscpy (fnbuf, XETEXT ("")); LOCAL_FILE_FORMAT_TO_TSTR (Fexpand_file_name (build_string (""), Qnil), ofn.lpstrInitialDir); @@ -480,7 +480,7 @@ CHECK_STRING (value); LOCAL_FILE_FORMAT_TO_TSTR (value, fnout); - xetcscpy (fnbuf, fnout); + qxetcscpy (fnbuf, fnout); } else if (EQ (key, Q_title)) { @@ -565,17 +565,14 @@ } else if (EQ (key, Q_buttons)) { - Lisp_Object item_cons; - /* Parse each item in the dialog into gui_item structs, and stuff a dynarr of these. Calculate button row width in this loop too */ - EXTERNAL_LIST_LOOP (item_cons, value) + EXTERNAL_LIST_LOOP_2 (item, value) { - if (!NILP (XCAR (item_cons))) + if (!NILP (item)) { - Lisp_Object gitem = - gui_parse_item_keywords (XCAR (item_cons)); + Lisp_Object gitem = gui_parse_item_keywords (item); Dynarr_add (dialog_items, gitem); button_row_width += button_width (XGUI_ITEM (gitem)->name) + X_BUTTON_MARGIN; diff --text -u 'xemacs-21.5.18/src/dired-msw.c' 'xemacs-21.5.19/src/dired-msw.c' Index: ./src/dired-msw.c --- ./src/dired-msw.c Wed Oct 1 00:26:40 2003 +++ ./src/dired-msw.c Fri Jan 28 11:36:24 2005 @@ -192,7 +192,7 @@ int findex; DECLARE_EISTRING (win32pattern); HANDLE fh; - int errm; + int errm; while (1) { @@ -206,14 +206,19 @@ /* Now *bufp is the compiled form of PATTERN; don't call anything which might compile a new regexp until we're done with the loop! */ + { + Ibyte *dir2; + LISP_PATHNAME_RESOLVE_LINKS (dirfile, dir2); + eicpy_rawz (win32pattern, dir2); + } + /* for Win32, we need to insure that the pathname ends with "\*". */ - eicpy_lstr (win32pattern, dirfile); if (!nowild) { Charcount len = eicharlen (win32pattern) - 1; if (!IS_DIRECTORY_SEP (eigetch_char (win32pattern, len))) - eicat_c (win32pattern, "\\"); - eicat_c (win32pattern, "*"); + eicat_ascii (win32pattern, "\\"); + eicat_ascii (win32pattern, "*"); } eito_external (win32pattern, Qmswindows_tstr); @@ -285,8 +290,7 @@ eigetch_char (filename, 2) == '\0'))) || hide_dot))) { - file.cFileName = - (Ibyte *) xmalloc (sizeof (Ibyte) * (1 + len)); + file.cFileName = xnew_ibytes (len + ITEXT_ZTERM_SIZE); memcpy (file.cFileName, eidata (filename), len); file.cFileName[len] = '\0'; Dynarr_add (files, file); @@ -313,17 +317,17 @@ file_size = file->nFileSizeHigh * (double)UINT_MAX + file->nFileSizeLow; #if INDENT_LISTING - eicat_c (puta, " "); + eicat_ascii (puta, " "); #endif if (display_size) { sprintf (buf, "%6d ", (int)((file_size + 1023.) / 1024.)); - eicat_c (puta, buf); + eicat_ascii (puta, buf); } if (file->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - eicat_c (puta, "d"); + eicat_ascii (puta, "d"); else - eicat_c (puta, "-"); + eicat_ascii (puta, "-"); buf[0] = buf[3] = buf[6] = 'r'; if (file->dwFileAttributes & FILE_ATTRIBUTE_READONLY) buf[1] = buf[4] = buf[7] = '-'; @@ -341,11 +345,11 @@ DEC_IBYTEPTR (end); DEC_IBYTEPTR (end); DEC_IBYTEPTR (end); - if (qxestrcasecmp_c (end, ".exe") == 0 - || qxestrcasecmp_c (end, ".com") == 0 - || qxestrcasecmp_c (end, ".bat") == 0 + if (qxestrcasecmp_ascii (end, ".exe") == 0 + || qxestrcasecmp_ascii (end, ".com") == 0 + || qxestrcasecmp_ascii (end, ".bat") == 0 #if 0 - || qxestrcasecmp_c (end, ".pif") == 0 + || qxestrcasecmp_ascii (end, ".pif") == 0 #endif ) is_executable = 1; @@ -356,11 +360,11 @@ buf[2] = buf[5] = buf[8] = '-'; } buf[9] = '\0'; - eicat_c (puta, buf); + eicat_ascii (puta, buf); if (file->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - eicat_c (puta, " 2 "); + eicat_ascii (puta, " 2 "); else - eicat_c (puta, " 1 "); + eicat_ascii (puta, " 1 "); luser = Fuser_login_name (Qnil); if (!STRINGP (luser)) sprintf (buf, "%-9d", 0); @@ -428,10 +432,10 @@ } } - eicat_c (puta, buf); + eicat_ascii (puta, buf); eicat_raw (puta, file->cFileName, qxestrlen (file->cFileName)); if (add_newline) - eicat_c (puta, "\n"); + eicat_ascii (puta, "\n"); return eimake_string (puta); } diff --text -u 'xemacs-21.5.18/src/dired.c' 'xemacs-21.5.19/src/dired.c' Index: ./src/dired.c --- ./src/dired.c Wed Sep 22 11:06:44 2004 +++ ./src/dired.c Fri Nov 5 08:06:21 2004 @@ -104,7 +104,7 @@ directory = Ffile_name_as_directory (directory); directorylen = XSTRING_LENGTH (directory); - statbuf = (Ibyte *) ALLOCA (directorylen + MAXNAMLEN + 1); + statbuf = alloca_ibytes (directorylen + MAXNAMLEN + 1); memcpy (statbuf, XSTRING_DATA (directory), directorylen); statbuf_tail = statbuf + directorylen; @@ -251,7 +251,7 @@ Bytecount len = NAMLEN (dp); Bytecount pos = XSTRING_LENGTH (directory); int value; - Ibyte *fullname = (Ibyte *) ALLOCA (len + pos + 2); + Ibyte *fullname = alloca_ibytes (len + pos + 2); memcpy (fullname, XSTRING_DATA (directory), pos); if (!IS_DIRECTORY_SEP (fullname[pos - 1])) @@ -391,11 +391,9 @@ /* if name is not an exact match against specified string. */ if (!passcount && cclen > file_name_length) { - Lisp_Object tem; /* and exit this for loop if a match is found */ - EXTERNAL_LIST_LOOP (tem, Vcompletion_ignored_extensions) + EXTERNAL_LIST_LOOP_2 (elt, Vcompletion_ignored_extensions) { - Lisp_Object elt = XCAR (tem); Charcount skip; CHECK_STRING (elt); diff --text -u 'xemacs-21.5.18/src/doc.c' 'xemacs-21.5.19/src/doc.c' Index: ./src/doc.c --- ./src/doc.c Sun Jan 4 06:54:42 2004 +++ ./src/doc.c Fri Nov 5 08:06:21 2004 @@ -1,7 +1,7 @@ /* Record indices of function doc strings stored in a file. Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - Copyright (C) 2001, 2002 Ben Wing. + Copyright (C) 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -100,11 +100,11 @@ Ibyte *old_buffer = buffer; if (buffer == buf) { - buffer = (Ibyte *) xmalloc (buffer_size *= 2); + buffer = xnew_ibytes (buffer_size *= 2); memcpy (buffer, old_buffer, p - old_buffer); } else - buffer = (Ibyte *) xrealloc (buffer, buffer_size *= 2); + XREALLOC_ARRAY (buffer, Ibyte, buffer_size *= 2); p += buffer - old_buffer; space_left = buffer_size - (p - buffer); } @@ -248,10 +248,10 @@ if (purify_flag) { /* sizeof ("../lib-src/") == 12 */ - name_nonreloc = (Ibyte *) ALLOCA (12 + XSTRING_LENGTH (file) + 8); + name_nonreloc = alloca_ibytes (12 + XSTRING_LENGTH (file) + 8); /* Preparing to dump; DOC file is probably not installed. So check in ../lib-src. */ - qxestrcpy (name_nonreloc, (Ibyte *) "../lib-src/"); + qxestrcpy_ascii (name_nonreloc, "../lib-src/"); qxestrcat (name_nonreloc, XSTRING_DATA (file)); fd = qxe_open (name_nonreloc, O_RDONLY | OPEN_BINARY, 0); @@ -461,7 +461,7 @@ { name = alloca_ibytes (XSTRING_LENGTH (filename) + 14); - qxestrcpy (name, (Ibyte *) "../lib-src/"); + qxestrcpy_ascii (name, "../lib-src/"); } qxestrcat (name, XSTRING_DATA (filename)); @@ -679,7 +679,7 @@ # define kludge_prefix "ad-Orig-" Lisp_Object name = XSYMBOL (sym)->name; return (XSTRING_LENGTH (name) > (Bytecount) (sizeof (kludge_prefix)) && - !qxestrncmp_c (XSTRING_DATA (name), kludge_prefix, + !qxestrncmp_ascii (XSTRING_DATA (name), kludge_prefix, sizeof (kludge_prefix) - 1)); # undef kludge_prefix } @@ -831,8 +831,8 @@ #endif strlength = XSTRING_LENGTH (string); - bsize = 1 + strlength; - buf = (Ibyte *) xmalloc (bsize); + bsize = ITEXT_ZTERM_SIZE + strlength; + buf = xnew_ibytes (bsize); bufp = buf; /* Have to reset strdata every time GC might be called */ diff --text -u 'xemacs-21.5.18/src/doprnt.c' 'xemacs-21.5.19/src/doprnt.c' Index: ./src/doprnt.c --- ./src/doprnt.c Wed Sep 15 05:54:36 2004 +++ ./src/doprnt.c Tue Jan 25 08:33:50 2005 @@ -239,7 +239,7 @@ case ' ': spec.space_flag = 1; break; case '#': spec.number_flag = 1; break; case '0': spec.zero_flag = 1; break; - default: abort (); + default: ABORT (); } NEXT_ASCII_BYTE (ch); } @@ -408,7 +408,7 @@ else if (strchr (bigfloat_converters, ch)) arg.obj = va_arg (vargs, Lisp_Object); #endif - else abort (); + else ABORT (); Dynarr_add (args, arg); } @@ -948,7 +948,7 @@ format_reloc, nargs, largs); Lstream_flush (XLSTREAM (stream)); len = Lstream_byte_count (XLSTREAM (stream)); - retval = (Ibyte *) xmalloc (len + 1); + retval = xnew_ibytes (len + 1); memcpy (retval, resizing_buffer_stream_ptr (XLSTREAM (stream)), len); retval[len] = '\0'; Lstream_delete (XLSTREAM (stream)); @@ -1032,7 +1032,7 @@ vargs); Lstream_flush (XLSTREAM (stream)); len = Lstream_byte_count (XLSTREAM (stream)); - retval = (Ibyte *) xmalloc (len + 1); + retval = xnew_ibytes (len + 1); memcpy (retval, resizing_buffer_stream_ptr (XLSTREAM (stream)), len); retval[len] = '\0'; end_gc_forbidden (count); diff --text -u 'xemacs-21.5.18/src/dragdrop.c' 'xemacs-21.5.19/src/dragdrop.c' Index: ./src/dragdrop.c --- ./src/dragdrop.c Thu May 24 16:51:07 2001 +++ ./src/dragdrop.c Fri Nov 5 08:06:21 2004 @@ -1,6 +1,7 @@ /* Drag'n'Drop definitions created 03-may-98 by Oliver Graf <ograf@fga.de> Copyright (C) 1998 Oliver Graf <ograf@fga.de> + Copyright (C) 2004 Ben Wing. This file is part of XEmacs. @@ -74,12 +75,12 @@ /* Encodes the unsafe characters (listed in URL_UNSAFE) in a given string, returning a malloc-ed %XX encoded string. if method is != NULL it is prepended to the string. */ -char * -dnd_url_hexify_string (const char *s, const char *m) +Ibyte * +dnd_url_hexify_string (const Ibyte *s, const Ibyte *m) { - const char *b; - char *p, *res; - int i; + const Ibyte *b; + Ibyte *p, *res; + Bytecount i; b = s; for (i = 0; *s; s++, i++) @@ -87,19 +88,19 @@ i += 2; /* Two more characters (hex digits) */ if (m) { - res = (char *)xmalloc (i + 1 + strlen (m)); - strcpy (res, m); - p = res + strlen (m); + res = xnew_ibytes (i + ITEXT_ZTERM_SIZE + qxestrlen (m)); + qxestrcpy (res, m); + p = res + qxestrlen (m); } else { - res = (char *)xmalloc (i + 1); + res = xnew_ibytes (i + ITEXT_ZTERM_SIZE); p = res; } for (s = b; *s; s++) if (strchr (URL_UNSAFE, *s)) { - const unsigned char c = *s; + const Ibyte c = *s; *p++ = '%'; *p++ = HEXD2ASC (c >> 4); *p++ = HEXD2ASC (c & 0xf); @@ -131,15 +132,15 @@ Vdragdrop_protocols = Qnil; #ifdef HAVE_MS_WINDOWS - Vdragdrop_protocols = Fcons ( Qmswindows , Vdragdrop_protocols ); + Vdragdrop_protocols = Fcons (Qmswindows, Vdragdrop_protocols); #endif #ifdef HAVE_CDE - Vdragdrop_protocols = Fcons ( intern ("cde") , Vdragdrop_protocols ); + Vdragdrop_protocols = Fcons (intern ("cde"), Vdragdrop_protocols); #endif #ifdef HAVE_OFFIX_DND - Vdragdrop_protocols = Fcons ( intern ("offix") , Vdragdrop_protocols ); + Vdragdrop_protocols = Fcons (intern ("offix"), Vdragdrop_protocols); #endif #ifdef HAVE_GTK - Vdragdrop_protocols = Fcons ( Qgtk , Vdragdrop_protocols ); + Vdragdrop_protocols = Fcons (Qgtk, Vdragdrop_protocols); #endif } diff --text -u 'xemacs-21.5.18/src/dragdrop.h' 'xemacs-21.5.19/src/dragdrop.h' Index: ./src/dragdrop.h --- ./src/dragdrop.h Fri Apr 13 03:23:35 2001 +++ ./src/dragdrop.h Fri Nov 5 08:06:22 2004 @@ -32,7 +32,7 @@ extern Lisp_Object Qdragdrop_drop_dispatch; /* some utility functions */ -char *dnd_url_hexify_string (const char *s, const char *m); +Ibyte *dnd_url_hexify_string (const Ibyte *s, const Ibyte *m); /* emacs interface */ void syms_of_dragdrop (void); diff --text -u 'xemacs-21.5.18/src/dump-data.c' 'xemacs-21.5.19/src/dump-data.c' Index: ./src/dump-data.c --- ./src/dump-data.c Mon Apr 19 23:49:07 2004 +++ ./src/dump-data.c Fri Nov 5 08:06:22 2004 @@ -33,7 +33,7 @@ /* 4 bytes for the data size, 4096 for alignment */ -static unsigned char dumped_data[MAX_SIZE+4096+4] = { +static Rawbyte dumped_data[MAX_SIZE+4096+4] = { 255, 6, 1, @@ -52,32 +52,33 @@ }; size_t -dumped_data_size(void) +dumped_data_size (void) { - return dumped_data[0] | (dumped_data[1] << 8) | (dumped_data[2] << 16) | (dumped_data[3] << 24); + return dumped_data[0] | (dumped_data[1] << 8) | (dumped_data[2] << 16) | + (dumped_data[3] << 24); } size_t -dumped_data_max_size(void) +dumped_data_max_size (void) { return MAX_SIZE; } size_t -dumped_data_align_offset(void) +dumped_data_align_offset (void) { - EMACS_INT iptr = (EMACS_INT)dumped_data; + EMACS_INT iptr = (EMACS_INT) dumped_data; EMACS_INT iptr2; - iptr2 = (iptr+4+4095) & ~(EMACS_INT)4095; + iptr2 = (iptr + 4 + 4095) & ~(EMACS_INT) 4095; - return iptr2-iptr; + return iptr2 - iptr; } -char * -dumped_data_get(void) +Rawbyte * +dumped_data_get (void) { - EMACS_INT iptr = (EMACS_INT)dumped_data; - iptr = (iptr+4+4095) & ~(EMACS_INT)4095; - return (char *)iptr; + EMACS_INT iptr = (EMACS_INT) dumped_data; + iptr = (iptr + 4 + 4095) & ~(EMACS_INT) 4095; + return (Rawbyte *) iptr; } diff --text -u 'xemacs-21.5.18/src/dump-data.h' 'xemacs-21.5.19/src/dump-data.h' Index: ./src/dump-data.h --- ./src/dump-data.h Mon Apr 19 23:49:07 2004 +++ ./src/dump-data.h Fri Nov 5 08:06:22 2004 @@ -24,15 +24,15 @@ #define INCLUDED_dump_data_h_ /* inline dumped data size */ -size_t dumped_data_size(void); +size_t dumped_data_size (void); /* maximum space available for inline data */ -size_t dumped_data_max_size(void); +size_t dumped_data_max_size (void); /* alignment offset for data inclusion */ -size_t dumped_data_align_offset(void); +size_t dumped_data_align_offset (void); /* inline data */ -char *dumped_data_get(void); +Rawbyte *dumped_data_get (void); #endif diff --text -u 'xemacs-21.5.18/src/dumper.c' 'xemacs-21.5.19/src/dumper.c' Index: ./src/dumper.c --- ./src/dumper.c Tue Sep 21 04:19:38 2004 +++ ./src/dumper.c Fri Feb 4 12:01:20 2005 @@ -1,7 +1,7 @@ /* Portable data dumper for XEmacs. - Copyright (C) 1999-2000 Olivier Galibert + Copyright (C) 1999-2000,2004 Olivier Galibert Copyright (C) 2001 Martin Buchholz - Copyright (C) 2001, 2002, 2003 Ben Wing. + Copyright (C) 2001, 2002, 2003, 2004, 2005 Ben Wing. This file is part of XEmacs. @@ -22,7 +22,17 @@ /* Synched up with: Not in FSF. */ -/* !!#### Not yet Mule-ized */ +/* This file has been Mule-ized, Ben Wing, 10-10-04. */ + +/* #### Put in much more assertions. Whenever we store fixups in the + process or writing out data, make sure the fixups (offsets) point to the + beginning of an object, i.e. are registered. Same whenever we read in + -- verify offsets as registered, and when compute a fixup, verify the + pointer is pointing within the pdump area. registered and check within + pdump area. For specific types of pointers (e.g. to Lisp_Objects), + check if they're pointing to the right kinds of types. It should be + possible to check that a putative Lisp_Object is really a Lisp_Object + since it will follow a strict format in its header. */ #include <config.h> #include "lisp.h" @@ -45,7 +55,7 @@ typedef struct { - const void *varaddress; + const void *blockaddr; Bytecount size; const struct memory_description *desc; } pdump_root_block; @@ -59,12 +69,63 @@ { void **ptraddress; const struct sized_memory_description *desc; -} pdump_root_struct_ptr; +} pdump_root_block_ptr; + +typedef struct +{ + Dynarr_declare (pdump_root_block_ptr); +} pdump_root_block_ptr_dynarr; + +typedef struct +{ + const void *object; + void *data; + Bytecount size; + EMACS_INT offset; + EMACS_INT dest_offset; + EMACS_INT save_offset; + const struct opaque_convert_functions *fcts; +} pdump_cv_data_info; + +typedef struct +{ + Dynarr_declare (pdump_cv_data_info); +} pdump_cv_data_info_dynarr; + +typedef struct +{ + EMACS_INT dest_offset; + EMACS_INT save_offset; + Bytecount size; +} pdump_cv_data_dump_info; + +typedef struct +{ + const void *object; + void *data; + Bytecount size; + EMACS_INT index; + EMACS_INT save_offset; + const struct opaque_convert_functions *fcts; +} pdump_cv_ptr_info; + +typedef struct +{ + Dynarr_declare (pdump_cv_ptr_info); +} pdump_cv_ptr_info_dynarr; typedef struct { - Dynarr_declare (pdump_root_struct_ptr); -} pdump_root_struct_ptr_dynarr; + EMACS_INT save_offset; + Bytecount size; +} pdump_cv_ptr_dump_info; + +typedef struct +{ + EMACS_INT save_offset; + Bytecount size; + void *adr; +} pdump_cv_ptr_load_info; typedef struct { @@ -74,23 +135,26 @@ typedef struct { - char **address; /* char * for ease of doing relocation */ - char * value; + Rawbyte **address; /* Rawbyte * for ease of doing relocation */ + Rawbyte * value; } pdump_static_pointer; static pdump_root_block_dynarr *pdump_root_blocks; -static pdump_root_struct_ptr_dynarr *pdump_root_struct_ptrs; +static pdump_root_block_ptr_dynarr *pdump_root_block_ptrs; static Lisp_Object_ptr_dynarr *pdump_root_lisp_objects; static Lisp_Object_ptr_dynarr *pdump_weak_object_chains; +static pdump_cv_data_info_dynarr *pdump_cv_data; +static pdump_cv_ptr_info_dynarr *pdump_cv_ptr; + +/* Mark SIZE bytes at non-heap address BLOCKADDR for dumping, described + by DESC. Called by outside callers during XEmacs initialization. */ -/* Mark SIZE bytes at non-heap address VARADDRESS for dumping, described - by DESC. */ void -dump_add_root_block (const void *varaddress, Bytecount size, +dump_add_root_block (const void *blockaddr, Bytecount size, const struct memory_description *desc) { pdump_root_block info; - info.varaddress = varaddress; + info.blockaddr = blockaddr; info.size = size; info.desc = desc; if (pdump_root_blocks == NULL) @@ -98,23 +162,25 @@ Dynarr_add (pdump_root_blocks, info); } -/* Mark the struct described by DESC and pointed to by the pointer at - non-heap address VARADDRESS for dumping. - All the objects reachable from this pointer will also be dumped. */ +/* Mark the block described by DESC and pointed to by the pointer at + non-heap address PTRADDRESS for dumping. + All the objects reachable from this pointer will also be dumped. + Called by outside callers during XEmacs initialization. */ void -dump_add_root_struct_ptr (void *ptraddress, - const struct sized_memory_description *desc) +dump_add_root_block_ptr (void *ptraddress, + const struct sized_memory_description *desc) { - pdump_root_struct_ptr info; + pdump_root_block_ptr info; info.ptraddress = (void **) ptraddress; info.desc = desc; - if (pdump_root_struct_ptrs == NULL) - pdump_root_struct_ptrs = Dynarr_new (pdump_root_struct_ptr); - Dynarr_add (pdump_root_struct_ptrs, info); + if (pdump_root_block_ptrs == NULL) + pdump_root_block_ptrs = Dynarr_new (pdump_root_block_ptr); + Dynarr_add (pdump_root_block_ptrs, info); } /* Mark the Lisp_Object at non-heap address VARADDRESS for dumping. - All the objects reachable from this var will also be dumped. */ + All the objects reachable from this var will also be dumped. + Called by outside callers during XEmacs initialization. */ void dump_add_root_lisp_object (Lisp_Object *varaddress) { @@ -123,7 +189,8 @@ Dynarr_add (pdump_root_lisp_objects, varaddress); } -/* Mark the list pointed to by the Lisp_Object at VARADDRESS for dumping. */ +/* Mark the list pointed to by the Lisp_Object at VARADDRESS for dumping. + Called by outside callers during XEmacs initialization. */ void dump_add_weak_object_chain (Lisp_Object *varaddress) { @@ -153,10 +220,10 @@ } while (0) #define PDUMP_READ(ptr, type) \ -(((type *) (ptr = (char*) (((type *) ptr) + 1)))[-1]) +(((type *) (ptr = (Rawbyte *) (((type *) ptr) + 1)))[-1]) #define PDUMP_READ_ALIGNED(ptr, type) \ -((ptr = (char *) ALIGN_PTR (ptr, type)), PDUMP_READ (ptr, type)) +((ptr = (Rawbyte *) ALIGN_PTR (ptr, type)), PDUMP_READ (ptr, type)) @@ -166,13 +233,13 @@ int count; } pdump_reloc_table; -static char *pdump_rt_list = 0; +static Rawbyte *pdump_rt_list = 0; void pdump_objects_unmark (void) { int i; - char *p = pdump_rt_list; + Rawbyte *p = pdump_rt_list; if (p) for (;;) { @@ -196,10 +263,13 @@ /* The structure of the dump file looks like this: 0 - header - dumped objects - stab_offset - nb_root_struct_ptrs*struct(void *, adr) - for global pointers to structures + stab_offset - nb_cv_data*struct(dest, adr) for in-object externally + represented data + - nb_cv_ptr*(adr) for pointed-to externally represented data + - nb_root_block_ptrs*struct(void *, adr) + for global pointers to heap blocks - nb_root_blocks*struct(void *, size, info) for global - objects to restore + data-segment blocks to restore - relocation table - root lisp object address/value couples with the count preceding the list @@ -215,14 +285,19 @@ unsigned int id; EMACS_UINT stab_offset; EMACS_UINT reloc_address; - int nb_root_struct_ptrs; + int nb_root_block_ptrs; int nb_root_blocks; + int nb_cv_data; + int nb_cv_ptr; } pdump_header; -char *pdump_start; -char *pdump_end; +Rawbyte *pdump_start; +Rawbyte *pdump_end; static Bytecount pdump_length; +static pdump_cv_data_dump_info *pdump_loaded_cv_data; +static pdump_cv_ptr_load_info *pdump_loaded_cv_ptr; + #ifdef WIN32_NATIVE /* Handle for the dump file */ static HANDLE pdump_hFile = INVALID_HANDLE_VALUE; @@ -246,38 +321,87 @@ return pdump_align_table[size % countof (pdump_align_table)]; } -typedef struct pdump_entry_list_elt +/************************************************************************/ +/* Registering memory blocks */ +/************************************************************************/ + +/* "Registering" or recording a heap memory block (which will need to be + written out, reloaded and relocated, and to which there may be pointers + from other heap blocks or from the data segment) happens both in a list + and in a hash table. There is a single hash table covering all + registered blocks, but different lists for different kinds of blocks. + There is one list for "opaque data" (stuff identified as + XD_OPAQUE_DATA_PTR, XD_ASCII_STRING, XD_DOC_STRING), one list for each + type of Lisp object, and one list for each different memory descriptor. + This lets similar-sized and aligned objects be grouped together when + they are written out, to save space. + + pdump_block_list is a list keeping track of registered memory blocks. + pdump_block_list_elt is a single entry through the list, and the list is + threaded through the NEXT pointer. The information in this list + associated with a particular block of memory is + + -- address of the beginning + -- number of elements at that address + -- size of each element + -- offset to this block in the dumped data + + pdump_desc_list is a list keeping track of the various descriptions + that we've seen. The primary purpose of this is so that memory blocks + can be grouped depending on the particular memory description + appropriate for them. The format of the list is different from + pdump_block_list -- a single array is used. (#### Dynarr should have + been used!!!). The information in this list associated with a + description is + + -- pointer to the description + -- a pdump_block_list of blocks using that description + + Functions for working with lists of memory blocks: + + -- Add a memory block to a list using pdump_add_block() + + -- Get a memory block from a pointer to its beginning using + pdump_get_block(). This uses the hash table, which lists everything. + + -- Return the memory-block list (pdump_block_list) associated with a + descriptor, using pdump_get_block_list(). If no entry found in the + pdump_desc_list, add a new one. + +*/ + +typedef struct pdump_block_list_elt { - struct pdump_entry_list_elt *next; + struct pdump_block_list_elt *next; const void *obj; Bytecount size; int count; EMACS_INT save_offset; -} pdump_entry_list_elt; +} pdump_block_list_elt; typedef struct { - pdump_entry_list_elt *first; + pdump_block_list_elt *first; int align; int count; -} pdump_entry_list; +} pdump_block_list; -typedef struct pdump_struct_list_elt +typedef struct pdump_desc_list_elt { - pdump_entry_list list; + pdump_block_list list; const struct memory_description *desc; -} pdump_struct_list_elt; +} pdump_desc_list_elt; typedef struct { - pdump_struct_list_elt *list; + pdump_desc_list_elt *list; int count; int size; -} pdump_struct_list; +} pdump_desc_list; -static pdump_entry_list *pdump_object_table; -static pdump_entry_list pdump_opaque_data_list; -static pdump_struct_list pdump_struct_table; +static pdump_block_list *pdump_object_table; +static pdump_block_list pdump_opaque_data_list; +static pdump_desc_list pdump_desc_table; static int *pdump_alert_undump_object; @@ -289,7 +413,7 @@ #define PDUMP_HASHSIZE 200001 -static pdump_entry_list_elt **pdump_hash; +static pdump_block_list_elt **pdump_hash; /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */ static int @@ -298,11 +422,14 @@ return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE; } -static pdump_entry_list_elt * -pdump_get_entry (const void *obj) +/* Return the entry for an already-registered memory block at OBJ, + or NULL if none. */ + +static pdump_block_list_elt * +pdump_get_block (const void *obj) { int pos = pdump_make_hash (obj); - pdump_entry_list_elt *e; + pdump_block_list_elt *e; assert (obj != 0); @@ -318,11 +445,14 @@ return 0; } +/* Register a new memory block on Return the entry for an already-registered heap (?) memory block at OBJ, + or NULL if none. */ + static void -pdump_add_entry (pdump_entry_list *list, const void *obj, Bytecount size, +pdump_add_block (pdump_block_list *list, const void *obj, Bytecount size, int count) { - pdump_entry_list_elt *e; + pdump_block_list_elt *e; int pos = pdump_make_hash (obj); while ((e = pdump_hash[pos]) != 0) @@ -335,7 +465,7 @@ pos = 0; } - e = xnew (pdump_entry_list_elt); + e = xnew (pdump_block_list_elt); e->next = list->first; e->obj = obj; @@ -354,30 +484,40 @@ } } -static pdump_entry_list * -pdump_get_entry_list (const struct memory_description *desc) +static pdump_block_list * +pdump_get_block_list (const struct memory_description *desc) { int i; - for (i=0; i<pdump_struct_table.count; i++) - if (pdump_struct_table.list[i].desc == desc) - return &pdump_struct_table.list[i].list; + for (i=0; i<pdump_desc_table.count; i++) + if (pdump_desc_table.list[i].desc == desc) + return &pdump_desc_table.list[i].list; - if (pdump_struct_table.size <= pdump_struct_table.count) + if (pdump_desc_table.size <= pdump_desc_table.count) { - if (pdump_struct_table.size == -1) - pdump_struct_table.size = 10; + if (pdump_desc_table.size == -1) + pdump_desc_table.size = 10; else - pdump_struct_table.size = pdump_struct_table.size * 2; - pdump_struct_table.list = (pdump_struct_list_elt *) - xrealloc (pdump_struct_table.list, - pdump_struct_table.size * sizeof (pdump_struct_list_elt)); - } - pdump_struct_table.list[pdump_struct_table.count].list.first = 0; - pdump_struct_table.list[pdump_struct_table.count].list.align = ALIGNOF (max_align_t); - pdump_struct_table.list[pdump_struct_table.count].list.count = 0; - pdump_struct_table.list[pdump_struct_table.count].desc = desc; + pdump_desc_table.size = pdump_desc_table.size * 2; + pdump_desc_table.list = (pdump_desc_list_elt *) + xrealloc (pdump_desc_table.list, + pdump_desc_table.size * sizeof (pdump_desc_list_elt)); + } + pdump_desc_table.list[pdump_desc_table.count].list.first = 0; + pdump_desc_table.list[pdump_desc_table.count].list.align = ALIGNOF (max_align_t); + pdump_desc_table.list[pdump_desc_table.count].list.count = 0; + pdump_desc_table.list[pdump_desc_table.count].desc = desc; - return &pdump_struct_table.list[pdump_struct_table.count++].list; + return &pdump_desc_table.list[pdump_desc_table.count++].list; +} + +static pdump_cv_ptr_info * +pdump_find_in_cv_ptr_dynarr(const void *object) +{ + int i; + for (i = 0; i < Dynarr_length (pdump_cv_ptr); i++) + if (Dynarr_at (pdump_cv_ptr, i).object == object) + return Dynarr_atp (pdump_cv_ptr, i); + return 0; } static struct @@ -421,7 +561,7 @@ #endif if (do_backtrace) pdump_backtrace (); - abort (); + ABORT (); } static void @@ -431,7 +571,7 @@ if (me > 65536) { stderr_out ("Backtrace overflow, loop ?\n"); - abort (); + ABORT (); } backtrace[me].obj = 0; backtrace[me].position = 0; @@ -439,13 +579,15 @@ } static void pdump_register_object (Lisp_Object obj); -static void pdump_register_struct_contents (const void *data, - const struct sized_memory_description * - sdesc, - int count); -static void pdump_register_struct (const void *data, - const struct sized_memory_description *sdesc, - int count); +static void pdump_register_block_contents (const void *data, + Bytecount size, + const struct memory_description * + desc, + int count); +static void pdump_register_block (const void *data, + Bytecount size, + const struct memory_description *desc, + int count); static void pdump_register_sub (const void *data, const struct memory_description *desc) @@ -458,7 +600,7 @@ const struct memory_description *desc1 = &desc[pos]; EMACS_INT offset = lispdesc_indirect_count (desc1->offset, desc, data); - const void *rdata = (const char *) data + offset; + const void *rdata = (const Rawbyte *) data + offset; backtrace[me].position = pos; backtrace[me].offset = offset; @@ -484,23 +626,23 @@ EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc, data); - pdump_add_entry (&pdump_opaque_data_list, + pdump_add_block (&pdump_opaque_data_list, *(void **)rdata, count, 1); break; } - case XD_C_STRING: + case XD_ASCII_STRING: { - const char *str = * (const char **) rdata; + const Ascbyte *str = * (const Ascbyte **) rdata; if (str) - pdump_add_entry (&pdump_opaque_data_list, str, strlen (str) + 1, + pdump_add_block (&pdump_opaque_data_list, str, strlen (str) + 1, 1); break; } case XD_DOC_STRING: { - const char *str = * (const char **) rdata; + const Ascbyte *str = * (const Ascbyte **) rdata; if ((EMACS_INT) str > 0) - pdump_add_entry (&pdump_opaque_data_list, str, strlen (str) + 1, + pdump_add_block (&pdump_opaque_data_list, str, strlen (str) + 1, 1); break; } @@ -510,7 +652,8 @@ assert (desc1->data1 == 0); - backtrace[me].offset = (const char *) pobj - (const char *) data; + backtrace[me].offset = + (const Rawbyte *) pobj - (const Rawbyte *) data; pdump_register_object (*pobj); break; } @@ -526,30 +669,32 @@ Lisp_Object dobj = *pobj; backtrace[me].offset = - (const char *) pobj - (const char *) data; + (const Rawbyte *) pobj - (const Rawbyte *) data; pdump_register_object (dobj); } break; } - case XD_STRUCT_PTR: + case XD_BLOCK_PTR: { EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc, data); const struct sized_memory_description *sdesc = - lispdesc_indirect_description (data, desc1->data2); - const char *dobj = *(const char **)rdata; + lispdesc_indirect_description (data, desc1->data2.descr); + const Rawbyte *dobj = *(const Rawbyte **)rdata; if (dobj) - pdump_register_struct (dobj, sdesc, count); + pdump_register_block (dobj, sdesc->size, sdesc->description, + count); break; } - case XD_STRUCT_ARRAY: + case XD_BLOCK_ARRAY: { EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc, data); const struct sized_memory_description *sdesc = - lispdesc_indirect_description (data, desc1->data2); + lispdesc_indirect_description (data, desc1->data2.descr); - pdump_register_struct_contents (rdata, sdesc, count); + pdump_register_block_contents (rdata, sdesc->size, + sdesc->description, count); break; } case XD_UNION: @@ -558,6 +703,29 @@ if (desc1) goto union_switcheroo; break; + case XD_OPAQUE_PTR_CONVERTIBLE: + { + pdump_cv_ptr_info info; + info.object = *(void **)rdata; + info.fcts = desc1->data2.funcs; + if (!pdump_find_in_cv_ptr_dynarr (info.object)) + { + info.fcts->convert(info.object, &info.data, &info.size); + Dynarr_add (pdump_cv_ptr, info); + } + break; + } + case XD_OPAQUE_DATA_CONVERTIBLE: + { + pdump_cv_data_info info; + info.object = data; + info.offset = offset; + info.fcts = desc1->data2.funcs; + + info.fcts->convert(rdata, &info.data, &info.size); + Dynarr_add (pdump_cv_data, info); + break; + } default: pdump_unsupported_dump_type (desc1->type, 1); @@ -578,7 +746,7 @@ if (!objh) return; - if (pdump_get_entry (objh)) + if (pdump_get_block (objh)) return; imp = LHEADER_IMPLEMENTATION (objh); @@ -588,7 +756,7 @@ { pdump_bump_depth (); backtrace[pdump_depth - 1].obj = objh; - pdump_add_entry (pdump_object_table + objh->type, + pdump_add_block (pdump_object_table + objh->type, objh, detagged_lisp_object_size (objh), 1); pdump_register_sub (objh, imp->description); --pdump_depth; @@ -601,62 +769,63 @@ } } -/* Register the referenced objects in the array of COUNT objects of - located at DATA; each object is described by SDESC. "Object" here - simply means any block of memory; it need not actually be a C - "struct". It could be a single integer or Lisp_Object, for - example, as long as the description is accurate. +/* Register the referenced objects in the array of COUNT blocks located at + DATA; each block is described by SIZE and DESC. "Block" here simply + means any block of memory. This does not register the block of memory itself; it may, for example, be an array of structures inlined in another memory block - and thus should not be registered. See pdump_register_struct(), + and thus should not be registered. See pdump_register_block(), which does register the memory block. */ static void -pdump_register_struct_contents (const void *data, - const struct sized_memory_description *sdesc, - int count) - +pdump_register_block_contents (const void *data, + Bytecount size, + const struct memory_description *desc, + int count) { int i; Bytecount elsize; pdump_bump_depth (); - elsize = lispdesc_structure_size (data, sdesc); + elsize = lispdesc_block_size_1 (data, size, desc); for (i = 0; i < count; i++) { - pdump_register_sub (((char *) data) + elsize * i, sdesc->description); + pdump_register_sub (((Rawbyte *) data) + elsize * i, desc); } --pdump_depth; } -/* Register the array of COUNT objects of located at DATA; each object is - described by SDESC. "Object" here simply means any block of memory; - it need not actually be a C "struct". It could be a single integer - or Lisp_Object, for example, as long as the description is accurate. +/* Register the array of COUNT blocks located at DATA; each block is + described by SDESC. "Block" here simply means any block of memory, + which is more accurate and less confusing than terms like `struct' and + `object'. A `block' need not actually be a C "struct". It could be a + single integer or Lisp_Object, for example, as long as the description + is accurate. - This is like pdump_register_struct_contents() but also registers + This is like pdump_register_block_contents() but also registers the memory block itself. */ static void -pdump_register_struct (const void *data, - const struct sized_memory_description *sdesc, - int count) -{ - if (data && !pdump_get_entry (data)) - { - pdump_add_entry (pdump_get_entry_list (sdesc->description), data, - lispdesc_structure_size (data, sdesc), count); - - pdump_register_struct_contents (data, sdesc, count); +pdump_register_block (const void *data, + Bytecount size, + const struct memory_description *desc, + int count) +{ + if (data && !pdump_get_block (data)) + { + pdump_add_block (pdump_get_block_list (desc), data, + lispdesc_block_size_1 (data, size, desc), count); + pdump_register_block_contents (data, size, desc, count); } } + /* Store the already-calculated new pointer offsets for all pointers in the COUNT contiguous blocks of memory, each described by DESC and of size SIZE, whose original is located at ORIG_DATA and the modifiable copy at DATA. We examine the description to figure out where the pointers are, - and then look up the replacement values using pdump_get_entry(). + and then look up the replacement values using pdump_get_block(). This is done just before writing the modified block of memory to the dump file. The new pointer offsets have been carefully calculated so @@ -688,7 +857,7 @@ for (i = 0; i < count; i++) { /* CUR points to the beginning of each block in the new data. */ - char *cur = ((char *)data) + i*size; + Rawbyte *cur = ((Rawbyte *)data) + i * size; /* Scan each line of the description for relocatable pointers */ for (pos = 0; desc[pos].type != XD_END; pos++) { @@ -719,12 +888,12 @@ break; } case XD_OPAQUE_DATA_PTR: - case XD_C_STRING: - case XD_STRUCT_PTR: + case XD_ASCII_STRING: + case XD_BLOCK_PTR: { void *ptr = * (void **) rdata; if (ptr) - * (EMACS_INT *) rdata = pdump_get_entry (ptr)->save_offset; + * (EMACS_INT *) rdata = pdump_get_block (ptr)->save_offset; break; } case XD_LO_LINK: @@ -738,7 +907,7 @@ referenced one. (The Qnil or Qunbound that ends the chain will always be a referenced object.) */ Lisp_Object obj = * (Lisp_Object *) rdata; - pdump_entry_list_elt *elt1; + pdump_block_list_elt *elt1; /* #### Figure out how to handle indirect offsets here. #### In general, when computing indirect counts, do we really need to use the orig_data pointer? Why not just @@ -752,11 +921,12 @@ assert (!XD_IS_INDIRECT (desc1->offset)); for (;;) { - elt1 = pdump_get_entry (XRECORD_LHEADER (obj)); + elt1 = pdump_get_block (XRECORD_LHEADER (obj)); if (elt1) break; obj = * (Lisp_Object *) (desc1->offset + - (char *)(XRECORD_LHEADER (obj))); + (Rawbyte *) + (XRECORD_LHEADER (obj))); } * (EMACS_INT *) rdata = elt1->save_offset; break; @@ -769,7 +939,7 @@ if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj)) * (EMACS_INT *) pobj = - pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset; + pdump_get_block (XRECORD_LHEADER (*pobj))->save_offset; break; } case XD_LISP_OBJECT_ARRAY: @@ -784,7 +954,7 @@ if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj)) * (EMACS_INT *) pobj = - pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset; + pdump_get_block (XRECORD_LHEADER (*pobj))->save_offset; } break; } @@ -793,23 +963,24 @@ EMACS_INT str = *(EMACS_INT *)rdata; if (str > 0) * (EMACS_INT *) rdata = - pdump_get_entry ((void *)str)->save_offset; + pdump_get_block ((void *)str)->save_offset; break; } - case XD_STRUCT_ARRAY: + case XD_BLOCK_ARRAY: { EMACS_INT num = lispdesc_indirect_count (desc1->data1, desc, orig_data); const struct sized_memory_description *sdesc = - lispdesc_indirect_description (orig_data, desc1->data2); + lispdesc_indirect_description (orig_data, desc1->data2.descr); pdump_store_new_pointer_offsets (num, rdata, - ((char *) rdata - (char *) data) + (char *) orig_data, + ((Rawbyte *) rdata - (Rawbyte *) data) + + (Rawbyte *) orig_data, sdesc->description, - lispdesc_structure_size - (((char *) rdata - (char *) data) + (char *) orig_data, - sdesc)); + lispdesc_block_size + (((Rawbyte *) rdata - (Rawbyte *) data) + + (Rawbyte *) orig_data, sdesc)); break; } case XD_UNION: @@ -819,6 +990,14 @@ goto union_switcheroo; break; + case XD_OPAQUE_PTR_CONVERTIBLE: + *(EMACS_INT *)rdata = pdump_find_in_cv_ptr_dynarr (*(void **)rdata)->index; + break; + + case XD_OPAQUE_DATA_CONVERTIBLE: + /* in-object, nothing to do */ + break; + default: pdump_unsupported_dump_type (desc1->type, 0); } @@ -834,7 +1013,7 @@ the dump file. */ static void -pdump_dump_data (pdump_entry_list_elt *elt, +pdump_dump_data (pdump_block_list_elt *elt, const struct memory_description *desc) { Bytecount size = elt->size; @@ -855,8 +1034,9 @@ in the block. Does not recursively relocate any other memory blocks pointed to. (We already have a list of all memory blocks in the dump file.) This is used once the dump data has been loaded back in, both - for blocks sitting in the dumped data and in global data objects whose - contents have been restored from the dumped data. */ + for blocks sitting in the dumped data (former heap blocks) and in global + data-sgment blocks whose contents have been restored from the dumped + data. */ static void pdump_reloc_one (void *data, EMACS_INT delta, @@ -867,8 +1047,9 @@ for (pos = 0; desc[pos].type != XD_END; pos++) { const struct memory_description *desc1 = &desc[pos]; - void *rdata = (char *) data + lispdesc_indirect_count (desc1->offset, - desc, data); + void *rdata = + (Rawbyte *) data + lispdesc_indirect_count (desc1->offset, + desc, data); union_switcheroo: @@ -886,8 +1067,8 @@ case XD_INT_RESET: break; case XD_OPAQUE_DATA_PTR: - case XD_C_STRING: - case XD_STRUCT_PTR: + case XD_ASCII_STRING: + case XD_BLOCK_PTR: case XD_LO_LINK: { EMACS_INT ptr = *(EMACS_INT *)rdata; @@ -903,7 +1084,7 @@ if (POINTER_TYPE_P (XTYPE (*pobj)) && ! EQ (*pobj, Qnull_pointer)) - *pobj = wrap_pointer_1 ((char *) XPNTR (*pobj) + delta); + *pobj = wrap_pointer_1 ((Rawbyte *) XPNTR (*pobj) + delta); break; } @@ -919,7 +1100,8 @@ if (POINTER_TYPE_P (XTYPE (*pobj)) && ! EQ (*pobj, Qnull_pointer)) - *pobj = wrap_pointer_1 ((char *) XPNTR (*pobj) + delta); + *pobj = wrap_pointer_1 ((Rawbyte *) XPNTR (*pobj) + + delta); } break; } @@ -930,18 +1112,18 @@ *(EMACS_INT *)rdata = str + delta; break; } - case XD_STRUCT_ARRAY: + case XD_BLOCK_ARRAY: { EMACS_INT num = lispdesc_indirect_count (desc1->data1, desc, data); int j; const struct sized_memory_description *sdesc = - lispdesc_indirect_description (data, desc1->data2); - Bytecount size = lispdesc_structure_size (rdata, sdesc); + lispdesc_indirect_description (data, desc1->data2.descr); + Bytecount size = lispdesc_block_size (rdata, sdesc); /* Note: We are recursing over data in the block itself */ for (j = 0; j < num; j++) - pdump_reloc_one ((char *) rdata + j * size, delta, + pdump_reloc_one ((Rawbyte *) rdata + j * size, delta, sdesc->description); break; @@ -953,6 +1135,28 @@ goto union_switcheroo; break; + case XD_OPAQUE_PTR_CONVERTIBLE: + { + pdump_cv_ptr_load_info *p = pdump_loaded_cv_ptr + *(EMACS_INT *)rdata; + if (!p->adr) + p->adr = desc1->data2.funcs->deconvert(0, pdump_start + + p->save_offset, p->size); + *(void **)rdata = p->adr; + break; + } + + case XD_OPAQUE_DATA_CONVERTIBLE: + { + EMACS_INT dest_offset = (Rawbyte *)rdata - pdump_start; + pdump_cv_data_dump_info *p; + + for(p = pdump_loaded_cv_data; p->dest_offset != dest_offset; p++); + + desc1->data2.funcs->deconvert(rdata, pdump_start + p->save_offset, + p->size); + break; + } + default: pdump_unsupported_dump_type (desc1->type, 0); } @@ -960,35 +1164,100 @@ } static void -pdump_allocate_offset (pdump_entry_list_elt *elt, +pdump_allocate_offset (pdump_block_list_elt *elt, const struct memory_description *UNUSED (desc)) { Bytecount size = elt->count * elt->size; elt->save_offset = cur_offset; - if (size>max_size) + if (size > max_size) max_size = size; cur_offset += size; } +/* Write out to global file descriptor PDUMP_OUT the result of an + external element. It's just opaque data. */ + +static void +pdump_dump_cv_data (pdump_cv_data_info *elt) +{ + retry_fwrite (elt->data, elt->size, 1, pdump_out); +} + +static void +pdump_dump_cv_ptr (pdump_cv_ptr_info *elt) +{ + retry_fwrite (elt->data, elt->size, 1, pdump_out); +} + +static void +pdump_allocate_offset_cv_data (pdump_cv_data_info *elt) +{ + elt->save_offset = cur_offset; + if (elt->size>max_size) + max_size = elt->size; + cur_offset += elt->size; +} + +static void +pdump_allocate_offset_cv_ptr (pdump_cv_ptr_info *elt) +{ + elt->save_offset = cur_offset; + if (elt->size>max_size) + max_size = elt->size; + cur_offset += elt->size; +} + +/* Traverse through all the heap blocks, once the "register" stage of + dumping has finished. To compress space as much as possible, we + logically sort all blocks by alignment, hitting all blocks with + alignment == the maximum (which may be 8 bytes, for doubles), then + all blocks with the next lower alignment (4 bytes), etc. + + Within each alignment we hit + + -- first the Lisp objects, type-by-type + + -- then the heap memory blocks that are not Lisp objects, description-by- + description -- i.e. all blocks with the same description will be + placed together + + -- then the "opaque" data objects declared as XD_OPAQUE_DATA_PTR, + XD_ASCII_STRING and XD_DOC_STRING. + + The idea is to have as little blank space as possible in the laid-out + data. + + For each item that we have hit, we process it by calling F, the function + passed it. In dumper.c, pdump_scan_by_alignment() is called twice with + two different functions -- pdump_allocate_offset() in stage 2 to compute + the offset to each block, and pdump_dump_data() in stage 3 to + successively write each block to disk. + + It's extremely important that the SAME traversal order gets invoked + in both stage 2 and 3. +*/ + static void -pdump_scan_by_alignment (void (*f)(pdump_entry_list_elt *, - const struct memory_description *)) +pdump_scan_by_alignment (void (*f)(pdump_block_list_elt *, + const struct memory_description *), + void (*g)(pdump_cv_data_info *), + void (*h)(pdump_cv_ptr_info *)) { int align; for (align = ALIGNOF (max_align_t); align; align>>=1) { int i; - pdump_entry_list_elt *elt; + pdump_block_list_elt *elt; for (i=0; i<lrecord_type_count; i++) if (pdump_object_table[i].align == align) for (elt = pdump_object_table[i].first; elt; elt = elt->next) f (elt, lrecord_implementations_table[i]->description); - for (i=0; i<pdump_struct_table.count; i++) + for (i=0; i<pdump_desc_table.count; i++) { - pdump_struct_list_elt list = pdump_struct_table.list[i]; + pdump_desc_list_elt list = pdump_desc_table.list[i]; if (list.list.align == align) for (elt = list.list.first; elt; elt = elt->next) f (elt, list.desc); @@ -997,35 +1266,97 @@ for (elt = pdump_opaque_data_list.first; elt; elt = elt->next) if (pdump_size_to_align (elt->size) == align) f (elt, 0); + + for (i=0; i < Dynarr_length (pdump_cv_data); i++) + if (pdump_size_to_align (Dynarr_atp (pdump_cv_data, i)->size) == align) + g (Dynarr_atp (pdump_cv_data, i)); + + for (i=0; i < Dynarr_length (pdump_cv_ptr); i++) + if (pdump_size_to_align (Dynarr_atp (pdump_cv_ptr, i)->size) == align) + h (Dynarr_atp (pdump_cv_ptr, i)); + } +} + +static void +pdump_dump_cv_data_info (void) +{ + int i; + Elemcount count = Dynarr_length (pdump_cv_data); + pdump_cv_data_dump_info *data = alloca_array (pdump_cv_data_dump_info, count); + for (i = 0; i < count; i++) + { + data[i].dest_offset = Dynarr_at (pdump_cv_data, i).dest_offset; + data[i].save_offset = Dynarr_at (pdump_cv_data, i).save_offset; + data[i].size = Dynarr_at (pdump_cv_data, i).size; + } + + PDUMP_ALIGN_OUTPUT (pdump_cv_data_dump_info); + retry_fwrite (data, sizeof (pdump_cv_data_dump_info), count, pdump_out); +} + +/* Dump out the root block pointers, part of stage 3 (the "WRITE" stage) of + dumping. For each pointer we dump out a structure containing the + location of the pointer and its value, replaced by the appropriate + offset into the dumped data. */ + +static void +pdump_dump_cv_ptr_info (void) +{ + int i; + Elemcount count = Dynarr_length (pdump_cv_ptr); + pdump_cv_ptr_dump_info *data = alloca_array (pdump_cv_ptr_dump_info, count); + for (i = 0; i < count; i++) + { + data[i].save_offset = Dynarr_at (pdump_cv_ptr, i).save_offset; + data[i].size = Dynarr_at (pdump_cv_ptr, i).size; } + + PDUMP_ALIGN_OUTPUT (pdump_cv_ptr_dump_info); + retry_fwrite (data, sizeof (pdump_cv_ptr_dump_info), count, pdump_out); } static void -pdump_dump_root_struct_ptrs (void) +pdump_dump_root_block_ptrs (void) { int i; - Elemcount count = Dynarr_length (pdump_root_struct_ptrs); + Elemcount count = Dynarr_length (pdump_root_block_ptrs); pdump_static_pointer *data = alloca_array (pdump_static_pointer, count); for (i = 0; i < count; i++) { data[i].address = - (char **) Dynarr_atp (pdump_root_struct_ptrs, i)->ptraddress; + (Rawbyte **) Dynarr_atp (pdump_root_block_ptrs, i)->ptraddress; data[i].value = - (char *) pdump_get_entry (* data[i].address)->save_offset; + (Rawbyte *) pdump_get_block (* data[i].address)->save_offset; } PDUMP_ALIGN_OUTPUT (pdump_static_pointer); retry_fwrite (data, sizeof (pdump_static_pointer), count, pdump_out); } +/* Dump out the root blocks, part of stage 3 (the "WRITE" stage) of + dumping. For each block we dump a structure containing info about the + block (its location, size and description) and then the block itself, + with its pointers replaced with offsets into the dump data. */ + static void pdump_dump_root_blocks (void) { int i; for (i = 0; i < Dynarr_length (pdump_root_blocks); i++) { - pdump_root_block *info = Dynarr_atp (pdump_root_blocks, i); - PDUMP_WRITE_ALIGNED (pdump_root_block, *info); - retry_fwrite (info->varaddress, info->size, 1, pdump_out); + pdump_root_block info = Dynarr_at (pdump_root_blocks, i); + PDUMP_WRITE_ALIGNED (pdump_root_block, info); + + if (info.desc) + { + /* Copy to temporary buffer */ + memcpy (pdump_buf, info.blockaddr, info.size); + + /* Store new offsets into all pointers in block */ + pdump_store_new_pointer_offsets (1, pdump_buf, info.blockaddr, + info.desc, info.size); + } + retry_fwrite (info.desc ? pdump_buf : info.blockaddr, + info.size, 1, pdump_out); } } @@ -1033,7 +1364,7 @@ pdump_dump_rtables (void) { int i; - pdump_entry_list_elt *elt; + pdump_block_list_elt *elt; pdump_reloc_table rt; for (i=0; i<lrecord_type_count; i++) @@ -1046,7 +1377,7 @@ PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt); while (elt) { - EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset; + EMACS_INT rdata = pdump_get_block (elt->obj)->save_offset; PDUMP_WRITE_ALIGNED (EMACS_INT, rdata); elt = elt->next; } @@ -1056,15 +1387,15 @@ rt.count = 0; PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt); - for (i=0; i<pdump_struct_table.count; i++) + for (i=0; i<pdump_desc_table.count; i++) { - elt = pdump_struct_table.list[i].list.first; - rt.desc = pdump_struct_table.list[i].desc; - rt.count = pdump_struct_table.list[i].list.count; + elt = pdump_desc_table.list[i].list.first; + rt.desc = pdump_desc_table.list[i].desc; + rt.count = pdump_desc_table.list[i].list.count; PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt); while (elt) { - EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset; + EMACS_INT rdata = pdump_get_block (elt->obj)->save_offset; int j; for (j=0; j<elt->count; j++) { @@ -1097,15 +1428,15 @@ if (POINTER_TYPE_P (XTYPE (obj.value))) obj.value = - wrap_pointer_1 ((void *) pdump_get_entry (XRECORD_LHEADER + wrap_pointer_1 ((void *) pdump_get_block (XRECORD_LHEADER (obj.value))->save_offset); PDUMP_WRITE (pdump_static_Lisp_Object, obj); } - for (i=0; i<Dynarr_length (pdump_weak_object_chains); i++) + for (i = 0; i < Dynarr_length (pdump_weak_object_chains); i++) { - pdump_entry_list_elt *elt; + pdump_block_list_elt *elt; pdump_static_Lisp_Object obj; obj.address = Dynarr_at (pdump_weak_object_chains, i); @@ -1115,7 +1446,7 @@ { const struct memory_description *desc; int pos; - elt = pdump_get_entry (XRECORD_LHEADER (obj.value)); + elt = pdump_get_block (XRECORD_LHEADER (obj.value)); if (elt) break; desc = XRECORD_LHEADER_IMPLEMENTATION (obj.value)->description; @@ -1126,7 +1457,7 @@ assert (!XD_IS_INDIRECT (desc[pos].offset)); obj.value = * (Lisp_Object *) (desc[pos].offset + - (char *) (XRECORD_LHEADER (obj.value))); + (Rawbyte *) (XRECORD_LHEADER (obj.value))); } obj.value = wrap_pointer_1 ((void *) elt->save_offset); @@ -1134,6 +1465,123 @@ } } + +/*######################################################################## + # Pdump # + ######################################################################## + + [ben] + + DISCUSSION OF DUMPING: + + The idea of dumping is to record the state of XEmacs in a file, so that + it can be reloaded later. This avoids having to reload all of the basic + Lisp code each time XEmacs is run, which is a rather time-consuming + process. (Less so on new machines, but still noticeable. As an example + of a program with similar issues but which does not have a dumping + process and as a result has a slow startup time, consider Adobe Photoshop + 5.0 or Adobe Photoshop Elements 2.0.) + + We don't actually record ALL the state of XEmacs (some of it, for example, + is dependent on the run-time environment and needs to be initialized + whenever XEmacs is run), but whatever state we don't record needs to be + reinitialized every time XEmacs is run. + + The old way of dumping was to make a new executable file with the data + segment expanded to contain the heap and written out from memory. This + is what the unex* files do. Unfortunately this process is extremely + system-specific and breaks easily with OS changes. + + Another simple, more portable trick, the "static heap" method, involves + replacing the allocator with our own allocator which allocates all space + out of a very large array declared in our data segment until we run out, + then uses the underlying malloc() to start allocating on the heap. If we + ensure that the large array is big enough to hold all data allocated + during the dump stage, then all of the data we need to save is in the + data segment, and it's easy to calculate the location and size of the + data segment we want to save (we don't want to record and reinitialize + the data segment of library functions) by using appropriately declared + variables in the first and last file linked. This method is known as the + "static heap" method, and is used by the non-pdump version of the dumper + under Cygwin, and was also used under VMS and in Win-Emacs. + + The "static heap" method works well in practice. Nonetheless, a more + complex method of dumping was written by Olivier Galibert, which requires + that structural descriptions of all data allocated in the heap be provided + and the roots of all pointers into the heap be noted through function calls + to the pdump API. This way, all the heap data can be traversed and written + out to a file, and then reloaded at run-time and the pointers relocated to + point at the new location of the loaded data. This is the "pdump" method + used in this file. + + There are two potential advantages of "pdump" over the "static heap": + + (1) It doesn't require any tricks to calculate the beginning and end of + the data segment, or even that the XEmacs section of the data segment + be contiguous. (It's not clear whether this is an issue in practice.) + (2) Potentially, it could handle an OS that does not always load the + static data segment at a predictable location. The "static heap" + method by its nature needs the data segment to stay in the same place + from invocation to invocation, since it simply dumps out memory and + reloads it, without any pointer relocation. I say "potentially" + because as it is currently written pdump does assume that the data + segment is never relocated. However, changing pdump to remove this + assumption is probably not difficult, as all the mechanism to handle + pointer relocation is already present. + + + DISCUSSION OF PDUMP WORKINGS: + + See man/internals/internals.texi for more information. + + NOTE that we have two kinds of memory to handle: memory on the heap + (i.e. allocated through malloc()) or the like, and static memory in the + data segment of the program, i.e. stuff declared as global or static. + All heap memory needs to be written out to the dump file and reproduced + (i.e. reloaded and any necessary relocations performed). Data-segment + memory that is not statically initialized (i.e. through declarations in + the C code) needs either to be written out and reloaded, or + reinitialized. In addition, any pointers in data-segment memory to heap + memory must be written out, reloaded and relocated. + + NOTE that we currently don't handle relocation of pointers into data- + segment memory. (See overview discussion above.) These are treated in + the descriptions as opaque data not needing relocation. If this becomes a + problem, it can be fixed through new kinds of types in + enum memory_description_type. + + Three basic steps to dumping out: + + (1) "REGISTER": + Starting with all sources of relocatable memory (currently this means + all data-segment pointers to heap memory -- see above about pointers + to data-segment memory), recursively traverse the tree of pointers + and "register" (make a note of) every memory block seen. + + (2) "LAYOUT": + Go through all of the registered blocks and compute the location of + each one in the dump data (i.e. the "offset" that will be added to + the address corresponding to start of the loaded-in data to get the + new pointer referring to this block). The blocks will be laid out + sequentially according to the order we traverse them. Also note the + maximum-sized block for use in step 3. + + (3) "WRITE": + After writing some header stuff, go through all of the registered + blocks and write out each one to the dump file. Note that we are + simply writing out the blocks sequentially as we see them, and our + traversal path is identical to that in step 2, so blocks will end up + at the locations computed for them. In order to write out a block, + first copy it to a temporary location (hence the maximum-block-size + computation in the previous step), then for each relocatable pointer + in the block, write in its place the offset to the heap block in the + dump data. When the dump data is loaded, the address of the + beginning of the dump data will be added to the offset in each + pointer, and thence become accurate. + + --ben +*/ + void pdump (void) { @@ -1144,7 +1592,7 @@ in_pdump = 1; - pdump_object_table = xnew_array (pdump_entry_list, lrecord_type_count); + pdump_object_table = xnew_array (pdump_block_list, lrecord_type_count); pdump_alert_undump_object = xnew_array (int, lrecord_type_count); assert (ALIGNOF (max_align_t) <= pdump_align_table[0]); @@ -1172,35 +1620,45 @@ lrecord_type_count * sizeof (lrecord_markers[0])); #endif /* not USE_KKCC */ - pdump_hash = xnew_array_and_zero (pdump_entry_list_elt *, PDUMP_HASHSIZE); + pdump_hash = xnew_array_and_zero (pdump_block_list_elt *, PDUMP_HASHSIZE); - for (i=0; i<lrecord_type_count; i++) + for (i = 0; i<lrecord_type_count; i++) { pdump_object_table[i].first = 0; pdump_object_table[i].align = ALIGNOF (max_align_t); pdump_object_table[i].count = 0; pdump_alert_undump_object[i] = 0; } - pdump_struct_table.count = 0; - pdump_struct_table.size = -1; + pdump_desc_table.count = 0; + pdump_desc_table.size = -1; pdump_opaque_data_list.first = 0; pdump_opaque_data_list.align = ALIGNOF (max_align_t); pdump_opaque_data_list.count = 0; pdump_depth = 0; + pdump_cv_data = Dynarr_new2 (pdump_cv_data_info_dynarr, pdump_cv_data_info); + pdump_cv_ptr = Dynarr_new2 (pdump_cv_ptr_info_dynarr, pdump_cv_ptr_info); + + /* (I) The "register" stage: Note all heap memory blocks to be relocated + */ + + /* Try various roots of accessibility: */ + + /* (1) Lisp objects, both those declared using DEFVAR_LISP*() and those + staticpro()d. */ for (i = 0; i < Dynarr_length (pdump_root_lisp_objects); i++) pdump_register_object (* Dynarr_at (pdump_root_lisp_objects, i)); none = 1; - for (i=0; i<lrecord_type_count; i++) + for (i = 0; i < lrecord_type_count; i++) if (pdump_alert_undump_object[i]) { if (none) - printf ("Undumpable types list :\n"); + stderr_out ("Undumpable types list :\n"); none = 0; - printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, - pdump_alert_undump_object[i]); + stderr_out (" - %s (%d)\n", lrecord_implementations_table[i]->name, + pdump_alert_undump_object[i]); } if (!none) { @@ -1208,26 +1666,72 @@ return; } - for (i=0; i<Dynarr_length (pdump_root_struct_ptrs); i++) + /* (2) Register out the data-segment pointer variables to heap blocks */ + for (i = 0; i < Dynarr_length (pdump_root_block_ptrs); i++) { - pdump_root_struct_ptr info = Dynarr_at (pdump_root_struct_ptrs, i); - pdump_register_struct (*(info.ptraddress), info.desc, 1); + pdump_root_block_ptr info = Dynarr_at (pdump_root_block_ptrs, i); + pdump_register_block (*(info.ptraddress), info.desc->size, + info.desc->description, 1); } + /* (3) Register out the data-segment blocks, maybe with pointers to heap + blocks */ + for (i = 0; i < Dynarr_length (pdump_root_blocks); i++) + { + pdump_root_block *info = Dynarr_atp (pdump_root_blocks, i); + if (info->desc) + { + /* Size may have been given as 0 meaning "compute later". + Compute now and update. If no DESC, size must always be + correct as there is no other way of computing it. */ + info->size = lispdesc_block_size_1 (info->blockaddr, info->size, + info->desc); + pdump_register_block_contents (info->blockaddr, info->size, + info->desc, 1); + } + } + + /* (II) The "layout" stage: Compute the offsets and max-size */ + + /* (1) Determine header size */ memcpy (header.signature, PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN); header.id = dump_id; header.reloc_address = 0; - header.nb_root_struct_ptrs = Dynarr_length (pdump_root_struct_ptrs); + header.nb_root_block_ptrs = Dynarr_length (pdump_root_block_ptrs); header.nb_root_blocks = Dynarr_length (pdump_root_blocks); + header.nb_cv_data = Dynarr_length (pdump_cv_data); + header.nb_cv_ptr = Dynarr_length (pdump_cv_ptr); cur_offset = MAX_ALIGN_SIZE (sizeof (header)); max_size = 0; - pdump_scan_by_alignment (pdump_allocate_offset); + /* (2) Traverse all heap blocks and compute their offsets; keep track + of maximum block size seen */ + pdump_scan_by_alignment (pdump_allocate_offset, + pdump_allocate_offset_cv_data, + pdump_allocate_offset_cv_ptr); cur_offset = MAX_ALIGN_SIZE (cur_offset); header.stab_offset = cur_offset; + /* (3) Update maximum size based on root (data-segment) blocks */ + for (i = 0; i < Dynarr_length (pdump_root_blocks); i++) + { + pdump_root_block info = Dynarr_at (pdump_root_blocks, i); + + /* If no DESC, no relocation needed and we copy directly instead of + into a temp buffer. */ + if (info.desc) + { + if (info.size > max_size) + max_size = info.size; + } + } + + /* (III) The "write "stage: Dump out the data, storing the offsets in + place of pointers whenever we write out memory blocks */ + pdump_buf = xmalloc (max_size); + /* EMACS_PROGNAME is entirely ASCII so this should be Mule-safe */ pdump_fd = open (EMACS_PROGNAME ".dmp", O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666); if (pdump_fd < 0) @@ -1241,11 +1745,37 @@ retry_fwrite (&header, sizeof (header), 1, pdump_out); PDUMP_ALIGN_OUTPUT (max_align_t); - pdump_scan_by_alignment (pdump_dump_data); + for (i = 0; i < Dynarr_length (pdump_cv_data); i++) + { + pdump_cv_data_info *elt = Dynarr_atp (pdump_cv_data, i); + elt->dest_offset = + pdump_get_block (elt->object)->save_offset + elt->offset; + } + + for (i = 0; i < Dynarr_length (pdump_cv_ptr); i++) + Dynarr_at (pdump_cv_ptr, i).index = i; + + pdump_scan_by_alignment (pdump_dump_data, pdump_dump_cv_data, pdump_dump_cv_ptr); + + for (i = 0; i < Dynarr_length (pdump_cv_data); i++) + { + pdump_cv_data_info *elt = Dynarr_atp (pdump_cv_data, i); + if(elt->fcts->convert_free) + elt->fcts->convert_free(elt->object, elt->data, elt->size); + } + + for (i = 0; i < Dynarr_length (pdump_cv_ptr); i++) + { + pdump_cv_ptr_info *elt = Dynarr_atp (pdump_cv_ptr, i); + if(elt->fcts->convert_free) + elt->fcts->convert_free(elt->object, elt->data, elt->size); + } fseek (pdump_out, header.stab_offset, SEEK_SET); - pdump_dump_root_struct_ptrs (); + pdump_dump_cv_data_info (); + pdump_dump_cv_ptr_info (); + pdump_dump_root_block_ptrs (); pdump_dump_root_blocks (); pdump_dump_rtables (); pdump_dump_root_lisp_objects (); @@ -1266,7 +1796,7 @@ static int pdump_load_check (void) { - return (!memcmp (((pdump_header *)pdump_start)->signature, + return (!memcmp (((pdump_header *) pdump_start)->signature, PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN) && ((pdump_header *)pdump_start)->id == dump_id); } @@ -1278,7 +1808,7 @@ pdump_load_finish (void) { int i; - char *p; + Rawbyte *p; EMACS_INT delta; EMACS_INT count; pdump_header *header = (pdump_header *) pdump_start; @@ -1288,9 +1818,26 @@ delta = ((EMACS_INT) pdump_start) - header->reloc_address; p = pdump_start + header->stab_offset; - /* Put back the pdump_root_struct_ptrs */ - p = (char *) ALIGN_PTR (p, pdump_static_pointer); - for (i = 0; i < header->nb_root_struct_ptrs; i++) + /* Get the cv_data array */ + p = (Rawbyte *) ALIGN_PTR (p, pdump_cv_data_dump_info); + pdump_loaded_cv_data = (pdump_cv_data_dump_info *)p; + p += header->nb_cv_data*sizeof(pdump_cv_data_dump_info); + + /* Build the cv_ptr array */ + p = (Rawbyte *) ALIGN_PTR (p, pdump_cv_ptr_dump_info); + pdump_loaded_cv_ptr = + alloca_array (pdump_cv_ptr_load_info, header->nb_cv_ptr); + for (i = 0; i < header->nb_cv_ptr; i++) + { + pdump_cv_ptr_dump_info info = PDUMP_READ (p, pdump_cv_ptr_dump_info); + pdump_loaded_cv_ptr[i].save_offset = info.save_offset; + pdump_loaded_cv_ptr[i].size = info.size; + pdump_loaded_cv_ptr[i].adr = 0; + } + + /* 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); (* ptr.address) = ptr.value + delta; @@ -1300,9 +1847,9 @@ for (i = 0; i < header->nb_root_blocks; i++) { pdump_root_block info = PDUMP_READ_ALIGNED (p, pdump_root_block); - memcpy ((void *) info.varaddress, p, info.size); + memcpy ((void *) info.blockaddr, p, info.size); if (info.desc) - pdump_reloc_one ((void *) info.varaddress, delta, info.desc); + pdump_reloc_one ((void *) info.blockaddr, delta, info.desc); p += info.size; } @@ -1312,16 +1859,16 @@ for (;;) { pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table); - p = (char *) ALIGN_PTR (p, char *); + p = (Rawbyte *) ALIGN_PTR (p, Rawbyte *); if (rt.desc) { - char **reloc = (char **) p; + Rawbyte **reloc = (Rawbyte **) p; for (i = 0; i < rt.count; i++) { reloc[i] += delta; pdump_reloc_one (reloc[i], delta, rt.desc); } - p += rt.count * sizeof (char *); + p += rt.count * sizeof (Rawbyte *); } else if (!(--count)) break; @@ -1329,13 +1876,13 @@ /* Put the pdump_root_lisp_objects variables in place */ i = PDUMP_READ_ALIGNED (p, Elemcount); - p = (char *) ALIGN_PTR (p, pdump_static_Lisp_Object); + p = (Rawbyte *) ALIGN_PTR (p, pdump_static_Lisp_Object); while (i--) { pdump_static_Lisp_Object obj = PDUMP_READ (p, pdump_static_Lisp_Object); if (POINTER_TYPE_P (XTYPE (obj.value))) - obj.value = wrap_pointer_1 ((char *) XPNTR (obj.value) + delta); + obj.value = wrap_pointer_1 ((Rawbyte *) XPNTR (obj.value) + delta); (* obj.address) = obj.value; } @@ -1346,7 +1893,7 @@ for (;;) { pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table); - p = (char *) ALIGN_PTR (p, Lisp_Object); + p = (Rawbyte *) ALIGN_PTR (p, Lisp_Object); if (!rt.desc) break; if (rt.desc == hash_table_description) @@ -1373,34 +1920,43 @@ } static int -pdump_file_get (const char *path) +pdump_file_get (const Wexttext *wpath) { + Extbyte *path; + if (XEUNICODE_P) + path = (Extbyte *) wpath; + else + path = WEXTTEXT_TO_MULTIBYTE (wpath); - pdump_hFile = CreateFileA (path, - GENERIC_READ + GENERIC_WRITE, /* Required for copy on write */ - 0, /* Not shared */ - NULL, /* Not inheritable */ - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); /* No template file */ + pdump_hFile = + qxeCreateFile (path, + GENERIC_READ + GENERIC_WRITE, /* Required for copy on + write */ + 0, /* Not shared */ + NULL, /* Not inheritable */ + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); /* No template file */ if (pdump_hFile == INVALID_HANDLE_VALUE) return 0; pdump_length = GetFileSize (pdump_hFile, NULL); - pdump_hMap = CreateFileMappingA (pdump_hFile, - NULL, /* No security attributes */ - PAGE_WRITECOPY, /* Copy on write */ - 0, /* Max size, high half */ - 0, /* Max size, low half */ - NULL); /* Unnamed */ + pdump_hMap = + qxeCreateFileMapping (pdump_hFile, + NULL, /* No security attributes */ + PAGE_WRITECOPY, /* Copy on write */ + 0, /* Max size, high half */ + 0, /* Max size, low half */ + NULL); /* Unnamed */ if (pdump_hMap == INVALID_HANDLE_VALUE) return 0; - pdump_start = (char *) MapViewOfFile (pdump_hMap, - FILE_MAP_COPY, /* Copy on write */ - 0, /* Start at zero */ - 0, - 0); /* Map all of it */ + pdump_start = + (Rawbyte *) MapViewOfFile (pdump_hMap, + FILE_MAP_COPY, /* Copy on write */ + 0, /* Start at zero */ + 0, + 0); /* Map all of it */ pdump_free = pdump_file_unmap; return 1; } @@ -1439,7 +1995,7 @@ if (hResLoad == NULL) return 0; - pdump_start = (char *) LockResource (hResLoad); + pdump_start = (Rawbyte *) LockResource (hResLoad); if (pdump_start == NULL) return 0; @@ -1459,7 +2015,7 @@ static void pdump_file_free (void) { - xfree (pdump_start, char *); + xfree (pdump_start, Rawbyte *); } #ifdef HAVE_MMAP @@ -1471,10 +2027,10 @@ #endif static int -pdump_file_get (const char *path) +pdump_file_get (const Wexttext *path) { - int fd = open (path, O_RDONLY | OPEN_BINARY); - if (fd<0) + int fd = wext_retry_open (path, O_RDONLY | OPEN_BINARY); + if (fd < 0) return 0; pdump_length = lseek (fd, 0, SEEK_END); @@ -1492,8 +2048,10 @@ # ifndef MAP_FAILED # define MAP_FAILED ((void *) -1L) # endif - pdump_start = (char *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); - if (pdump_start != (char *) MAP_FAILED) + pdump_start = + (Rawbyte *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, + fd, 0); + if (pdump_start != (Rawbyte *) MAP_FAILED) { pdump_free = pdump_file_unmap; retry_close (fd); @@ -1501,7 +2059,7 @@ } #endif /* HAVE_MMAP */ - pdump_start = xnew_array (char, pdump_length); + pdump_start = xnew_array (Rawbyte, pdump_length); pdump_free = pdump_file_free; retry_read (fd, pdump_start, pdump_length); @@ -1512,23 +2070,28 @@ static int pdump_ram_try (void) { - pdump_start = dumped_data_get(); - pdump_length = dumped_data_size(); + pdump_start = dumped_data_get (); + pdump_length = dumped_data_size (); - return pdump_load_check(); + return pdump_load_check (); } #endif /* !WIN32_NATIVE */ static int -pdump_file_try (char *exe_path) +pdump_file_try (Wexttext *exe_path) { - char *w = exe_path + strlen (exe_path); + Wexttext *w = exe_path + wext_strlen (exe_path); + /* We look for various names, including those with the version and dump ID, + those with just the dump ID, and those without either. We first try + adding directly to the executable name, then lopping off any extension + (e.g. .exe) or version name in the executable (xemacs-21.5.18). */ do { - sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id); + wext_sprintf (w, WEXTSTRING ("-%s-%08x.dmp"), WEXTSTRING (EMACS_VERSION), + dump_id); if (pdump_file_get (exe_path)) { if (pdump_load_check ()) @@ -1536,7 +2099,7 @@ pdump_free (); } - sprintf (w, "-%08x.dmp", dump_id); + wext_sprintf (w, WEXTSTRING ("-%08x.dmp"), dump_id); if (pdump_file_get (exe_path)) { if (pdump_load_check ()) @@ -1544,7 +2107,7 @@ pdump_free (); } - sprintf (w, ".dmp"); + wext_sprintf (w, WEXTSTRING (".dmp")); if (pdump_file_get (exe_path)) { if (pdump_load_check ()) @@ -1554,50 +2117,87 @@ do w--; - while (w>exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && (*w != '.')); + /* !!#### See comment below about how this is unsafe. */ + while (w > exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && + (*w != '.')); } - while (w>exe_path && !IS_DIRECTORY_SEP (*w)); + while (w > exe_path && !IS_DIRECTORY_SEP (*w)); return 0; } int -pdump_load (const Extbyte *argv0) +pdump_load (const Wexttext *argv0) { - Extbyte exe_path[PATH_MAX]; - #ifdef WIN32_NATIVE - GetModuleFileNameA (NULL, exe_path, PATH_MAX); + Wexttext *exe_path = NULL; + int bufsize = 4096; + int cchpathsize; +#define DUMP_SLACK 100 /* Enough to include dump ID, version name, .DMP */ + + /* Copied from mswindows_get_module_file_name (). Not clear if it's + kosher to malloc() yet. */ + while (1) + { + exe_path = alloca_array (Wexttext, bufsize); + cchpathsize = qxeGetModuleFileName (NULL, (Extbyte *) exe_path, + bufsize); + if (!cchpathsize) + goto fail; + if (cchpathsize + DUMP_SLACK <= bufsize) + break; + bufsize *= 2; + } + + if (!XEUNICODE_P) + { + Wexttext *wexe = MULTIBYTE_TO_WEXTTEXT ((Extbyte *) exe_path); + wext_strcpy (exe_path, wexe); + } #else /* !WIN32_NATIVE */ - Extbyte *w; - const Extbyte *dir, *p; + Wexttext *exe_path; + Wexttext *w; + const Wexttext *dir, *p; - if(pdump_ram_try()) { - pdump_load_finish(); - in_pdump = 0; - return 1; - } + if (pdump_ram_try ()) + { + pdump_load_finish (); + in_pdump = 0; + return 1; + } in_pdump = 1; dir = argv0; if (dir[0] == '-') { /* XEmacs as a login shell, oh goody! */ - dir = getenv ("SHELL"); /* not egetenv -- not yet initialized */ + dir = wext_getenv ("SHELL"); /* not egetenv -- not yet initialized and we + want external-format data */ } - p = dir + strlen (dir); - while (p != dir && !IS_ANY_SEP (p[-1])) p--; + p = dir + wext_strlen (dir); + /* !!#### This is bad as it may fail with certain non-ASCII-compatible + external formats such as JIS. Maybe we should be using the mb*() + routines in libc? But can we reliably trust them on all Unix + platforms? (We can't convert to internal since those conversion + routines aren't yet initialized) */ + while (p != dir && !IS_ANY_SEP (p[-1])) + p--; if (p != dir) { /* invocation-name includes a directory component -- presumably it is relative to cwd, not $PATH */ - strcpy (exe_path, dir); + exe_path = alloca_array (Wexttext, 1 + wext_strlen (dir)); + wext_strcpy (exe_path, dir); } else { - const Extbyte *path = getenv ("PATH"); /* not egetenv -- not yet init. */ - const Extbyte *name = p; + const Wexttext *path = wext_getenv ("PATH"); /* not egetenv -- + not yet init. */ + const Wexttext *name = p; + exe_path = alloca_array (Wexttext, + 10 + max (wext_strlen (name), + wext_strlen (path))); for (;;) { p = path; @@ -1610,22 +2210,17 @@ } else { - memcpy (exe_path, path, p - path); + memcpy (exe_path, path, (p - path) * sizeof (Wexttext)); w = exe_path + (p - path); } if (!IS_DIRECTORY_SEP (w[-1])) - { - *w++ = '/'; - } - strcpy (w, name); - -#undef access /* avoid !@#$%^& encapsulated access */ -#undef stat /* avoid !@#$%^& encapsulated stat */ + *w++ = '/'; + wext_strcpy (w, name); { struct stat statbuf; - if (access (exe_path, X_OK) == 0 - && stat (exe_path, &statbuf) == 0 + if (wext_access (exe_path, X_OK) == 0 + && wext_stat (exe_path, &statbuf) == 0 && ! S_ISDIR (statbuf.st_mode)) break; } @@ -1633,10 +2228,10 @@ if (!*p) { /* Oh well, let's have some kind of default */ - sprintf (exe_path, "./%s", name); + wext_sprintf (exe_path, "./%s", name); break; } - path = p+1; + path = p + 1; } } #endif /* WIN32_NATIVE */ @@ -1659,6 +2254,8 @@ } pdump_free (); } + +fail: #endif in_pdump = 0; diff --text -u 'xemacs-21.5.18/src/dumper.h' 'xemacs-21.5.19/src/dumper.h' Index: ./src/dumper.h --- ./src/dumper.h Tue Oct 14 14:03:03 2003 +++ ./src/dumper.h Tue Feb 15 12:17:07 2005 @@ -20,6 +20,8 @@ /* Synched up with: Not in FSF. */ +/* This file has been Mule-ized, Ben Wing, 10-7-04. */ + #ifndef INCLUDED_dumper_h #define INCLUDED_dumper_h @@ -27,10 +29,10 @@ void pdump_objects_unmark (void); void pdump (void); -int pdump_load (const char *argv0); +int pdump_load (const Wexttext *argv0); void pdump_backtrace (void); extern unsigned int dump_id; -extern char *pdump_start, *pdump_end; +extern Rawbyte *pdump_start, *pdump_end; END_C_DECLS diff --text -u 'xemacs-21.5.18/src/dynarr.c' 'xemacs-21.5.19/src/dynarr.c' Index: ./src/dynarr.c --- ./src/dynarr.c Wed Oct 1 00:26:41 2003 +++ ./src/dynarr.c Tue Jan 25 08:33:50 2005 @@ -1,6 +1,6 @@ /* Support for dynamic arrays. Copyright (C) 1993 Sun Microsystems, Inc. - Copyright (C) 2002, 2003 Ben Wing. + Copyright (C) 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -45,10 +45,10 @@ This is a container object. Declare a dynamic array of a specific type as follows: -typedef struct -{ - Dynarr_declare (mytype); -} mytype_dynarr; + typedef struct + { + Dynarr_declare (mytype); + } mytype_dynarr; Use the following functions/macros: @@ -129,7 +129,7 @@ static int Dynarr_min_size = 8; static void -Dynarr_realloc (Dynarr *dy, int new_size) +Dynarr_realloc (Dynarr *dy, Bytecount new_size) { if (DUMPEDP (dy->base)) { @@ -151,7 +151,7 @@ } void -Dynarr_resize (void *d, int size) +Dynarr_resize (void *d, Elemcount size) { int newsize; double multiplier; @@ -271,3 +271,70 @@ } #endif /* MEMORY_USAGE_STATS */ + +/* Version of malloc() that will be extremely efficient when allocation + nearly always occurs in LIFO (stack) order. + + #### Perhaps shouldn't be in this file, but where else? */ + +typedef struct +{ + Dynarr_declare (char_dynarr *); +} char_dynarr_dynarr; + +char_dynarr_dynarr *stack_like_free_list; +char_dynarr_dynarr *stack_like_in_use_list; + +void * +stack_like_malloc (Bytecount size) +{ + char_dynarr *this_one; + if (!stack_like_free_list) + { + stack_like_free_list = Dynarr_new2 (char_dynarr_dynarr, + char_dynarr *); + stack_like_in_use_list = Dynarr_new2 (char_dynarr_dynarr, + char_dynarr *); + } + + if (Dynarr_length (stack_like_free_list) > 0) + this_one = Dynarr_pop (stack_like_free_list); + else + this_one = Dynarr_new (char); + Dynarr_add (stack_like_in_use_list, this_one); + Dynarr_resize (this_one, size); + return Dynarr_atp (this_one, 0); +} + +void +stack_like_free (void *val) +{ + int len = Dynarr_length (stack_like_in_use_list); + assert (len > 0); + /* The vast majority of times, we will be called in a last-in first-out + order, and the item at the end of the list will be the one we're + looking for, so just check for this first and avoid any function + calls. */ + if (Dynarr_atp (Dynarr_at (stack_like_in_use_list, len - 1), 0) == val) + { + char_dynarr *this_one = Dynarr_pop (stack_like_in_use_list); + Dynarr_add (stack_like_free_list, this_one); + } + else + { + /* Find the item and delete it. */ + int i; + assert (len >= 2); + for (i = len - 2; i >= 0; i--) + if (Dynarr_atp (Dynarr_at (stack_like_in_use_list, i), 0) == + val) + { + char_dynarr *this_one = Dynarr_at (stack_like_in_use_list, i); + Dynarr_add (stack_like_free_list, this_one); + Dynarr_delete (stack_like_in_use_list, i); + return; + } + + ABORT (); + } +} diff --text -u 'xemacs-21.5.18/src/editfns.c' 'xemacs-21.5.19/src/editfns.c' Index: ./src/editfns.c --- ./src/editfns.c Tue Sep 21 04:19:39 2004 +++ ./src/editfns.c Mon Dec 6 12:52:03 2004 @@ -1,7 +1,7 @@ /* Lisp functions pertaining to editing. Copyright (C) 1985-1987, 1989, 1992-1995 Free Software Foundation, Inc. Copyright (C) 1995 Tinker Systems and INS Engineering Corp. - Copyright (C) 1996, 2001, 2002 Ben Wing. + Copyright (C) 1996, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -607,7 +607,7 @@ DECLARE_EISTRING (eipath); Ibyte *path; - eicpy_c (eipath, "/tmp/"); + eicpy_ascii (eipath, "/tmp/"); eicat_rawz (eipath, login_name); path = eidata (eipath); if (qxe_lstat (path, &st) < 0 && errno == ENOENT) @@ -618,7 +618,7 @@ else { eicpy_rawz (eipath, egetenv ("HOME")); - eicat_c (eipath, "/tmp/"); + eicat_ascii (eipath, "/tmp/"); path = eidata (eipath); if (qxe_stat (path, &st) < 0 && errno == ENOENT) { @@ -627,7 +627,7 @@ qxe_mkdir (path, 0700); /* ignore retvals */ eicpy_ei (eiwarnpath, eipath); - eicat_c (eiwarnpath, ".created_by_xemacs"); + eicat_ascii (eiwarnpath, ".created_by_xemacs"); if ((fd = qxe_open (eidata (eiwarnpath), O_WRONLY | O_CREAT, 0644)) > 0) { @@ -851,8 +851,8 @@ (homepath = egetenv ("HOMEPATH")) != NULL) { cached_home_directory = - (Ibyte *) xmalloc (qxestrlen (homedrive) + - qxestrlen (homepath) + 1); + xnew_ibytes (qxestrlen (homedrive) + qxestrlen (homepath) + + ITEXT_ZTERM_SIZE); qxesprintf (cached_home_directory, "%s%s", homedrive, homepath); @@ -1061,7 +1061,7 @@ while (1) { - Extbyte *buf = (Extbyte *) ALLOCA (size); + Extbyte *buf = alloca_extbytes (size); Extbyte *formext; *buf = 1; @@ -1339,8 +1339,8 @@ See Sun bugs 1113095 and 1114114, ``Timezone routines improperly modify environment''. */ -static Char_ASCII set_time_zone_rule_tz1[] = "TZ=GMT+0"; -static Char_ASCII set_time_zone_rule_tz2[] = "TZ=GMT+1"; +static Ascbyte set_time_zone_rule_tz1[] = "TZ=GMT+0"; +static Ascbyte set_time_zone_rule_tz2[] = "TZ=GMT+1"; #endif @@ -1579,7 +1579,7 @@ if (n <= 0) return Qnil; slen = min (n, (Bytecount) 768); - string = alloca_array (Ibyte, slen); + string = alloca_ibytes (slen); /* Write as many copies of the character into the temp string as will fit. */ for (i = 0; i + charlen <= slen; i += charlen) for (j = 0; j < charlen; j++) diff --text -u 'xemacs-21.5.18/src/elhash.c' 'xemacs-21.5.19/src/elhash.c' Index: ./src/elhash.c --- ./src/elhash.c Fri Oct 15 02:26:23 2004 +++ ./src/elhash.c Fri Feb 4 01:14:05 2005 @@ -1,6 +1,6 @@ /* Implementation of the hash table lisp object type. Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. - Copyright (C) 1995, 1996, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2002, 2004 Ben Wing. Copyright (C) 1997 Free Software Foundation, Inc. This file is part of XEmacs. @@ -374,7 +374,7 @@ else if (ht->test_function == lisp_object_eql_equal) DO_NOTHING; else - abort (); + ABORT (); if (ht->count || !print_readably) { @@ -402,9 +402,7 @@ if (print_readably) write_c_string (printcharfun, ")"); else - { - write_fmt_string (printcharfun, " 0x%x>", ht->header.uid); - } + write_fmt_string (printcharfun, " 0x%x>", ht->header.uid); } static void @@ -453,9 +451,9 @@ static const struct memory_description htentry_union_description_1[] = { /* Note: XD_INDIRECT in this table refers to the surrounding table, and so this will work. */ - { XD_STRUCT_PTR, HASH_TABLE_NON_WEAK, XD_INDIRECT (0, 1), - &htentry_description }, - { XD_STRUCT_PTR, 0, XD_INDIRECT (0, 1), &htentry_description, + { XD_BLOCK_PTR, HASH_TABLE_NON_WEAK, XD_INDIRECT (0, 1), + { &htentry_description } }, + { XD_BLOCK_PTR, 0, XD_INDIRECT (0, 1), { &htentry_description }, XD_FLAG_UNION_DEFAULT_ENTRY | XD_FLAG_NO_KKCC }, { XD_END } }; @@ -469,7 +467,7 @@ { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) }, { XD_INT, offsetof (Lisp_Hash_Table, weakness) }, { XD_UNION, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (1, 0), - &htentry_union_description }, + { &htentry_union_description } }, { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, { XD_END } }; @@ -535,7 +533,7 @@ break; default: - abort (); + ABORT (); } return make_general_lisp_hash_table (hash_function, test_function, @@ -790,12 +788,8 @@ Lisp_Object weakness = Qnil; Lisp_Object data = Qnil; - while (!NILP (plist)) + PROPERTY_LIST_LOOP_3 (key, value, plist) { - Lisp_Object key, value; - key = XCAR (plist); plist = XCDR (plist); - value = XCAR (plist); plist = XCDR (plist); - if (EQ (key, Qtest)) test = value; else if (EQ (key, Qsize)) size = value; else if (EQ (key, Qrehash_size)) rehash_size = value; @@ -804,7 +798,7 @@ else if (EQ (key, Qdata)) data = value; else if (EQ (key, Qtype))/*obsolete*/ weakness = value; else - abort (); + ABORT (); } /* Create the hash table. */ @@ -1065,6 +1059,35 @@ return probe; } +/* A version of Fputhash() that increments the value by the specified + amount and dispenses will all error checks. Assumes that tables does + comparison using EQ. Used by the profiling routines to avoid + overhead -- profiling overhead was being recorded at up to 15% of the + total time. */ + +void +inchash_eq (Lisp_Object key, Lisp_Object table, EMACS_INT offset) +{ + Lisp_Hash_Table *ht = XHASH_TABLE (table); + htentry *entries = ht->hentries; + htentry *probe = entries + HASHCODE (key, ht); + + LINEAR_PROBING_LOOP (probe, entries, ht->size) + if (EQ (probe->key, key)) + break; + + if (!HTENTRY_CLEAR_P (probe)) + probe->value = make_int (XINT (probe->value) + offset); + else + { + probe->key = key; + probe->value = make_int (offset); + + if (++ht->count >= ht->rehash_count) + enlarge_hash_table (ht); + } +} + DEFUN ("gethash", Fgethash, 2, 3, 0, /* Find hash value for KEY in HASH-TABLE. If there is no corresponding value, return DEFAULT (which defaults to nil). diff --text -u 'xemacs-21.5.18/src/elhash.h' 'xemacs-21.5.19/src/elhash.h' Index: ./src/elhash.h --- ./src/elhash.h Sun Jan 12 20:08:12 2003 +++ ./src/elhash.h Wed Jan 26 19:22:25 2005 @@ -62,7 +62,7 @@ EXFUN (Fclrhash, 1); typedef int (*hash_table_test_function_t) (Lisp_Object obj1, Lisp_Object obj2); -typedef unsigned long (*hash_table_hash_function_t) (Lisp_Object obj); +typedef Hashcode (*hash_table_hash_function_t) (Lisp_Object obj); typedef int (*maphash_function_t) (Lisp_Object key, Lisp_Object value, void* extra_arg); @@ -97,4 +97,6 @@ void pdump_reorganize_hash_table (Lisp_Object); +void inchash_eq (Lisp_Object key, Lisp_Object table, EMACS_INT offset); + #endif /* INCLUDED_elhash_h_ */ diff --text -u 'xemacs-21.5.18/src/emacs-marshals.c' 'xemacs-21.5.19/src/emacs-marshals.c' Index: ./src/emacs-marshals.c --- ./src/emacs-marshals.c Sun May 2 13:06:58 2004 +++ ./src/emacs-marshals.c Wed Jan 26 19:22:25 2005 @@ -1466,35 +1466,6 @@ #include "hash.h" -static int -our_string_eq (const void *st1, const void *st2) -{ - if (!st1) - return st2 ? 0 : 1; - else if (!st2) - return 0; - else - return !strcmp ( (const char *) st1, (const char *) st2); -} - -static unsigned long -our_string_hash (const void *xv) -{ - unsigned int h = 0; - unsigned const char *x = (unsigned const char *) xv; - - if (!x) return 0; - - while (*x) - { - unsigned int g; - h = (h << 4) + *x++; - if ((g = h & 0xf0000000) != 0) - h = (h ^ (g >> 24)) ^ g; - } - - return h; -} static struct hash_table *marshaller_hashtable; @@ -1502,7 +1473,7 @@ { if (!marshaller_hashtable) { - marshaller_hashtable = make_general_hash_table (100, our_string_hash, our_string_eq); + marshaller_hashtable = make_string_hash_table (100); puthash ("emacs_gtk_marshal_BOOL__OBJECT_INT", (void *) emacs_gtk_marshal_BOOL__OBJECT_INT, marshaller_hashtable); puthash ("emacs_gtk_marshal_BOOL__OBJECT_OBJECT_OBJECT", (void *) emacs_gtk_marshal_BOOL__OBJECT_OBJECT_OBJECT, marshaller_hashtable); puthash ("emacs_gtk_marshal_BOOL__OBJECT_OBJECT", (void *) emacs_gtk_marshal_BOOL__OBJECT_OBJECT, marshaller_hashtable); diff --text -u 'xemacs-21.5.18/src/emacs.c' 'xemacs-21.5.19/src/emacs.c' Index: ./src/emacs.c --- ./src/emacs.c Tue Sep 21 04:19:39 2004 +++ ./src/emacs.c Tue Feb 1 04:29:48 2005 @@ -2,7 +2,7 @@ Copyright (C) 1985, 1986, 1987, 1992, 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -23,6 +23,8 @@ /* Synched up with: Mule 2.0, FSF 19.28. */ +/* This file has been Mule-ized, Ben Wing, 10-7-04. */ + /* Capsule summary of the various releases of Lucid Emacs/XEmacs and FSF/GNU Emacs. (Copied from the Internals Manual, where the canonical version lives.) Provided here for use in cross-referencing @@ -34,103 +36,141 @@ -- A time line for Lucid Emacs/XEmacs is -version 19.0 shipped with Energize 1.0, April 1992. -version 19.1 released June 4, 1992. -version 19.2 released June 19, 1992. -version 19.3 released September 9, 1992. -version 19.4 released January 21, 1993. -version 19.5 was a repackaging of 19.4 with a few bug fixes and - shipped with Energize 2.0. Never released to the net. -version 19.6 released April 9, 1993. -version 19.7 was a repackaging of 19.6 with a few bug fixes and +Version 19.0 shipped with Energize 1.0, April 1992. +Version 19.1 released June 4, 1992. +Version 19.2 released June 19, 1992. +Version 19.3 released September 9, 1992. +Version 19.4 released January 21, 1993. +Version 19.5 released February 5, 1993. This was a repackaging of 19.4 with a + few bug fixes and shipped with Energize 2.0. It was a trade-show giveaway + and never released to the net. +Version 19.6 released April 9, 1993. +Version 19.7 was a repackaging of 19.6 with a few bug fixes and shipped with Energize 2.1. Never released to the net. -version 19.8 released September 6, 1993. -version 19.9 released January 12, 1994. -version 19.10 released May 27, 1994. -version 19.11 (first XEmacs) released September 13, 1994. -version 19.12 released June 23, 1995. -version 19.13 released September 1, 1995. -version 19.14 released June 23, 1996. -version 20.0 released February 9, 1997. -version 19.15 released March 28, 1997. -version 20.1 (not released to the net) April 15, 1997. -version 20.2 released May 16, 1997. -version 19.16 released October 31, 1997. -version 20.3 (the first stable version of XEmacs 20.x) released November 30, -1997. -version 20.4 released February 28, 1998. -version 21.0.60 released December 10, 1998. (The version naming scheme was -changed at this point: [a] the second version number is odd for stable -versions, even for beta versions; [b] a third version number is added, -replacing the "beta xxx" ending for beta versions and allowing for -periodic maintenance releases for stable versions. Therefore, 21.0 was -never "officially" released; similarly for 21.2, etc.) -version 21.0.61 released January 4, 1999. -version 21.0.63 released February 3, 1999. -version 21.0.64 released March 1, 1999. -version 21.0.65 released March 5, 1999. -version 21.0.66 released March 12, 1999. -version 21.0.67 released March 25, 1999. -version 21.1.2 released May 14, 1999; on comp.emacs, May 28. (This is +Version 19.8 released September 6, 1993. (Epoch merger, preliminary I18N + support) +Version 19.9 released January 12, 1994. (Scrollbars, Athena.) +Version 19.10 released May 27, 1994. Known as "Lucid Emacs" when + shipped by Lucid, and as "XEmacs" when shipped by Sun; but Lucid + went out of business a few days later and it's unclear very many + copies of 19.10 were released by Lucid. (Last release by Jamie Zawinski.) +Version 19.11 (first XEmacs) released September 13, 1994. +Version 19.12 released June 23, 1995. +Version 19.13 released September 1, 1995. +Version 19.14 released June 23, 1996. +Version 20.0 released February 9, 1997. +Version 19.15 released March 28, 1997. +Version 20.1 (not released to the net) April 15, 1997. +Version 20.2 released May 16, 1997. +Version 19.16 released October 31, 1997; retiring of v19 series. +Version 20.3 (the first stable version of XEmacs 20.x) released November 30, + 1997. +Version 20.4 released February 28, 1998. (Jamie claims this version is the + "first reasonably stable release with MULE support" and says that "XEmacs + 'core' and 'packages' now packaged separately.") +Version 21.0-pre5 released July 18, 1998. (Jamie says "Numbering scheme goes + wonky due to switch to stable + unstable branches.") +Version 21.0.60 released December 10, 1998. (The version naming scheme was + changed at this point: [a] the second version number is odd for stable + versions, even for beta versions; [b] a third version number is added, + replacing the "beta xxx" ending for beta versions and allowing for + periodic maintenance releases for stable versions. Therefore, 21.0 was + never "officially" released; similarly for 21.2, etc.) +Version 21.0.61 released January 4, 1999. +Version 21.0.63 released February 3, 1999. +Version 21.0.64 released March 1, 1999. +Version 21.0.65 released March 5, 1999. +Version 21.0.66 released March 12, 1999. +Version 21.0.67 released March 25, 1999. +Version 21.1.2 released May 14, 1999; on comp.emacs, May 28. (This is the followup to 21.0.67. The second version number was bumped to indicate the beginning of the "stable" series.) -version 21.1.3 released June 26, 1999. -version 21.1.4 released July 8, 1999. -version 21.1.6 released August 14, 1999. (There was no 21.1.5.) -version 21.1.7 released September 26, 1999. -version 21.1.8 released November 2, 1999. -version 21.1.9 released February 13, 2000. -version 21.1.10 released May 7, 2000. -version 21.1.10a released June 24, 2000. -version 21.1.11 released July 18, 2000. -version 21.1.12 released August 5, 2000. -version 21.1.13 released January 7, 2001. -version 21.1.14 released January 27, 2001. -version 21.2.9 released February 3, 1999. -version 21.2.10 released February 5, 1999. -version 21.2.11 released March 1, 1999. -version 21.2.12 released March 5, 1999. -version 21.2.13 released March 12, 1999. -version 21.2.14 released May 14, 1999. -version 21.2.15 released June 4, 1999. -version 21.2.16 released June 11, 1999. -version 21.2.17 released June 22, 1999. -version 21.2.18 released July 14, 1999. -version 21.2.19 released July 30, 1999. -version 21.2.20 released November 10, 1999. -version 21.2.21 released November 28, 1999. -version 21.2.22 released November 29, 1999. -version 21.2.23 released December 7, 1999. -version 21.2.24 released December 14, 1999. -version 21.2.25 released December 24, 1999. -version 21.2.26 released December 31, 1999. -version 21.2.27 released January 18, 2000. -version 21.2.28 released February 7, 2000. -version 21.2.29 released February 16, 2000. -version 21.2.30 released February 21, 2000. -version 21.2.31 released February 23, 2000. -version 21.2.32 released March 20, 2000. -version 21.2.33 released May 1, 2000. -version 21.2.34 released May 28, 2000. -version 21.2.35 released July 19, 2000. -version 21.2.36 released October 4, 2000. -version 21.2.37 released November 14, 2000. -version 21.2.38 released December 5, 2000. -version 21.2.39 released December 31, 2000. -version 21.2.40 released January 8, 2001. -version 21.2.41 "Polyhymnia" released January 17, 2001. -version 21.2.42 "Poseidon" released January 20, 2001. -version 21.2.43 "Terspichore" released January 26, 2001. -version 21.2.44 "Thalia" released February 8, 2001. -version 21.2.45 "Thelxepeia" released February 23, 2001. -version 21.2.46 "Urania" released March 21, 2001. -version 21.5.0 "alfalfa" released April 18, 2001. -version 21.5.1 "anise" released May 9, 2001. -version 21.5.2 "artichoke" released July 28, 2001. -version 21.5.3 "asparagus" released September 7, 2001. -version 21.5.4 "bamboo" released January 8, 2002. -version 21.5.5 "beets" released March 5, 2002. -version 21.5.6 "bok choi" released April 5, 2002. +Version 21.1.3 released June 26, 1999. +Version 21.1.4 released July 8, 1999. +Version 21.1.6 released August 14, 1999. (There was no 21.1.5.) +Version 21.1.7 released September 26, 1999. +Version 21.1.8 released November 2, 1999. +Version 21.1.9 released February 13, 2000. +Version 21.1.10 released May 7, 2000. +Version 21.1.10a released June 24, 2000. +Version 21.1.11 released July 18, 2000. +Version 21.1.12 released August 5, 2000. +Version 21.1.13 released January 7, 2001. +Version 21.1.14 released January 27, 2001. +Version 21.2.9 released February 3, 1999. +Version 21.2.10 released February 5, 1999. +Version 21.2.11 released March 1, 1999. +Version 21.2.12 released March 5, 1999. +Version 21.2.13 released March 12, 1999. +Version 21.2.14 released May 14, 1999. +Version 21.2.15 released June 4, 1999. +Version 21.2.16 released June 11, 1999. +Version 21.2.17 released June 22, 1999. +Version 21.2.18 released July 14, 1999. +Version 21.2.19 released July 30, 1999. +Version 21.2.20 released November 10, 1999. +Version 21.2.21 released November 28, 1999. +Version 21.2.22 released November 29, 1999. +Version 21.2.23 released December 7, 1999. +Version 21.2.24 released December 14, 1999. +Version 21.2.25 released December 24, 1999. +Version 21.2.26 released December 31, 1999. +Version 21.2.27 released January 18, 2000. +Version 21.2.28 released February 7, 2000. +Version 21.2.29 released February 16, 2000. +Version 21.2.30 released February 21, 2000. +Version 21.2.31 released February 23, 2000. +Version 21.2.32 released March 20, 2000. +Version 21.2.33 released May 1, 2000. +Version 21.2.34 released May 28, 2000. +Version 21.2.35 released July 19, 2000. +Version 21.2.36 released October 4, 2000. +Version 21.2.37 released November 14, 2000. +Version 21.2.38 released December 5, 2000. +Version 21.2.39 released December 31, 2000. +Version 21.2.40 released January 8, 2001. +Version 21.2.41 "Polyhymnia" released January 17, 2001. +Version 21.2.42 "Poseidon" released January 20, 2001. +Version 21.2.43 "Terspichore" released January 26, 2001. +Version 21.2.44 "Thalia" released February 8, 2001. +Version 21.2.45 "Thelxepeia" released February 23, 2001. +Version 21.2.46 "Urania" released March 21, 2001. +Version 21.2.47 "Zephir" released April 14, 2001. +Version 21.4.0 "Solid Vapor" released April 16, 2001. +Version 21.4.1 "Copyleft" released April 19, 2001. +Version 21.4.2 "Developer-Friendly Unix APIs" released May 10, 2001. +Version 21.4.3 "Academic Rigor" released May 17, 2001. +Version 21.4.4 "Artificial Intelligence" released July 28, 2001. +Version 21.4.5 "Civil Service" released October 23, 2001. +Version 21.4.6 "Common Lisp" released December 17, 2001. +Version 21.4.7 "Economic Science" released May 4, 2002. +Version 21.4.8 "Honest Recruiter" released May 9, 2002. +Version 21.4.9 "Informed Management" released August 23, 2002. +Version 21.4.10 "Military Intelligence" released November 2, 2002. +Version 21.4.11 "Native Windows TTY Support" released January 3, 2003. +Version 21.4.12 "Portable Code" released January 15, 2003. +Version 21.4.13 "Rational FORTRAN" released May 25, 2003. +Version 21.4.14 "Reasonable Discussion" released September 3, 2003. +Version 21.4.15 "Security Through Obscurity" released February 2, 2004. +Version 21.5.0 "alfalfa" released April 18, 2001. +Version 21.5.1 "anise" released May 9, 2001. +Version 21.5.2 "artichoke" released July 28, 2001. +Version 21.5.3 "asparagus" released September 7, 2001. +Version 21.5.4 "bamboo" released January 8, 2002. +Version 21.5.5 "beets" released March 5, 2002. +Version 21.5.6 "bok choi" released April 5, 2002. +Version 21.5.7 "broccoflower" released July 2, 2002. +Version 21.5.8 "broccoli" released July 27, 2002. +Version 21.5.9 "brussels sprouts" released August 30, 2002. +Version 21.5.10 "burdock" released January 4, 2003. +Version 21.5.11 "cabbage" released February 16, 2003. +Version 21.5.12 "carrot" released April 24, 2003. +Version 21.5.13 "cauliflower" released May 10, 2003. +Version 21.5.14 "cassava" released June 1, 2003. +Version 21.5.15 "celery" released September 3, 2003. +Version 21.5.16 "celeriac" released September 26, 2003. +Version 21.5.17 "chayote" released March 22, 2004. +Version 21.5.18 "chestnut" released October 22, 2004. -- A time line for GNU Emacs version 19 is @@ -173,6 +213,8 @@ version 20.3 released August 19, 1998. version 20.4 released July 12, 1999; on comp.emacs, July 27. version 21.1 released October 20, 2001. +Version 21.2 released March 16, 2002. +Version 21.3 released March 19, 2003. -- A time line for GNU Emacs version 18 and older is @@ -232,8 +274,150 @@ version 18.58 released ?????. version 18.59 released October 31, 1992. + +-- A time line for Epoch is + +Epoch 1.0 released December 14, 1989. (by Simon Kaplan, Chris Love, et al.) +Epoch 2.0 released December 23, 1989. +Epoch 3.1 released February 6, 1990. +Epoch 3.2 released December[????] 11, 1990. +Epoch 4.0 released August 27, 1990. + */ +/* Sources for further information: + +----------------------------------- +1. Using XEmacs, Programming Elisp: +----------------------------------- + +;;; -- the XEmacs User's Manual (Access using the online Info browser: +;;; Use `Help->Info (Online Docs)->XEmacs User's Manual' (if +;;; there is such an entry); or get to the Info contents page +;;; using `Help->Info Contents' or `C-h i', and then +;;; *middle-click* the XEmacs link or move the cursor into the +;;; link and hit ENTER. This manual contains a great deal of +;;; documentation on customization: Scroll down to the +;;; Customization link and select it in the same fashion as for +;;; the XEmacs link just mentioned.) + +;;; -- the XEmacs FAQ (`C-h F' for the local version; get either the +;;; local version or the very latest version off the net using +;;; the Help menu) + +;;; -- the XEmacs Lisp Reference Manual, containing detailed +;;; documentation on Elisp. (Access using Info, just like for the +;;; XEmacs User's Manual.) + +;;; -- the documentation strings for specific commands, functions, +;;; key sequences, and variables. NOTE: This is *not* the same +;;; information as in the XEmacs User's Manual or XEmacs Lisp +;;; Reference Manual! In general, the doc strings are more +;;; terse and more up-to-date than what is found in the manuals. +;;; Once you understand the general concepts, these doc strings +;;; should be your first point of reference for further +;;; info. (Access using menu entries under `Help->Commands, +;;; Variables, Keys' or using the keyboard: `C-h k' for a key +;;; sequence, `C-h f' for a named command or Elisp function, +;;; `C-h v' for a variable. There is various other useful +;;; information accessible similarly, such as `C-h a' +;;; ["Apropos", i.e. search for a command, function, or variable +;;; by name]; `C-h C-a' ["Apropos Docs", i.e. search through the +;;; text of the doc strings]; `C-h b' to list all key bindings; +;;; `C-h m' to describe the current major and minor modes; etc. +;;; Type `C-h ? ?' for a complete list.) + +;;; -- Getting Started with XEmacs [aka the "New User's Guide"], a +;;; more introductory manual than the XEmacs User's Manual. +;;; (Access using Info, just like for the XEmacs User's Manual. +;;; There are some sections on customization here.) + +;;; -- the XEmacs tutorial, a very simple introduction to XEmacs for +;;; total beginners. (`C-h t' for English; get the version in +;;; various languages from the Help menu) + +;;; -- the XEmacs web site, www.xemacs.org. + +;;; -- the XEmacs mailing lists (xemacs-FOO@xemacs.org; +;;; see http://www.xemacs.org/Lists/ for more info. Before +;;; posting, consider looking through the archives -- they go back +;;; years and there is a powerful searching interface. Currently +;;; the archives are at http://list-archive.xemacs.org/, but if +;;; this doesn't work, you can always access them through +;;; www.xemacs.org.) + +;;; -- the XEmacs newsgroup, comp.emacs.xemacs. This is +;;; bi-directionally gatewayed with xemacs@xemacs.org. WARNING: +;;; The developers do not normally hang out on this newsgroup. If +;;; you need to contact them, use xemacs-beta@xemacs.org. + +;;; -- the XEmacs internals manual, for those interested in working on +;;; the XEmacs C code. (Available through Info.) + +;;; -- `Help->About XEmacs' to find out who the maintainers are. + +--------------------- +2. Developing XEmacs: +--------------------- + +-- the internals manual, man/internals/internals.texi + +-- long comments at the head of certain files: + + emacs.c + extents.c + text.c + text.h + lisp.h + redisplay.h + dynarr.c + blocktype.c + eval.c + event-Xt.c (sort of) + event-stream.c (command event queue) + frame.c + intl-encap-win32.c + keymap.c + line-number.c (a little bit) + menubar-msw.c (sort of) + menubar-x.c (sort of) + mule-canna.c (sort of) + mule-ccl.c + mule-coding.c (scattered in the file) + mule-wnn.c (in japanese) + ntheap.c (near the top) + redisplay.c (various scattered) + regex.c (various scattered) + sysdep.c (maybe; wait_for_termination) + unexec.c + unicode.c + xgccache.c (a bit) + + #### review .h files; write a perl program to look for long comments + throughout the files, ignoring stuff inside of DEFUN's. + + #### elsewhere? + +-- comments scattered throughout the sources (#### should be grouped + together if feasible). For example, lrecord.h (pdump and object- + creation), alloc.c (fixed-type allocation), etc. #### fill in. + +-- Ben's Architecting XEmacs web site. + (http://www.xemacs.org/Architecting-XEmacs/index.html; #### should be + integrated into the sources) + +-- Back discussions on xemacs-beta (#### The juiciest tidbits, esp. + those with specific proposals, should be extracted and stuck in + the source) + +-- README.* in the src/ directory (and maybe other directories) + +-- The ChangeLog files, sometimes. + +*/ + + + /* Note: It is necessary to specify <config.h> and not "config.h" in order for the --srcdir type of compilation to work properly. Otherwise the config.h from the srcdir, rather than the one from @@ -383,7 +567,7 @@ /* Type of display specified. We cannot use a Lisp symbol here because Lisp symbols may not initialized at the time that we set this variable. */ -const Char_ASCII *display_use; +const Ascbyte *display_use; /* If non-zero, then the early error handler will only print the error message and exit. */ @@ -391,7 +575,7 @@ /* An address near the bottom of the stack. Tells GC how to save a copy of the stack. */ -char *stack_bottom; +Rawbyte *stack_bottom; #ifdef USG_SHARED_LIBRARIES /* If nonzero, this is the place to put the end of the writable segment @@ -462,10 +646,10 @@ int debug_paths; /* Save argv and argc. */ -static Extbyte **initial_argv; /* #### currently unused */ +static Wexttext **initial_argv; /* #### currently unused */ static int initial_argc; /* #### currently unused */ -static void sort_args (int argc, char **argv); +static void sort_args (int argc, Wexttext **argv); Lisp_Object Qkill_emacs_hook; Lisp_Object Qsave_buffers_kill_emacs; @@ -480,16 +664,14 @@ int preparing_for_armageddon; /* Nonzero means we're in an unstable situation and need to skip - i18n conversions and such during printing. */ -int inhibit_non_essential_printing_operations; + i18n conversions and such. During printing we check for this, + and during conversion we abort if we see this. */ +int inhibit_non_essential_conversion_operations; static JMP_BUF run_temacs_catch; static int run_temacs_argc; -static Extbyte **run_temacs_argv; -static Extbyte *run_temacs_args; -static int run_temacs_argv_size; -static int run_temacs_args_size; +static Wexttext **run_temacs_argv; #ifdef _MSC_VER static DWORD mswindows_handle_hardware_exceptions (DWORD code); @@ -507,7 +689,7 @@ /* Code for dealing with Lisp access to the Unix command line */ static Lisp_Object -make_arg_list_1 (int argc, Extbyte **argv, int skip_args) +make_arg_list_1 (int argc, Wexttext **argv, int skip_args) { Lisp_Object result = Qnil; REGISTER int i; @@ -531,8 +713,8 @@ } else #endif - result = Fcons (build_ext_string (argv[i], - Qcommand_argument_encoding), + result = Fcons (build_wext_string (argv[i], + Qcommand_argument_encoding), result); } } @@ -540,7 +722,7 @@ } Lisp_Object -make_arg_list (int argc, Extbyte **argv) +make_arg_list (int argc, Wexttext **argv) { return make_arg_list_1 (argc, argv, 0); } @@ -548,40 +730,39 @@ /* Calling functions are also responsible for calling free_argc_argv when they are done with the generated list. */ void -make_argc_argv (Lisp_Object argv_list, int *argc, Extbyte ***argv) +make_argc_argv (Lisp_Object argv_list, int *argc, Wexttext ***argv) { Lisp_Object next; int n = XINT (Flength (argv_list)); REGISTER int i; - *argv = (Extbyte**) xmalloc ((n+1) * sizeof (Extbyte*)); + *argv = xnew_array (Wexttext *, n + 1); for (i = 0, next = argv_list; i < n; i++, next = XCDR (next)) { - const Extbyte *temp; CHECK_STRING (XCAR (next)); - LISP_STRING_TO_EXTERNAL (XCAR (next), temp, Qcommand_argument_encoding); - (*argv) [i] = xstrdup (temp); + LISP_STRING_TO_EXTERNAL_MALLOC (XCAR (next), (*argv) [i], + Qcommand_argument_encoding); } (*argv) [n] = 0; *argc = i; } void -free_argc_argv (Extbyte **argv) +free_argc_argv (Wexttext **argv) { int elt = 0; while (argv[elt]) { - xfree (argv[elt], Extbyte *); + xfree (argv[elt], Wexttext *); elt++; } - xfree (argv, Extbyte **); + xfree (argv, Wexttext **); } static void -init_cmdargs (int argc, Extbyte **argv, int skip_args) +init_cmdargs (int argc, Wexttext **argv, int skip_args) { initial_argv = argv; initial_argc = argc; @@ -619,12 +800,12 @@ enough information to do it right. */ static int -argmatch (char **argv, int argc, char *sstr, char *lstr, - int minlen, char **valptr, int *skipptr) +argmatch (Wexttext **argv, int argc, Ascbyte *sstr, Ascbyte *lstr, + int minlen, Wexttext **valptr, int *skipptr) { - char *p = NULL; - int arglen; - char *arg; + Wexttext *p = NULL; + Charcount arglen; + Wexttext *arg; /* Don't access argv[argc]; give up in advance. */ if (argc <= *skipptr + 1) @@ -633,7 +814,7 @@ arg = argv[*skipptr+1]; if (arg == NULL) return 0; - if (strcmp (arg, sstr) == 0) + if (wext_strcmp_ascii (arg, sstr) == 0) { if (valptr != NULL) { @@ -644,11 +825,12 @@ *skipptr += 1; return 1; } - arglen = (valptr != NULL && (p = strchr (arg, '=')) != NULL - ? p - arg : (int) strlen (arg)); + arglen = (valptr != NULL && (p = wext_strchr (arg, '=')) != NULL + ? p - arg : (Charcount) wext_strlen (arg)); if (lstr && !minlen) minlen = strlen (lstr); - if (lstr == 0 || arglen < minlen || strncmp (arg, lstr, arglen) != 0) + if (lstr == 0 || arglen < minlen || + wext_strncmp_ascii (arg, lstr, arglen) != 0) return 0; else if (valptr == NULL) { @@ -657,13 +839,13 @@ } else if (p != NULL) { - *valptr = p+1; + *valptr = p + 1; *skipptr += 1; return 1; } - else if (argv[*skipptr+2] != NULL) + else if (argv[*skipptr + 2] != NULL) { - *valptr = argv[*skipptr+2]; + *valptr = argv[*skipptr + 2]; *skipptr += 2; return 1; } @@ -674,7 +856,7 @@ } static void -check_compatible_window_system (char *must) +check_compatible_window_system (Ascbyte *must) { if (display_use && strcmp (display_use, must)) fatal ("Incompatible window system type `%s': `%s' already specified", @@ -700,33 +882,17 @@ the conventional dumper or `xemacs -nd' with the pdumper). See Frun_emacs_from_temacs(). */ -DECLARE_DOESNT_RETURN (main_1 (int, Extbyte **, Extbyte **, int)); +DECLARE_DOESNT_RETURN (main_1 (int, Wexttext **, Wexttext **, int)); DOESNT_RETURN -main_1 (int argc, Extbyte **argv, -#if defined (WIN32_NATIVE) || defined (_SCO_DS) - Extbyte **envp, -#else - Extbyte **UNUSED (envp), -#endif - int restart) +main_1 (int argc, Wexttext **argv, Wexttext **UNUSED (envp), int restart) { - char stack_bottom_variable; + Rawbyte stack_bottom_variable; int skip_args = 0; Lisp_Object load_me; #ifdef NeXT extern int malloc_cookie; #endif - /* !!#### Under MS Windows, this should all be rewritten to deal with - Unicode arguments and environment. We need to retrieve the command - line with GetCommandLine and convert to argv format with - CommandLineToArgvW. Unfortunately we have a bootstrapping problem - currently because we can't initialize the Unicode tables until we've - computed the location of data-directory, which doesn't happen till - startup.el, which is way late. We need to be dumping the Unicode - data, which means we need to fix pdump to correctly dump the "union" - format used by the tables. */ - #if (!defined (SYSTEM_MALLOC) && !defined (HAVE_LIBMCHECK) \ && !defined (DOUG_LEA_MALLOC)) /* Make sure that any libraries we link against haven't installed a @@ -740,7 +906,7 @@ noninteractive = 0; display_use = 0; - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; #ifdef NeXT /* 19-Jun-1995 -baw @@ -770,7 +936,9 @@ sort_args (argc, argv); -#if defined (WIN32_NATIVE) || defined (_SCO_DS) +#if 0 /* defined (_SCO_DS) + #### Turn this off, we already have another SCO_DS hack in main(). + */ environ = envp; #endif @@ -834,8 +1002,8 @@ alignment and max size of the inline data and quit */ if (argmatch (argv, argc, "-si", "--show-inline-info", 0, NULL, &skip_args)) { -#if defined(PDUMP) && !defined(WIN32_NATIVE) - printf ("%u %u\n", dumped_data_max_size(), dumped_data_align_offset()); +#if defined (PDUMP) && !defined (WIN32_NATIVE) + printf ("%u %u\n", dumped_data_max_size (), dumped_data_align_offset ()); #else printf ("Portable dumper not configured or windows native; -si just forces exit.\n"); #endif @@ -869,11 +1037,11 @@ makes (e.g.) the "Stop Build" command from VC++ correctly terminate XEmacs. */ - char *heventstr; + Wexttext *heventstr; if (argmatch (argv, argc, "-mswindows-termination-handle", 0, 0, &heventstr, &skip_args)) { - HANDLE hevent = (HANDLE) atol (heventstr); + HANDLE hevent = (HANDLE) wext_atol (heventstr); DWORD unused; HANDLE h_thread = CreateThread (NULL, 0, wait_for_termination_signal, (void *) hevent, 0, &unused); @@ -982,9 +1150,11 @@ /* Handle the -t switch, which specifies filename to use as terminal */ { - Extbyte *term; + Wexttext *term; if (argmatch (argv, argc, "-t", "--terminal", 0, &term, &skip_args)) { + int fd; + check_compatible_window_system ("tty"); #ifndef HAVE_TTY fatal ("Sorry, this XEmacs was not compiled with TTY support"); @@ -992,16 +1162,20 @@ retry_close (0); retry_close (1); - if (open (term, O_RDWR | OPEN_BINARY, 2) < 0) - fatal ("%s: %s", term, strerror (errno)); + + fd = wext_retry_open (term, O_RDWR | OPEN_BINARY, 2); + /* Conversions are not possible yet, and printing will be in + external format, so strerror() and ttyname() are OK. */ + if (fd < 0) + fatal ("%s: %s", WEXTTEXT_TO_8_BIT (term), strerror (errno)); dup (0); if (! isatty (0)) - fatal ("%s: not a tty", term); + fatal ("%s: not a tty", WEXTTEXT_TO_8_BIT (term)); #if 0 stderr_out ("Using %s", ttyname (0)); #endif - stderr_out ("Using %s", term); + stderr_out ("Using %s", WEXTTEXT_TO_8_BIT (term)); } } @@ -1011,7 +1185,7 @@ to run until we've recognized this argument. */ { #ifdef HAVE_X_WINDOWS - char *dpy = 0; + Wexttext *dpy = 0; int count_before = skip_args; if (argmatch (argv, argc, "-d", "--display", 3, &dpy, &skip_args) || @@ -1025,12 +1199,12 @@ This requires inserting a new element into argv. */ if (dpy != 0 && skip_args - count_before == 1) { - char **new = (char **) xmalloc (sizeof (char *) * (argc + 2)); + Wexttext **new = xnew_array (Wexttext *, argc + 2); int j; for (j = 0; j < count_before + 1; j++) new[j] = argv[j]; - new[count_before + 1] = "-d"; + new[count_before + 1] = WEXTSTRING ("-d"); new[count_before + 2] = dpy; for (j = count_before + 2; j <argc; j++) new[j + 1] = argv[j]; @@ -1040,7 +1214,7 @@ /* Change --display to -d, when its arg is separate. */ else if (dpy != 0 && skip_args > count_before && argv[count_before + 1][1] == '-') - argv[count_before + 1] = "-d"; + argv[count_before + 1] = WEXTSTRING ("-d"); /* Don't actually discard this arg. */ skip_args = count_before; @@ -1053,11 +1227,11 @@ #if defined (HAVE_X_WINDOWS) || defined (HAVE_GTK) if (!display_use) { - char *dpy; + Wexttext *dpy; /* If there is a non-empty environment var DISPLAY, assume X or GTK, but don't set `display_arg', which is only to be set if the display was specified on the command line. */ - if ((dpy = getenv ("DISPLAY")) && dpy[0]) + if ((dpy = wext_getenv (WEXTSTRING ("DISPLAY"))) && dpy[0]) #ifdef HAVE_X_WINDOWS /* #### Who gets precedence? X or GTK? For the moment, GTK support is unstable so use X. Maybe eventually we will switch this. */ @@ -1126,11 +1300,8 @@ As early as possible, of course, so we can be fairly accurate. */ -#ifdef WIN32_ANY - init_win32_very_early (); -#endif #ifdef HAVE_MS_WINDOWS - /* Depends on XEUNICODE_P, only accurate after the previous call */ + /* Depends on XEUNICODE_P */ init_mswindows_dde_very_early (); /* DDE needs to be initialized early so that the client doesn't give up waiting. */ @@ -1201,7 +1372,7 @@ else purify_flag = 1; } -#else +#else /* not PDUMP */ if (!initialized) purify_flag = 1; #endif @@ -1626,22 +1797,6 @@ coding_system_type_create_mule_coding (); #endif - /* Now initialize the structure types and associated symbols. - Other than the first function below, the functions may - make exactly the following function/macro calls: - - define_structure_type() - define_structure_type_keyword() - - */ - - structure_type_create (); - - structure_type_create_chartab (); - structure_type_create_faces (); - structure_type_create_rangetab (); - structure_type_create_hash_table (); - /* Now initialize the image instantiator formats and associated symbols. Other than the first function below, the functions may make exactly the following function/macro calls: @@ -1668,6 +1823,71 @@ #ifdef HAVE_GTK image_instantiator_format_create_glyphs_gtk (); #endif + } +#ifdef PDUMP + else if (!restart) /* after successful pdump_load() + (note, we are inside ifdef PDUMP) */ + { + reinit_alloc_early (); + reinit_symbols_early (); + reinit_opaque_early (); + reinit_eistring_early (); + + reinit_console_type_create_stream (); +#ifdef HAVE_TTY + reinit_console_type_create_tty (); +#endif +#ifdef HAVE_X_WINDOWS + reinit_console_type_create_x (); + reinit_console_type_create_device_x (); +#endif +#ifdef HAVE_MS_WINDOWS + reinit_console_type_create_mswindows (); +#endif +#ifdef HAVE_GTK + reinit_console_type_create_gtk (); +#endif + + reinit_specifier_type_create (); + reinit_specifier_type_create_image (); + reinit_specifier_type_create_gutter (); + reinit_specifier_type_create_objects (); +#ifdef HAVE_TOOLBARS + reinit_specifier_type_create_toolbar (); +#endif + + reinit_coding_system_type_create (); + reinit_coding_system_type_create_unicode (); +#ifdef WIN32_ANY + reinit_coding_system_type_create_intl_win32 (); +#endif +#ifdef MULE + reinit_coding_system_type_create_mule_coding (); +#endif + } +#endif /* PDUMP */ + + if (!initialized +#ifdef PDUMP + || !restart +#endif + ) + { + /* Now initialize the structure types and associated symbols. + Other than the first function below, the functions may + make exactly the following function/macro calls: + + define_structure_type() + define_structure_type_keyword() + + */ + + structure_type_create (); + + structure_type_create_chartab (); + structure_type_create_faces (); + structure_type_create_rangetab (); + structure_type_create_hash_table (); /* Now initialize the lstream types and associated symbols. Other than the first function below, the functions may @@ -1694,7 +1914,10 @@ #ifdef HAVE_WIN32_PROCESSES process_type_create_nt (); #endif + } + if (!initialized) + { /* Now initialize most variables. These functions may do exactly the following: @@ -1744,6 +1967,8 @@ variables settable from the command line. See the comment above the call to pdump_load() in main_1(). This caveat should only apply to vars_of_emacs(). + + Order should not matter in these functions. */ /* Now allow Fprovide() statements to be made. */ @@ -1779,7 +2004,6 @@ vars_of_editfns (); vars_of_emacs (); vars_of_eval (); - init_eval_semi_early (); #ifdef HAVE_X_WINDOWS vars_of_event_Xt (); @@ -1861,6 +2085,7 @@ #if defined (HAVE_MMAP) && defined (REL_ALLOC) && !defined (DOUG_LEA_MALLOC) vars_of_ralloc (); #endif /* HAVE_MMAP && REL_ALLOC */ + vars_of_realpath (); vars_of_redisplay (); vars_of_regex (); #ifdef HAVE_SCROLLBARS @@ -1986,7 +2211,86 @@ #ifdef HAVE_GPM vars_of_gpmevent (); #endif + } + + if (!initialized +#ifdef PDUMP + || !restart +#endif + ) + { + /* Now do additional vars_of_*() initialization that happens both + at dump time and after pdump load. */ + reinit_vars_of_buffer (); + reinit_vars_of_console (); +#ifdef DEBUG_XEMACS + reinit_vars_of_debug (); +#endif + reinit_vars_of_device (); + reinit_vars_of_eval (); +#if defined (HAVE_TTY) && (defined (DEBUG_TTY_EVENT_STREAM) || !defined (HAVE_X_WINDOWS)) + reinit_vars_of_event_tty (); +#endif + reinit_vars_of_event_stream (); + reinit_vars_of_events (); + reinit_vars_of_extents (); + reinit_vars_of_file_coding (); + reinit_vars_of_fileio (); +#ifdef USE_C_FONT_LOCK + reinit_vars_of_font_lock (); +#endif /* USE_C_FONT_LOCK */ + reinit_vars_of_glyphs (); + reinit_vars_of_glyphs_widget (); + reinit_vars_of_insdel (); + reinit_vars_of_lread (); + reinit_vars_of_lstream (); + reinit_vars_of_minibuf (); +#ifdef HAVE_SHLIB + reinit_vars_of_module (); +#endif + reinit_vars_of_objects (); + reinit_vars_of_print (); + reinit_vars_of_search (); + reinit_vars_of_text (); + reinit_vars_of_undo (); + reinit_vars_of_window (); + +#ifdef HAVE_MS_WINDOWS + reinit_vars_of_event_mswindows (); + reinit_vars_of_frame_mswindows (); + reinit_vars_of_object_mswindows (); +#endif + +#ifdef HAVE_GTK + reinit_vars_of_event_gtk (); + reinit_vars_of_menubar_gtk (); +#endif + +#ifdef HAVE_X_WINDOWS + reinit_vars_of_device_x (); + reinit_vars_of_event_Xt (); +#ifdef HAVE_SCROLLBARS + reinit_vars_of_scrollbar_x (); +#endif +#ifdef HAVE_MENUBARS + reinit_vars_of_menubar_x (); +#endif + reinit_vars_of_select_x (); +#if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_X_DIALOGS) || defined (HAVE_TOOLBARS) + reinit_vars_of_gui_x (); +#endif +#endif /* HAVE_X_WINDOWS */ + +#ifdef MULE + reinit_vars_of_mule_coding (); +#endif +#if defined (MULE) && defined (HAVE_WNN) + reinit_vars_of_mule_wnn (); +#endif + } + if (!initialized) + { /* Now initialize any specifier variables. We do this later because it has some dependence on the vars initialized above. @@ -2035,6 +2339,13 @@ complex_vars_of_intl_win32 (); #endif + /* At this point we should be able to do conversion operations. + We have initialized things to the point that we can create Lisp + objects and we have defined the basic coding systems (in the + just-previous complex-vars calls). We will in fact do conversion + quite soon, e.g. in complex_vars_of_glyphs_x(). */ + inhibit_non_essential_conversion_operations = 0; + /* Depends on specifiers. */ complex_vars_of_faces (); @@ -2116,150 +2427,28 @@ } #endif } - -#ifdef PDUMP - if (initialized && !restart) /* after successful pdump_load() - (note, we are inside ifdef PDUMP) */ + else { - reinit_alloc_early (); - reinit_symbols_early (); - reinit_opaque_early (); - reinit_eistring_early (); - - reinit_console_type_create_stream (); -#ifdef HAVE_TTY - reinit_console_type_create_tty (); -#endif -#ifdef HAVE_X_WINDOWS - reinit_console_type_create_x (); - reinit_console_type_create_device_x (); -#endif -#ifdef HAVE_MS_WINDOWS - reinit_console_type_create_mswindows (); -#endif -#ifdef HAVE_GTK - reinit_console_type_create_gtk (); -#endif - - reinit_specifier_type_create (); - reinit_specifier_type_create_image (); - reinit_specifier_type_create_gutter (); - reinit_specifier_type_create_objects (); -#ifdef HAVE_TOOLBARS - reinit_specifier_type_create_toolbar (); -#endif - - structure_type_create (); - - reinit_coding_system_type_create (); - reinit_coding_system_type_create_unicode (); -#ifdef WIN32_ANY - reinit_coding_system_type_create_intl_win32 (); -#endif -#ifdef MULE - reinit_coding_system_type_create_mule_coding (); -#endif - - structure_type_create_chartab (); - structure_type_create_faces (); - structure_type_create_rangetab (); - structure_type_create_hash_table (); - - lstream_type_create (); - lstream_type_create_file_coding (); -#if defined (HAVE_MS_WINDOWS) && !defined (HAVE_MSG_SELECT) - lstream_type_create_mswindows_selectable (); -#endif -#ifdef HAVE_UNIX_PROCESSES - process_type_create_unix (); -#endif -#ifdef HAVE_WIN32_PROCESSES - process_type_create_nt (); -#endif - - reinit_vars_of_buffer (); - reinit_vars_of_console (); -#ifdef DEBUG_XEMACS - reinit_vars_of_debug (); -#endif - reinit_vars_of_device (); - reinit_vars_of_eval (); -#if defined (HAVE_TTY) && (defined (DEBUG_TTY_EVENT_STREAM) || !defined (HAVE_X_WINDOWS)) - reinit_vars_of_event_tty (); -#endif - reinit_vars_of_event_stream (); - reinit_vars_of_events (); - reinit_vars_of_extents (); - reinit_vars_of_file_coding (); - reinit_vars_of_fileio (); -#ifdef USE_C_FONT_LOCK - reinit_vars_of_font_lock (); -#endif /* USE_C_FONT_LOCK */ - reinit_vars_of_glyphs (); - reinit_vars_of_glyphs_widget (); - reinit_vars_of_insdel (); - reinit_vars_of_lread (); - reinit_vars_of_lstream (); - reinit_vars_of_minibuf (); -#ifdef HAVE_SHLIB - reinit_vars_of_module (); -#endif - reinit_vars_of_objects (); - reinit_vars_of_print (); - reinit_vars_of_search (); - reinit_vars_of_text (); - reinit_vars_of_undo (); - reinit_vars_of_unicode (); - reinit_vars_of_window (); - -#ifdef HAVE_MS_WINDOWS - reinit_vars_of_event_mswindows (); - reinit_vars_of_frame_mswindows (); - reinit_vars_of_object_mswindows (); -#endif - -#ifdef HAVE_GTK - reinit_vars_of_event_gtk (); - reinit_vars_of_menubar_gtk (); -#endif - -#ifdef HAVE_X_WINDOWS - reinit_vars_of_device_x (); - reinit_vars_of_event_Xt (); -#ifdef HAVE_SCROLLBARS - reinit_vars_of_scrollbar_x (); -#endif -#ifdef HAVE_MENUBARS - reinit_vars_of_menubar_x (); -#endif - reinit_vars_of_select_x (); -#if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_X_DIALOGS) || defined (HAVE_TOOLBARS) - reinit_vars_of_gui_x (); -#endif -#endif /* HAVE_X_WINDOWS */ + /* We are at the equivalent place where we reset this in the + non-initialized case. */ + inhibit_non_essential_conversion_operations = 0; -#ifdef MULE - reinit_vars_of_mule_coding (); -#endif -#if defined (MULE) && defined (HAVE_WNN) - reinit_vars_of_mule_wnn (); -#endif - - reinit_complex_vars_of_buffer_runtime_only (); - reinit_complex_vars_of_console_runtime_only (); - reinit_complex_vars_of_minibuf (); - } +#ifdef PDUMP + if (!restart) /* after successful pdump_load() + (note, we are inside ifdef PDUMP) */ + { + reinit_complex_vars_of_buffer_runtime_only (); + reinit_complex_vars_of_console_runtime_only (); + reinit_complex_vars_of_minibuf (); + } #endif /* PDUMP */ - - /* CONGRATULATIONS!!! We have successfully initialized the Lisp - engine. */ + } if (initialized) init_eval_semi_early (); -#ifdef MULE - init_mule_charset (); -#endif + /* CONGRATULATIONS!!! We have successfully initialized the Lisp + engine. */ /* Now do further initialization/setup of stuff that is not needed by the syms_of_() routines. This involves stuff that only is enabled in @@ -2267,7 +2456,11 @@ not needed until we start loading Lisp code (the reader). A lot of this stuff involves querying the current environment and needs to be done both at dump time and at run time. Some will be done - only at run time, by querying the `initialized' variable. */ + only at run time, by querying the `initialized' variable. + + The ordering of these functions is critical, especially the early ones, + where there is typically a dependency from each to the previous. + */ #ifdef WIN32_ANY init_intl_win32 (); /* Under Windows, determine whether we use Unicode @@ -2310,8 +2503,7 @@ #endif init_lread (); /* Set up the Lisp reader. */ - init_cmdargs (argc, (Extbyte **) argv, - skip_args); /* Create list Vcommand_line_args */ + init_cmdargs (argc, argv, skip_args); /* Create list Vcommand_line_args */ init_buffer_2 (); /* Set default directory of *scratch* buffer */ #ifdef WIN32_NATIVE @@ -2390,9 +2582,10 @@ if (!initialized) { /* Handle -l loadup-and-dump, args passed by Makefile. */ - if (argc > 2 + skip_args && !strcmp (argv[1 + skip_args], "-l")) - /* !!#### need to be Mule-translating this, but later */ - load_me = build_string (argv[2 + skip_args]); + if (argc > 2 + skip_args && + !wext_strcmp_ascii (argv[1 + skip_args], "-l")) + load_me = build_wext_string (argv[2 + skip_args], + Qcommand_argument_encoding); } #ifdef QUANTIFY @@ -2401,7 +2594,6 @@ #endif /* QUANTIFY */ initialized = 1; - inhibit_non_essential_printing_operations = 0; /* This never returns. */ initial_command_loop (load_me); @@ -2416,8 +2608,8 @@ struct standard_args { - const char *name; - const char *longname; + const Ascbyte *name; + const Ascbyte *longname; int priority; int nargs; }; @@ -2512,9 +2704,9 @@ If an option takes an argument, keep it and its argument together. */ static void -sort_args (int argc, char **argv) +sort_args (int argc, Wexttext **argv) { - char **new_argv = xnew_array (char *, argc); + Wexttext **new_argv = xnew_array (Wexttext *, argc); /* For each element of argv, the corresponding element of options is: 0 for an option that takes no arguments, @@ -2534,22 +2726,24 @@ options[from] = -1; priority[from] = 0; /* Pseudo options "--" and "run-temacs" indicate end of options */ - if (!strcmp (argv[from], "--") || - !strcmp (argv[from], "run-temacs")) + if (!wext_strcmp_ascii (argv[from], "--") || + !wext_strcmp_ascii (argv[from], "run-temacs")) end_of_options_p = 1; if (!end_of_options_p && argv[from][0] == '-') { - int match, thislen; - char *equals; + int match; + Charcount thislen; + Wexttext *equals; /* Look for a match with a known old-fashioned option. */ for (i = 0; i < countof (standard_args); i++) - if (!strcmp (argv[from], standard_args[i].name)) + if (!wext_strcmp_ascii (argv[from], standard_args[i].name)) { options[from] = standard_args[i].nargs; priority[from] = standard_args[i].priority; if (from + standard_args[i].nargs >= argc) - fatal ("Option `%s' requires an argument\n", argv[from]); + fatal ("Option `%s' requires an argument\n", + WEXTTEXT_TO_8_BIT (argv[from])); from += standard_args[i].nargs; goto done; } @@ -2560,15 +2754,16 @@ if (argv[from][1] == '-') { match = -1; - thislen = strlen (argv[from]); - equals = strchr (argv[from], '='); + thislen = wext_strlen (argv[from]); + equals = wext_strchr (argv[from], '='); if (equals != 0) thislen = equals - argv[from]; for (i = 0; i < countof (standard_args); i++) if (standard_args[i].longname - && !strncmp (argv[from], standard_args[i].longname, - thislen)) + && !wext_strncmp_ascii (argv[from], + standard_args[i].longname, + thislen)) { if (match == -1) match = i; @@ -2586,7 +2781,8 @@ if (equals != 0) options[from] = 0; if (from + options[from] >= argc) - fatal ("Option `%s' requires an argument\n", argv[from]); + fatal ("Option `%s' requires an argument\n", + WEXTTEXT_TO_8_BIT (argv[from])); from += options[from]; } } @@ -2616,7 +2812,7 @@ } if (best < 0) - abort (); + ABORT (); /* Copy the highest priority remaining option, with its args, to NEW_ARGV. */ @@ -2630,8 +2826,8 @@ argv[best + i + 1] = 0; } - memcpy (argv, new_argv, sizeof (char *) * argc); - xfree (new_argv, char **); + memcpy (argv, new_argv, sizeof (Wexttext *) * argc); + xfree (new_argv, Wexttext **); xfree (options, int *); xfree (priority, int *); } @@ -2704,54 +2900,32 @@ tools like Purify or tcov that get confused by XEmacs' dumping. */ (int nargs, Lisp_Object *args)) { - int ac; - const Extbyte *wampum; - int namesize; - int total_len; - Lisp_Object orig_invoc_name = Fcar (Vcommand_line_args); - const Extbyte **wampum_all = alloca_array (const Extbyte *, nargs); - int *wampum_all_len = alloca_array (int, nargs); + int i; assert (!gc_in_progress); if (run_temacs_argc < 0) - invalid_operation ("I've lost my temacs-hood.", Qunbound); + invalid_operation ("I've lost my temacs-hood", Qunbound); + + run_temacs_argc = nargs + 1; + run_temacs_argv = xnew_array (Wexttext *, nargs + 2); - /* Need to convert the orig_invoc_name and all of the arguments - to external format. */ + LISP_STRING_TO_EXTERNAL_MALLOC (Fcar (Vcommand_line_args), + run_temacs_argv[0], + Qcommand_argument_encoding); + for (i = 0; i < nargs; i++) + { + CHECK_STRING (args[i]); - TO_EXTERNAL_FORMAT (LISP_STRING, orig_invoc_name, - ALLOCA, (wampum, namesize), - Qnative); - namesize++; - - for (ac = 0, total_len = namesize; ac < nargs; ac++) - { - CHECK_STRING (args[ac]); - TO_EXTERNAL_FORMAT (LISP_STRING, args[ac], - ALLOCA, (wampum_all[ac], wampum_all_len[ac]), - Qnative); - wampum_all_len[ac]++; - total_len += wampum_all_len[ac]; - } - DO_REALLOC (run_temacs_args, run_temacs_args_size, total_len, char); - DO_REALLOC (run_temacs_argv, run_temacs_argv_size, nargs+2, char *); - - memcpy (run_temacs_args, wampum, namesize); - run_temacs_argv [0] = run_temacs_args; - for (ac = 0; ac < nargs; ac++) - { - memcpy (run_temacs_args + namesize, - wampum_all[ac], wampum_all_len[ac]); - run_temacs_argv [ac + 1] = run_temacs_args + namesize; - namesize += wampum_all_len[ac]; + LISP_STRING_TO_EXTERNAL_MALLOC (args[i], run_temacs_argv[i + 1], + Qcommand_argument_encoding); } - run_temacs_argv [nargs + 1] = 0; + run_temacs_argv[nargs + 1] = 0; + catchlist = NULL; /* Important! Otherwise free_cons() calls in condition_case_unwind() may lead to GC death. */ unbind_to (0); /* this closes loadup.el */ purify_flag = 0; - run_temacs_argc = nargs + 1; #if defined (HEAP_IN_DATA) && !defined (PDUMP) report_sheap_usage (0); #endif @@ -2767,7 +2941,7 @@ /* ARGSUSED */ int -main (int argc, char **argv, char **envp) +main (int argc, Extbyte **argv, Extbyte **UNUSED (envp)) { #ifdef _MSC_VER @@ -2780,8 +2954,7 @@ #endif int volatile vol_argc = argc; - char ** volatile vol_argv = argv; - char ** volatile vol_envp = envp; + Wexttext ** volatile vol_argv; /* This is hairy. We need to compute where the XEmacs binary was invoked from because temacs initialization requires it to find the lisp directories. The code that recomputes the path is guarded by the @@ -2815,7 +2988,7 @@ quantify_clear_data (); #endif /* QUANTIFY */ - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; suppress_early_error_handler_backtrace = 0; lim_data = 0; /* force reinitialization of this variable */ @@ -2826,6 +2999,35 @@ sbrk (1); #endif +#ifdef WIN32_ANY + /* Figure out which version we're running so XEUNICODE_P works */ + init_win32_very_very_early (); +#endif + +#ifdef WIN32_NATIVE +#if 0 + /* !!#### We should be doing something like this, but this messes up + globbing. I tried using wmain() and linking with WSETARGV, but the + routines for WSETARGV are left out of MSVCRT.DLL! + + To fix this we need to copy the argument-expanding and globbing code + from Cygwin and Unicode-ize it. Yuck. */ + if (XEUNICODE_P) + /* Set up Unicode versions of the arguments. */ + vol_argv = CommandLineToArgvW (GetCommandLineW (), &vol_argc); +#else + { + int i; + + vol_argv = alloca_array (Wexttext *, argc); + for (i = 0; i < argc; i++) + vol_argv[i] = MULTIBYTE_TO_WEXTTEXT (argv[i]); + } +#endif +#else + vol_argv = (Wexttext **) argv; +#endif /* WIN32_NATIVE */ + if (!initialized) { #ifdef DOUG_LEA_MALLOC @@ -2834,7 +3036,7 @@ run_temacs_argc = 0; if (! SETJMP (run_temacs_catch)) { - main_1 (vol_argc, vol_argv, vol_envp, 0); + main_1 (vol_argc, vol_argv, NULL, 0); } /* run-emacs-from-temacs called */ restarted = 1; @@ -2855,12 +3057,11 @@ 06/20/96 robertl@dgii.com */ { - extern char **_environ; - if ((unsigned) environ == 0) + extern Extbyte *_environ; + if (environ == NULL) environ = _environ; } #endif /* _SCO_DS */ - vol_envp = environ; } #if defined (RUN_TIME_REMAP) && ! defined (PDUMP) else @@ -2876,7 +3077,7 @@ if (rc != 0) { stderr_out ("malloc_set_state failed, rc = %d\n", rc); - abort (); + ABORT (); } #if 0 free (malloc_state_ptr); @@ -2896,7 +3097,7 @@ run_temacs_argc = -2; - main_1 (vol_argc, vol_argv, vol_envp, restarted); + main_1 (vol_argc, vol_argv, NULL, restarted); #ifdef _MSC_VER } @@ -2914,7 +3115,7 @@ /************************************************************************/ #if !defined (PDUMP) || !defined (SYSTEM_MALLOC) -extern Char_Binary my_edata[]; +extern Rawbyte my_edata[]; #endif extern void disable_free_hook (void); @@ -3022,53 +3223,11 @@ /* exiting XEmacs (intended or not) */ /************************************************************************/ -/* 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. +Info on intended/unintended exits: + + (Info-goto-node "(internals)Exiting") */ /* ------------------------------- */ @@ -3131,7 +3290,7 @@ /* If we can, try to avoid problems with super-optimizing compilers that might decide that memcmp (ptr, ptr, len) can be optimized away since its result is always 1. */ - memcmp (ptr, (char *) ptr + 1, len - 1); + memcmp (ptr, (Rawbyte *) ptr + 1, len - 1); else memcmp (ptr, ptr, len); } @@ -3152,7 +3311,7 @@ Cause XEmacs to enter the debugger. On some systems, there may be no way to do this gracefully; if so, nothing happens unless ABORT is non-nil, in which case XEmacs will -abort() -- a sure-fire way to immediately get back to the debugger, +ABORT() -- a sure-fire way to immediately get back to the debugger, but also a sure-fire way to kill XEmacs (and dump core on Unix systems)! */ @@ -3160,7 +3319,7 @@ { debugging_breakpoint (); if (!NILP (abort_)) - abort (); + ABORT (); return Qnil; } @@ -3315,21 +3474,21 @@ ); #ifndef _MSC_VER { - const char *name; - char *dir = 0; + const Ibyte *name; + Ibyte *dir = 0; /* Now try to determine the actual path to the executable, to try to make the backtrace-determination process as foolproof as possible. */ if (STRINGP (Vinvocation_name)) - name = (char *) XSTRING_DATA (Vinvocation_name); + name = XSTRING_DATA (Vinvocation_name); else - name = "xemacs"; + name = (const Ibyte *) "xemacs"; if (STRINGP (Vinvocation_directory)) - dir = (char *) XSTRING_DATA (Vinvocation_directory); + dir = XSTRING_DATA (Vinvocation_directory); if (!dir || dir[0] != '/') stderr_out ("`which %s`", name); - else if (dir[strlen (dir) - 1] != '/') + else if (dir[qxestrlen (dir) - 1] != '/') stderr_out ("%s/%s", dir, name); else stderr_out ("%s%s", dir, name); @@ -3476,7 +3635,7 @@ guts_of_fatal_error_signal (int sig) { fatal_error_in_progress++; - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; preparing_for_armageddon = 1; ensure_no_quitting_from_now_on (); @@ -3511,13 +3670,13 @@ # if 0 /* This is evil, rarely useful, and causes grief in some cases. */ /* Check for Sun-style stack printing via /proc */ { - const Char_ASCII *pstack = "/usr/proc/bin/pstack"; + const Ascbyte *pstack = "/usr/proc/bin/pstack"; if (access (pstack, X_OK) == 0) { - Char_ASCII buf[100]; + Ascbyte buf[100]; stderr_out ("\nC backtrace follows:\n" "(A real debugger may provide better information)\n\n"); - sprintf (buf, "%s %d >&2", pstack, (int)getpid()); + sprintf (buf, "%s %d >&2", pstack, (int) getpid()); system (buf); } } @@ -3557,7 +3716,7 @@ static DWORD mswindows_handle_hardware_exceptions_1 (void) { - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; preparing_for_armageddon = 1; #if !defined (USER_IS_DEVELOPING_XEMACS) pause_so_user_can_read_messages (0); @@ -3637,26 +3796,25 @@ in one session without having to recompile. */ /* #define ASSERTIONS_DONT_ABORT */ -#ifdef USE_ASSERTIONS /* This highly dubious kludge ... shut up Jamie, I'm tired of your slagging. */ /* Nonzero if handling an assertion failure. (Bumped by one each time we recursively hit such a failure.) */ static int in_assert_failed; -static const char *assert_failed_file; +static const Ascbyte *assert_failed_file; static int assert_failed_line; -static const char *assert_failed_expr; +static const Ascbyte *assert_failed_expr; #ifdef fprintf #undef fprintf #endif -/* This is called when an assert() fails or when abort() is called -- both +/* This is called when an assert() fails or when ABORT() is called -- both of those are defined in the preprocessor to an expansion involving assert_failed(). */ void -assert_failed (const char *file, int line, const char *expr) +assert_failed (const Ascbyte *file, int line, const Ascbyte *expr) { /* If we're already crashing, let's not crash again. This might be critical to getting auto-saving working properly. */ @@ -3666,7 +3824,7 @@ /* We are extremely paranoid so we sensibly deal with recursive assertion failures. */ in_assert_failed++; - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; if (in_assert_failed >= 4) _exit (-1); @@ -3734,10 +3892,9 @@ really_abort (); #endif /* defined (_MSC_VER) || defined (CYGWIN) */ #endif /* !defined (ASSERTIONS_DONT_ABORT) */ - inhibit_non_essential_printing_operations = 0; + inhibit_non_essential_conversion_operations = 0; in_assert_failed = 0; } -#endif /* USE_ASSERTIONS */ /* -------------------------------------- */ /* low-memory notification */ @@ -4222,7 +4379,7 @@ */ ); #ifdef PATH_MULELOADSEARCH Vconfigure_mule_lisp_directory = Ffile_name_as_directory - (build_string ((char *) PATH_MULELOADSEARCH)); + (build_ext_string (PATH_MULELOADSEARCH, Qfile_name); #else Vconfigure_mule_lisp_directory = Qnil; #endif @@ -4388,10 +4545,6 @@ #endif -#undef abort /* Get access to the real version of abort. We put this all - the way at the end to make sure that all calls to abort() - anywhere in the above code go through assert_failed(). */ - DOESNT_RETURN really_abort (void) { diff --text -u 'xemacs-21.5.18/src/emodules.c' 'xemacs-21.5.19/src/emodules.c' Index: ./src/emodules.c --- ./src/emodules.c Sat May 15 00:34:40 2004 +++ ./src/emodules.c Fri Nov 5 08:06:24 2004 @@ -239,12 +239,12 @@ * not previously loaded. */ if (modules == NULL) - modules = (emodules_list *) xmalloc (sizeof (emodules_list)); + modules = xnew (emodules_list); modnum++; - modules = (emodules_list *) xrealloc (modules, modnum * sizeof (emodules_list)); + XREALLOC_ARRAY (modules, emodules_list, modnum); fs = modnum - 1; - memset (&modules[fs], 0, sizeof(emodules_list)); + memset (&modules[fs], 0, sizeof (emodules_list)); return fs; } @@ -333,6 +333,7 @@ emodules_load (const CIbyte *module, const CIbyte *modname, const CIbyte *modver) { + /* !!#### Needs serious work */ Lisp_Object old_load_list; Lisp_Object filename; Lisp_Object foundname, lisp_modname; @@ -588,8 +589,6 @@ #ifdef HAVE_SHLIB Fprovide (intern ("modules")); - reinit_vars_of_module (); - #ifdef HAVE_LTDL lt_dlinit (); lt_dlmalloc = (lt_ptr (*) (size_t)) xmalloc; diff --text -u 'xemacs-21.5.18/src/emodules.h' 'xemacs-21.5.19/src/emodules.h' Index: ./src/emodules.h --- ./src/emodules.h Wed Oct 15 12:09:03 2003 +++ ./src/emodules.h Fri Nov 5 08:06:24 2004 @@ -81,8 +81,8 @@ /* We should not expose module entities to the portable dumper. */ #if defined(PDUMP) && defined(EMACS_MODULE) -#undef dump_add_root_struct_ptr -#define dump_add_root_struct_ptr(varaddr,descaddr) DO_NOTHING +#undef dump_add_root_block_ptr +#define dump_add_root_block_ptr(varaddr,descaddr) DO_NOTHING #undef dump_add_opaque #define dump_add_opaque(varaddr,size) DO_NOTHING #undef dump_add_root_block diff --text -u 'xemacs-21.5.18/src/esd.c' 'xemacs-21.5.19/src/esd.c' Index: ./src/esd.c --- ./src/esd.c Tue Sep 21 04:19:40 2004 +++ ./src/esd.c Fri Nov 5 08:06:25 2004 @@ -42,9 +42,9 @@ return esd_play_file(ESD_NAME, file, 0); } -int esd_play_sound_data (UChar_Binary *data, size_t length, int vol); +int esd_play_sound_data (Binbyte *data, size_t length, int vol); int -esd_play_sound_data (UChar_Binary *data, size_t length, int UNUSED (vol)) +esd_play_sound_data (Binbyte *data, size_t length, int UNUSED (vol)) { /* #### FIXME: vol is ignored */ size_t (*parsesndfile)(void **dayta,size_t *sz,void **outbuf); size_t (*sndcnv)(void **dayta,size_t *sz,void **); diff --text -u 'xemacs-21.5.18/src/eval.c' 'xemacs-21.5.19/src/eval.c' Index: ./src/eval.c --- ./src/eval.c Wed Sep 22 11:06:45 2004 +++ ./src/eval.c Fri Feb 4 01:30:36 2005 @@ -1,7 +1,7 @@ /* Evaluator for XEmacs Lisp interpreter. Copyright (C) 1985-1987, 1992-1994 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -404,6 +404,7 @@ #endif static int warning_will_be_discarded (Lisp_Object level); +static Lisp_Object maybe_get_trapping_problems_backtrace (void); /************************************************************************/ @@ -428,7 +429,7 @@ } static const struct memory_description subr_description[] = { - { XD_DOC_STRING, offsetof (Lisp_Subr, doc), 0, 0, XD_FLAG_NO_KKCC }, + { XD_DOC_STRING, offsetof (Lisp_Subr, doc), 0, { 0 }, XD_FLAG_NO_KKCC }, { XD_END } }; @@ -526,7 +527,7 @@ max_specpdl_size = specpdl_size + 40; speccount = internal_bind_int (&entering_debugger, 1); - val = internal_catch (Qdebugger, call_debugger_259, arg, &threw, 0); + val = internal_catch (Qdebugger, call_debugger_259, arg, &threw, 0, 0); return unbind_to_1 (speccount, ((threw) ? Qunbound /* Not returning a value */ @@ -586,10 +587,10 @@ while (CONSP (conditions)) { - Lisp_Object this, tail; - this = XCAR (conditions); + Lisp_Object curr, tail; + curr = XCAR (conditions); for (tail = list; CONSP (tail); tail = XCDR (tail)) - if (EQ (XCAR (tail), this)) + if (EQ (XCAR (tail), curr)) return 1; conditions = XCDR (conditions); } @@ -1154,25 +1155,24 @@ (args)) { /* This function can GC */ - Lisp_Object symbol, tail, val = Qnil; int nargs; - struct gcpro gcpro1; + Lisp_Object retval = Qnil; GET_LIST_LENGTH (args, nargs); if (nargs & 1) /* Odd number of arguments? */ Fsignal (Qwrong_number_of_arguments, list2 (Qsetq, make_int (nargs))); - GCPRO1 (val); - - PROPERTY_LIST_LOOP (tail, symbol, val, args) + GC_PROPERTY_LIST_LOOP_3 (symbol, val, args) { val = Feval (val); Fset (symbol, val); + retval = val; } - UNGCPRO; - return val; + END_GC_PROPERTY_LIST_LOOP (symbol); + + return retval; } DEFUN ("quote", Fquote, 1, UNEVALLED, 0, /* @@ -1481,7 +1481,7 @@ /* This function can GC */ Lisp_Object tag = Feval (XCAR (args)); Lisp_Object body = XCDR (args); - return internal_catch (tag, Fprogn, body, 0, 0); + return internal_catch (tag, Fprogn, body, 0, 0, 0); } /* Set up a catch, then call C function FUNC on argument ARG. @@ -1493,7 +1493,8 @@ Lisp_Object (*func) (Lisp_Object arg), Lisp_Object arg, int * volatile threw, - Lisp_Object * volatile thrown_tag) + Lisp_Object * volatile thrown_tag, + Lisp_Object * volatile backtrace_before_throw) { /* This structure is made part of the chain `catchlist'. */ struct catchtag c; @@ -1502,6 +1503,7 @@ c.next = catchlist; c.tag = tag; c.actual_tag = Qnil; + c.backtrace = Qnil; c.val = Qnil; c.backlist = backtrace_list; #if 0 /* FSFmacs */ @@ -1522,6 +1524,7 @@ /* Throw works by a longjmp that comes right here. */ if (threw) *threw = 1; if (thrown_tag) *thrown_tag = c.actual_tag; + if (backtrace_before_throw) *backtrace_before_throw = c.backtrace; return c.val; } c.val = (*func) (arg); @@ -1643,7 +1646,7 @@ #ifdef DEFEND_AGAINST_THROW_RECURSION /* die if we recurse more than is reasonable */ if (++throw_level > 20) - abort (); + ABORT (); #endif #ifdef ERROR_CHECK_TRAPPING_PROBLEMS @@ -1678,6 +1681,8 @@ #endif for (c = catchlist; c; c = c->next) { + if (EQ (c->tag, Vcatch_everything_tag)) + c->backtrace = maybe_get_trapping_problems_backtrace (); if (EQ (c->tag, tag) || EQ (c->tag, Vcatch_everything_tag)) unwind_to_catch (c, val, tag); } @@ -1882,6 +1887,7 @@ #endif c.val = Qnil; c.actual_tag = Qnil; + c.backtrace = Qnil; c.backlist = backtrace_list; #if 0 /* FSFmacs */ /* #### */ @@ -2229,7 +2235,7 @@ /* who knows how much has been initialized? Safest bet is just to bomb out immediately. */ stderr_out ("Error before initialization is complete!\n"); - abort (); + ABORT (); } assert (!gc_in_progress); @@ -4814,15 +4820,10 @@ void *arg; }; -static DECLARE_DOESNT_RETURN_TYPE - (Lisp_Object, flagged_a_squirmer (Lisp_Object, Lisp_Object, Lisp_Object)); - -static DOESNT_RETURN_TYPE (Lisp_Object) -flagged_a_squirmer (Lisp_Object error_conditions, Lisp_Object data, - Lisp_Object opaque) +static Lisp_Object +maybe_get_trapping_problems_backtrace (void) { - struct call_trapping_problems *p = - (struct call_trapping_problems *) get_opaque_ptr (opaque); + Lisp_Object backtrace; if (!(inhibit_flags & INHIBIT_WARNING_ISSUE) && !warning_will_be_discarded (current_warning_level ())) @@ -4842,15 +4843,32 @@ lstream = make_resizing_buffer_output_stream (); Fbacktrace (lstream, Qt); Lstream_flush (XLSTREAM (lstream)); - p->backtrace = resizing_buffer_to_lisp_string (XLSTREAM (lstream)); + backtrace = resizing_buffer_to_lisp_string (XLSTREAM (lstream)); Lstream_delete (XLSTREAM (lstream)); UNGCPRO; unbind_to (speccount); } else - p->backtrace = Qnil; + backtrace = Qnil; + return backtrace; +} + +static DECLARE_DOESNT_RETURN_TYPE + (Lisp_Object, flagged_a_squirmer (Lisp_Object, Lisp_Object, Lisp_Object)); + +static DOESNT_RETURN_TYPE (Lisp_Object) +flagged_a_squirmer (Lisp_Object error_conditions, Lisp_Object data, + Lisp_Object opaque) +{ + struct call_trapping_problems *p = + (struct call_trapping_problems *) get_opaque_ptr (opaque); + + if (!EQ (error_conditions, Qquit)) + p->backtrace = maybe_get_trapping_problems_backtrace (); + else + p->backtrace = Qnil; p->error_conditions = error_conditions; p->data = data; @@ -4891,14 +4909,14 @@ { Lisp_Object errstr = emacs_sprintf_string_lisp - ("%s: Attempt to throw outside of function " - "to catch `%s' with value `%s'", + ("%s: Attempt to throw outside of function:" + "To catch `%s' with value `%s'\n\nBacktrace follows:\n\n%s", Qnil, 3, build_msg_string (warning_string ? warning_string : "error"), - p->thrown_tag, p->thrown_value); + p->thrown_tag, p->thrown_value, p->backtrace); warn_when_safe_lispobj (Qerror, current_warning_level (), errstr); } - else if (p->caught_error) + else if (p->caught_error && !EQ (p->error_conditions, Qquit)) { Lisp_Object errstr; /* #### This should call @@ -4979,7 +4997,7 @@ `throw' out of the function being called are trapped, and a warning issued. (Again, WARNING_STRING should be given.) - (If FLAGS contains INHIBIT_WARNING_ISSUE, no warnings are issued; + If FLAGS contains INHIBIT_WARNING_ISSUE, no warnings are issued; this applies to recursive invocations of call_trapping_problems, too. If FLAGS contains POSTPONE_WARNING_ISSUE, no warnings are issued; @@ -5109,7 +5127,7 @@ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; struct call_trapping_problems package; struct call_trapping_problems_result real_problem; - Lisp_Object opaque, thrown_tag, tem; + Lisp_Object opaque, thrown_tag, tem, thrown_backtrace; int thrown = 0; assert (SYMBOLP (warning_class)); /* sanity-check */ @@ -5144,11 +5162,11 @@ after printing the warning. (We print the warning in the stack context of the error, so we can get a backtrace.) */ tem = internal_catch (package.catchtag, call_trapping_problems_1, opaque, - &thrown, &thrown_tag); + &thrown, &thrown_tag, &thrown_backtrace); else if (flags & INTERNAL_INHIBIT_THROWS) /* We skip over the first wrapper, which traps errors. */ tem = internal_catch (package.catchtag, call_trapping_problems_2, opaque, - &thrown, &thrown_tag); + &thrown, &thrown_tag, &thrown_backtrace); else /* Nothing special. */ tem = (fun) (arg); @@ -5182,7 +5200,7 @@ problem->caught_throw = 1; problem->error_conditions = Qnil; problem->data = Qnil; - problem->backtrace = Qnil; + problem->backtrace = thrown_backtrace; problem->thrown_tag = thrown_tag; problem->thrown_value = tem; } @@ -6519,13 +6537,12 @@ #ifdef DEFEND_AGAINST_THROW_RECURSION throw_level = 0; #endif + init_eval_semi_early (); } void vars_of_eval (void) { - reinit_vars_of_eval (); - DEFVAR_INT ("max-specpdl-size", &max_specpdl_size /* Limit on number of Lisp variable bindings & unwind-protects before error. */ ); @@ -6545,7 +6562,7 @@ t each time a Control-G is detected, and to `critical' each time a Shift-Control-G is detected. The XEmacs core C code is littered with calls to the QUIT; macro, which check the values of `quit-flag' and -`inhibit-quit' and abort (or more accurately, call (signal 'quit)) if +`inhibit-quit' and ABORT (or more accurately, call (signal 'quit)) if it's correct to do so. */ ); Vquit_flag = Qnil; @@ -6608,7 +6625,7 @@ \(force-debugging-signal t). This is useful because debugging noninteractive runs of XEmacs is often very difficult, since they typically happen as part of sometimes large and complex make suites (e.g. rebuilding -the XEmacs packages). NOTE: This runs abort()!!! (As well as and after +the XEmacs packages). NOTE: This runs ABORT()!!! (As well as and after executing INT 3 under MS Windows, which should invoke a debugger if it's active.) This is guaranteed to kill XEmacs! (But in this situation, XEmacs is about to die anyway, and if no debugger is present, this will usefully diff --text -u 'xemacs-21.5.18/src/event-Xt.c' 'xemacs-21.5.19/src/event-Xt.c' Index: ./src/event-Xt.c --- ./src/event-Xt.c Tue Sep 21 04:19:40 2004 +++ ./src/event-Xt.c Tue Jan 25 08:33:52 2005 @@ -870,7 +870,7 @@ case MappingKeyboard: x_reset_key_mapping (d); break; case MappingModifier: x_reset_modifier_mapping (d); break; case MappingPointer: /* Do something here? */ break; - default: abort(); + default: ABORT(); } } @@ -1089,6 +1089,7 @@ } case XLookupNone: return Qnil; case XBufferOverflow: + /* !!#### needs work */ bufptr = (char *) ALLOCA (len+1); bufsiz = len+1; goto Lookup_String; @@ -1344,7 +1345,7 @@ explicitly prohibits. */ XClientMessageEvent *ev = &x_event->xclient; #ifdef HAVE_OFFIX_DND - if (DndIsDropMessage(x_event)) + if (DndIsDropMessage (x_event)) { unsigned int state; int modifiers = 0; @@ -1362,7 +1363,8 @@ GCPRO4 (l_type, l_data, l_dndlist, l_item); set_event_type (emacs_event, misc_user_event); SET_EVENT_CHANNEL (emacs_event, wrap_frame (frame)); - SET_EVENT_TIMESTAMP (emacs_event, DEVICE_X_LAST_SERVER_TIMESTAMP (d)); + SET_EVENT_TIMESTAMP (emacs_event, + DEVICE_X_LAST_SERVER_TIMESTAMP (d)); state=DndDragButtons (x_event); if (state & ShiftMask) modifiers |= XEMACS_MOD_SHIFT; @@ -1389,35 +1391,36 @@ DndDropCoordinates (FRAME_X_TEXT_WIDGET (frame), x_event, &(EVENT_MISC_USER_X (emacs_event)), &(EVENT_MISC_USER_Y (emacs_event))); - DndGetData (x_event,&data,&size); + DndGetData (x_event, &data, &size); - dtype=DndDataType (x_event); + dtype = DndDataType (x_event); switch (dtype) { case DndFiles: /* null terminated strings, end null */ { int len; - char *hurl = NULL; + Ibyte *hurl = NULL; while (*data) { - len = strlen ((char*)data); - hurl = dnd_url_hexify_string ((char *)data, "file:"); - l_item = make_string ((Ibyte *)hurl, strlen (hurl)); + Ibyte *dataint; + len = strlen (data); + EXTERNAL_TO_C_STRING (data, dataint, Qfile_name); + hurl = dnd_url_hexify_string (dataint, "file:"); + l_item = build_intstring (hurl); l_dndlist = Fcons (l_item, l_dndlist); data += len + 1; - xfree (hurl, char *); + xfree (hurl, Ibyte *); } l_type = Qdragdrop_URL; } break; case DndText: l_type = Qdragdrop_MIME; - l_dndlist = list1 ( list3 ( list1 ( make_string ((Ibyte *)"text/plain", 10) ), - make_string ((Ibyte *)"8bit", 4), - make_ext_string ((Extbyte *)data, - strlen((char *)data), - Qctext) ) ); + l_dndlist = list1 (list3 (list1 (build_string ("text/plain")), + build_string ("8bit"), + build_ext_string (data, + Qctext))); break; case DndMIME: /* we have to parse this in some way to extract @@ -1428,44 +1431,41 @@ to tm... */ l_type = Qdragdrop_MIME; - l_dndlist = list1 ( make_ext_string ((Extbyte *)data, - strlen((char *)data), - Qbinary) ); + l_dndlist = list1 (build_ext_string (data, Qbinary)); break; case DndFile: case DndDir: case DndLink: case DndExe: { - char *hurl = dnd_url_hexify_string ((char *) data, "file:"); - - l_dndlist = list1 ( make_string ((Ibyte *)hurl, - strlen (hurl)) ); - l_type = Qdragdrop_URL; - - xfree (hurl, char *); + Ibyte *dataint, *hurl; + EXTERNAL_TO_C_STRING (data, dataint, Qfile_name); + hurl = dnd_url_hexify_string (dataint, "file:"); + l_dndlist = list1 (build_intstring (hurl)); + xfree (hurl, Ibyte *); } break; case DndURL: /* as it is a real URL it should already be escaped and escaping again will break them (cause % is unsave) */ - l_dndlist = list1 ( make_ext_string ((Extbyte *)data, - strlen ((char *)data), - Qfile_name) ); + l_dndlist = list1 (build_ext_string (data, + Qfile_name)); l_type = Qdragdrop_URL; break; default: /* Unknown, RawData and any other type */ - l_dndlist = list1 ( list3 ( list1 ( make_string ((Ibyte *)"application/octet-stream", 24) ), - make_string ((Ibyte *)"8bit", 4), - make_ext_string ((Extbyte *)data, - size, - Qbinary) ) ); + l_dndlist = list1 (list3 (list1 (build_string + ("application/octet-stream")), + build_string ("8bit"), + make_ext_string (data, size, + Qbinary))); l_type = Qdragdrop_MIME; break; } - SET_EVENT_MISC_USER_FUNCTION (emacs_event, Qdragdrop_drop_dispatch); - SET_EVENT_MISC_USER_OBJECT (emacs_event, Fcons (l_type, l_dndlist)); + SET_EVENT_MISC_USER_FUNCTION (emacs_event, + Qdragdrop_drop_dispatch); + SET_EVENT_MISC_USER_OBJECT (emacs_event, + Fcons (l_type, l_dndlist)); UNGCPRO; @@ -2456,7 +2456,7 @@ return; } } - abort (); + ABORT (); } static void @@ -3214,8 +3214,6 @@ void vars_of_event_Xt (void) { - reinit_vars_of_event_Xt (); - DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /* *Non-nil means to allow synthetic events. Nil means they are ignored. Beware: allowing emacs to process SendEvents opens a big security hole. diff --text -u 'xemacs-21.5.18/src/event-gtk.c' 'xemacs-21.5.19/src/event-gtk.c' Index: ./src/event-gtk.c --- ./src/event-gtk.c Tue Sep 21 04:19:41 2004 +++ ./src/event-gtk.c Tue Jan 25 08:33:52 2005 @@ -97,10 +97,23 @@ Lisp_Object Qkey_mapping; Lisp_Object Qsans_modifiers; +/* + * Identify if the keysym is a modifier. This implementation mirrors x.org's + * IsModifierKey(), but for GDK keysyms. + */ +#ifdef GDK_ISO_Lock #define IS_MODIFIER_KEY(keysym) \ ((((keysym) >= GDK_Shift_L) && ((keysym) <= GDK_Hyper_R)) \ + || (((keysym) >= GDK_ISO_Lock) && \ + ((keysym) <= GDK_ISO_Last_Group_Lock)) \ || ((keysym) == GDK_Mode_switch) \ || ((keysym) == GDK_Num_Lock)) +#else +#define IS_MODIFIER_KEY(keysym) \ + ((((keysym) >= GDK_Shift_L) && ((keysym) <= GDK_Hyper_R)) \ + || ((keysym) == GDK_Mode_switch) \ + || ((keysym) == GDK_Num_Lock)) +#endif #define THIS_IS_GTK #include "event-xlike-inc.c" @@ -891,7 +904,7 @@ return; } } - abort (); + ABORT (); } static void @@ -1648,8 +1661,6 @@ void vars_of_event_gtk (void) { - reinit_vars_of_event_gtk (); - DEFVAR_BOOL ("gtk-allow-sendevents", >k_allow_sendevents /* *Non-nil means to allow synthetic events. Nil means they are ignored. Beware: allowing emacs to process SendEvents opens a big security hole. diff --text -u 'xemacs-21.5.18/src/event-gtk.h' 'xemacs-21.5.19/src/event-gtk.h' Index: ./src/event-gtk.h --- ./src/event-gtk.h Sat Mar 16 19:39:16 2002 +++ ./src/event-gtk.h Fri Nov 5 08:06:26 2004 @@ -32,6 +32,5 @@ gboolean emacs_shell_event_handler (GtkWidget *wid /* unused */, GdkEvent *event, gpointer closure); -void reinit_vars_of_event_gtk (void); #endif /* __EVENT-GTK_H__ */ diff --text -u 'xemacs-21.5.18/src/event-msw.c' 'xemacs-21.5.19/src/event-msw.c' Index: ./src/event-msw.c --- ./src/event-msw.c Tue Sep 21 04:19:41 2004 +++ ./src/event-msw.c Fri Jan 28 11:36:24 2005 @@ -1655,9 +1655,9 @@ mswindows_enqueue_process_event (XPROCESS (vaffanculo)); else { - /* abort (); */ + /* ABORT (); */ /* #### FUCKME! When can this happen? I hit this - abort() when I tried enabling it. */ + ABORT() when I tried enabling it. */ /* Have to return something: there may be no accompanying process event */ mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); @@ -2065,7 +2065,7 @@ else if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)) { DWORD len = DdeGetData (hdata, NULL, 0, 0); - LPBYTE extcmd = (LPBYTE) ALLOCA (len + 1); + Extbyte *extcmd = alloca_extbytes (len + 1); Ibyte *cmd; Ibyte *end; struct gcpro gcpro1, gcpro2; @@ -2074,7 +2074,7 @@ Lisp_Object frmcons, devcons, concons; Lisp_Event *event = XEVENT (emacs_event); - DdeGetData (hdata, extcmd, len, 0); + DdeGetData (hdata, (LPBYTE) extcmd, len, 0); DdeFreeDataHandle (hdata); TO_INTERNAL_FORMAT (DATA, (extcmd, len), @@ -2085,7 +2085,7 @@ * treat like a file drop */ if (*cmd == '[') cmd++; - if (qxestrncasecmp_c (cmd, MSWINDOWS_DDE_ITEM_OPEN, + if (qxestrncasecmp_ascii (cmd, MSWINDOWS_DDE_ITEM_OPEN, strlen (MSWINDOWS_DDE_ITEM_OPEN))) return DDE_FNOTPROCESSED; cmd += strlen (MSWINDOWS_DDE_ITEM_OPEN); @@ -2823,7 +2823,7 @@ lcid = MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US); break; - default: abort (); lcid = 0; + default: ABORT (); lcid = 0; } /* VERY CONFUSING! See intl-win32.c. */ @@ -2946,7 +2946,7 @@ if one wants to exercise fingers playing chords on the mouse, he is allowed to do that! */ mswindows_enqueue_mouse_button_event (hwnd, message_, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ MK_MBUTTON, GetMessageTime()); break; @@ -2966,7 +2966,7 @@ msframe->button2_is_down = 0; msframe->ignore_next_rbutton_up = 1; mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON), @@ -2978,12 +2978,12 @@ { msframe->button2_need_rbutton = 0; mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ MK_LBUTTON, GetMessageTime()); } mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONUP, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ MK_LBUTTON, GetMessageTime()); } @@ -3004,7 +3004,7 @@ msframe->button2_is_down = 0; msframe->ignore_next_lbutton_up = 1; mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON), @@ -3016,12 +3016,12 @@ { msframe->button2_need_lbutton = 0; mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ MK_RBUTTON, GetMessageTime()); } mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONUP, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ MK_RBUTTON, GetMessageTime()); } @@ -3036,10 +3036,10 @@ msframe->button2_need_lbutton = 0; msframe->button2_need_rbutton = 0; if (mswindows_button2_near_enough (msframe->last_click_point, - MAKEPOINTS (lParam))) + XE_MAKEPOINTS (lParam))) { mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON), @@ -3054,7 +3054,7 @@ &~ MK_RBUTTON, msframe->last_click_time); mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ MK_LBUTTON, GetMessageTime()); } @@ -3063,7 +3063,7 @@ { mswindows_set_chord_timer (hwnd); msframe->button2_need_rbutton = 1; - msframe->last_click_point = MAKEPOINTS (lParam); + msframe->last_click_point = XE_MAKEPOINTS (lParam); msframe->last_click_mods = wParam; } msframe->last_click_time = GetMessageTime(); @@ -3078,10 +3078,10 @@ msframe->button2_need_lbutton = 0; msframe->button2_need_rbutton = 0; if (mswindows_button2_near_enough (msframe->last_click_point, - MAKEPOINTS (lParam))) + XE_MAKEPOINTS (lParam))) { mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON), @@ -3096,7 +3096,7 @@ &~ MK_LBUTTON, msframe->last_click_time); mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam &~ MK_RBUTTON, GetMessageTime()); } @@ -3105,7 +3105,7 @@ { mswindows_set_chord_timer (hwnd); msframe->button2_need_lbutton = 1; - msframe->last_click_point = MAKEPOINTS (lParam); + msframe->last_click_point = XE_MAKEPOINTS (lParam); msframe->last_click_mods = wParam; } msframe->last_click_time = GetMessageTime(); @@ -3151,7 +3151,7 @@ as if timer has expired. This improves drag-select feedback */ if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton) && !mswindows_button2_near_enough (msframe->last_click_point, - MAKEPOINTS (lParam))) + XE_MAKEPOINTS (lParam))) { KillTimer (hwnd, BUTTON_2_TIMER_ID); qxeSendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0); @@ -3163,8 +3163,8 @@ XSET_EVENT_CHANNEL (emacs_event, mswindows_find_frame(hwnd)); XSET_EVENT_TIMESTAMP (emacs_event, GetMessageTime()); XSET_EVENT_TYPE (emacs_event, pointer_motion_event); - XSET_EVENT_MOTION_X (emacs_event,MAKEPOINTS (lParam).x); - XSET_EVENT_MOTION_Y (emacs_event,MAKEPOINTS (lParam).y); + XSET_EVENT_MOTION_X (emacs_event, XE_MAKEPOINTS (lParam).x); + XSET_EVENT_MOTION_Y (emacs_event, XE_MAKEPOINTS (lParam).y); XSET_EVENT_MOTION_MODIFIERS (emacs_event, mswindows_modifier_state (NULL, wParam, 0)); @@ -3207,7 +3207,7 @@ may be copying an ANSI string into it. Easiest to just zero the whole thing. */ xzero (*tttextw->szText); - xetcsncpy ((Extbyte *) tttextw->szText, btextext, 79); + qxetcsncpy ((Extbyte *) tttextw->szText, btextext, 79); } else tttextw->lpszText = NULL; @@ -3558,9 +3558,9 @@ displayed */ if (!mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd), keys, delta, - MAKEPOINTS (lParam))) + XE_MAKEPOINTS (lParam))) mswindows_enqueue_mouse_button_event (hwnd, message_, - MAKEPOINTS (lParam), + XE_MAKEPOINTS (lParam), wParam, GetMessageTime()); /* We are not in a modal loop so no pumping is necessary. */ @@ -3712,169 +3712,32 @@ Extbyte *fname_ext; Bytecount fnamelen; Charcount len = qxeDragQueryFile ((HDROP) wParam, i, NULL, 0); + int freeme = 0; /* The URLs that we make here aren't correct according to section * 3.10 of rfc1738 because they're missing the //<host>/ part and * because they may contain reserved characters. But that's OK - * they just need to be good enough to keep dragdrop.el happy. */ - fname_ext = (Extbyte *) ALLOCA ((len + 1) * XETCHAR_SIZE); + fname_ext = alloca_extbytes ((len + 1) * XETCHAR_SIZE); qxeDragQueryFile ((HDROP) wParam, i, fname_ext, len + 1); TO_INTERNAL_FORMAT (DATA, (fname_ext, len * XETCHAR_SIZE), ALLOCA, (fname, fnamelen), Qmswindows_tstr); + /* May be a shell link aka "shortcut" - replace fname if so */ -#if !defined (NO_CYGWIN_COM_SUPPORT) - if (!qxestrcasecmp_c (fname + fnamelen - 4, ".LNK")) + if (!qxestrcasecmp_ascii (fname + fnamelen - 4, ".LNK")) { - /* #### - - Note the following in the docs: - - Note: The IShellLink interface has an ANSI version - (IShellLinkA) and a Unicode version (IShellLinkW). The - version that will be used depends on whether you compile - for ANSI or Unicode. However, Microsoft® Windows 95 and - Microsoft® Windows 98 only support IShellLinkA. - - We haven't yet implemented COM support in the - Unicode-splitting library. I don't quite understand how - COM works yet, but it looks like what's happening is - that the ShellLink class implements both the IShellLinkA - and IShellLinkW interfaces. To make this work at - run-time, we have to do something like this: - - -- define a new interface qxeIShellLink that uses - Extbyte * instead of LPSTR or LPWSTR. (not totally - necessary since Extbyte * == LPSTR). - - -- define a new class qxeShellLink that implements - qxeIShellLink. the methods on this class need to create - a shadow ShellLink object to do all the real work, and - call the corresponding function from either the - IShellLinkA or IShellLinkW interfaces on this object, - depending on whether XEUNICODE_P is defined. - - -- with appropriate preprocessor magic, of course, we - could make things appear transparent; but we've decided - not to do preprocessor magic for the moment. - */ - - /* #### Not Unicode-split for the moment; we have to do it - ourselves. */ - if (XEUNICODE_P) - { - IShellLinkW *psl; - - if (CoCreateInstance ( - XECOMID (CLSID_ShellLink), - NULL, - CLSCTX_INPROC_SERVER, - XECOMID (IID_IShellLinkW), - (void **) &psl) == S_OK) - { - IPersistFile *ppf; - - if (XECOMCALL2 (psl, QueryInterface, - XECOMID (IID_IPersistFile), - (void **) &ppf) == - S_OK) - { - Extbyte *fname_unicode; - WIN32_FIND_DATAW wfd; - LPWSTR resolved = - alloca_array (WCHAR, PATH_MAX + 1); - - TO_EXTERNAL_FORMAT (DATA, (fname, fnamelen), - C_STRING_ALLOCA, - fname_unicode, - Qmswindows_unicode); - - if (XECOMCALL2 (ppf, Load, - (LPWSTR) fname_unicode, - STGM_READ) == S_OK && - /* #### YUCK! Docs read - - cchMaxPath - - Maximum number of bytes to copy to the buffer pointed to by the - pszFile parameter. - - But "cch" means "count of characters", not bytes. I'll assume the doc - writers messed up and the programmer was correct. Also, this approach - is safe even if it's actually the other way around. */ -#if defined (CYGWIN_HEADERS) && W32API_INSTALLED_VER < W32API_VER(2,2) - /* Another Cygwin prototype error, - fixed in v2.2 of w32api */ - XECOMCALL4 (psl, GetPath, (LPSTR) resolved, - PATH_MAX, &wfd, 0) -#else - XECOMCALL4 (psl, GetPath, resolved, - PATH_MAX, &wfd, 0) -#endif - == S_OK) - TO_INTERNAL_FORMAT (C_STRING, resolved, - ALLOCA, (fname, fnamelen), - Qmswindows_tstr); - - XECOMCALL0 (ppf, Release); - } - - XECOMCALL0 (psl, Release); - } - } - else - { - IShellLinkA *psl; - - if (CoCreateInstance ( - XECOMID (CLSID_ShellLink), - NULL, - CLSCTX_INPROC_SERVER, - XECOMID (IID_IShellLinkA), - (void **) &psl) == S_OK) - { - IPersistFile *ppf; - - if (XECOMCALL2 (psl, QueryInterface, - XECOMID (IID_IPersistFile), - (void **) &ppf) == - S_OK) - { - Extbyte *fname_unicode; - WIN32_FIND_DATAA wfd; - LPSTR resolved = - alloca_array (CHAR, PATH_MAX + 1); - - /* Always Unicode. Not obvious from the - IPersistFile documentation, but look under - "Shell Link" for example code. */ - TO_EXTERNAL_FORMAT (DATA, (fname, fnamelen), - C_STRING_ALLOCA, - fname_unicode, - Qmswindows_unicode); - - if (XECOMCALL2 (ppf, Load, - (LPWSTR) fname_unicode, - STGM_READ) == S_OK - && XECOMCALL4 (psl, GetPath, resolved, - PATH_MAX, &wfd, 0) == S_OK) - TO_INTERNAL_FORMAT (C_STRING, resolved, - ALLOCA, (fname, fnamelen), - Qmswindows_tstr); - - XECOMCALL0 (ppf, Release); - } - - XECOMCALL0 (psl, Release); - } - } + fname = mswindows_read_link (fname); + freeme = 1; } -#endif /* !defined (NO_CYGWIN_COM_SUPPORT) */ + { - fname = urlify_filename (fname); - l_item = build_intstring (fname); - xfree (fname, Ibyte *); + Ibyte *fname2 = urlify_filename (fname); + l_item = build_intstring (fname2); + xfree (fname2, Ibyte *); + if (freeme) + xfree (fname, Ibyte *); l_dndlist = Fcons (l_item, l_dndlist); } } @@ -3916,7 +3779,7 @@ ImmGetCompositionStringW is supported even on Windows 9x, and allows us to handle multiple languages. */ len = ImmGetCompositionStringW (imc, GCS_RESULTSTR, NULL, 0); - result = alloca_array (Extbyte, len); + result = alloca_extbytes (len); ImmGetCompositionStringW (imc, GCS_RESULTSTR, (WCHAR *) result, len); ImmReleaseContext (hwnd, imc); @@ -4421,7 +4284,7 @@ FROB (XM_MAPFRAME); FROB (XM_UNMAPFRAME); - default: abort (); + default: ABORT (); } #undef FROB @@ -5180,8 +5043,6 @@ void vars_of_event_mswindows (void) { - reinit_vars_of_event_mswindows (); - mswindows_s_dispatch_event_queue = Qnil; staticpro (&mswindows_s_dispatch_event_queue); mswindows_s_dispatch_event_queue_tail = Qnil; diff --text -u 'xemacs-21.5.18/src/event-stream.c' 'xemacs-21.5.19/src/event-stream.c' Index: ./src/event-stream.c --- ./src/event-stream.c Tue Sep 21 04:19:41 2004 +++ ./src/event-stream.c Tue Jan 25 08:33:53 2005 @@ -277,52 +277,13 @@ /* The callback routines for the window system or terminal driver */ struct event_stream *event_stream; -/* 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. - */ + +/* + +See also + + (Info-goto-node "(internals)Event Stream Callback Routines") +*/ static Lisp_Object command_event_queue; static Lisp_Object command_event_queue_tail; @@ -1340,7 +1301,7 @@ Lisp_Object lid; id = event_stream_generate_wakeup (msecs, msecs2, function, object, 0); lid = make_int (id); - if (id != XINT (lid)) abort (); + if (id != XINT (lid)) ABORT (); return lid; } @@ -1419,7 +1380,7 @@ Lisp_Object lid; id = event_stream_generate_wakeup (msecs, msecs2, function, object, 1); lid = make_int (id); - if (id != XINT (lid)) abort (); + if (id != XINT (lid)) ABORT (); return lid; } @@ -1554,76 +1515,12 @@ /* -Ben's capsule lecture on focus: - -In FSFmacs `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 FSFmacs, 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. - -FSFmacs 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 FSFmacs 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. +See also + (Info-goto-node "(internals)Focus Handling") */ + static void run_select_frame_hook (void) { @@ -3184,7 +3081,7 @@ event_stream_handle_magic_event (XEVENT (event)); goto done; default: - abort (); + ABORT (); } done: @@ -3694,7 +3591,7 @@ Lisp_Object e = XVECTOR_DATA (Vrecent_keys_ring)[j]; if (NILP (e)) - abort (); + ABORT (); XVECTOR_DATA (val)[i] = Fcopy_event (e, Qnil); if (++j >= recent_keys_ring_size) j = 0; @@ -3838,7 +3735,7 @@ { if (!n) { - /* must copy to avoid an abort() in next_event_internal() */ + /* must copy to avoid an ABORT() in next_event_internal() */ if (!NILP (XEVENT_NEXT (event))) return Fcopy_event (event, Qnil); else @@ -3971,7 +3868,7 @@ SET_EVENT_BUTTON_MODIFIERS (e, EVENT_BUTTON_MODIFIERS (e) | XEMACS_MOD_META); else - abort (); + ABORT (); { int tckn = event_chain_count (Vthis_command_keys); @@ -4863,7 +4760,6 @@ void vars_of_event_stream (void) { - reinit_vars_of_event_stream (); Vrecent_keys_ring = Qnil; staticpro (&Vrecent_keys_ring); diff --text -u 'xemacs-21.5.18/src/event-tty.c' 'xemacs-21.5.19/src/event-tty.c' Index: ./src/event-tty.c --- ./src/event-tty.c Tue Sep 21 04:19:41 2004 +++ ./src/event-tty.c Fri Nov 5 08:06:27 2004 @@ -299,7 +299,6 @@ void vars_of_event_tty (void) { - reinit_vars_of_event_tty (); } void diff --text -u 'xemacs-21.5.18/src/events.c' 'xemacs-21.5.19/src/events.c' Index: ./src/events.c --- ./src/events.c Wed Oct 20 02:19:06 2004 +++ ./src/events.c Fri Feb 4 01:14:05 2005 @@ -189,16 +189,16 @@ }; static const struct memory_description event_data_description_1 [] = { - { XD_STRUCT_ARRAY, key_press_event, 1, &key_data_description }, - { XD_STRUCT_ARRAY, button_press_event, 1, &button_data_description }, - { XD_STRUCT_ARRAY, button_release_event, 1, &button_data_description }, - { XD_STRUCT_ARRAY, pointer_motion_event, 1, &motion_data_description }, - { XD_STRUCT_ARRAY, process_event, 1, &process_data_description }, - { XD_STRUCT_ARRAY, timeout_event, 1, &timeout_data_description }, - { XD_STRUCT_ARRAY, magic_event, 1, &magic_data_description }, - { XD_STRUCT_ARRAY, magic_eval_event, 1, &magic_eval_data_description }, - { XD_STRUCT_ARRAY, eval_event, 1, &eval_data_description }, - { XD_STRUCT_ARRAY, misc_user_event, 1, &misc_user_data_description }, + { XD_BLOCK_ARRAY, key_press_event, 1, { &key_data_description } }, + { XD_BLOCK_ARRAY, button_press_event, 1, { &button_data_description } }, + { XD_BLOCK_ARRAY, button_release_event, 1, { &button_data_description } }, + { XD_BLOCK_ARRAY, pointer_motion_event, 1, { &motion_data_description } }, + { XD_BLOCK_ARRAY, process_event, 1, { &process_data_description } }, + { XD_BLOCK_ARRAY, timeout_event, 1, { &timeout_data_description } }, + { XD_BLOCK_ARRAY, magic_event, 1, { &magic_data_description } }, + { XD_BLOCK_ARRAY, magic_eval_event, 1, { &magic_eval_data_description } }, + { XD_BLOCK_ARRAY, eval_event, 1, { &eval_data_description } }, + { XD_BLOCK_ARRAY, misc_user_event, 1, { &misc_user_data_description } }, { XD_END } }; @@ -211,7 +211,7 @@ { XD_LISP_OBJECT, offsetof (struct Lisp_Event, next) }, { XD_LISP_OBJECT, offsetof (struct Lisp_Event, channel) }, { XD_UNION, offsetof (struct Lisp_Event, event), - XD_INDIRECT (0, 0), &event_data_description }, + XD_INDIRECT (0, 0), { &event_data_description } }, { XD_END } }; @@ -306,7 +306,7 @@ case dead_event: break; default: - abort (); + ABORT (); } mark_object (event->channel); return event->next; @@ -399,7 +399,7 @@ /* if (e1->timestamp != e2->timestamp) return 0; */ switch (e1->event_type) { - default: abort (); + default: ABORT (); case process_event: return EQ (EVENT_PROCESS_PROCESS (e1), EVENT_PROCESS_PROCESS (e2)); @@ -505,7 +505,7 @@ return hash; default: - abort (); + ABORT (); } return 0; /* unreached */ @@ -823,7 +823,7 @@ SET_EVENT_MISC_USER_Y (e, coord_y); break; default: - abort (); + ABORT (); } } @@ -884,18 +884,18 @@ if (EQ (event, Vlast_command_event) || EQ (event, Vlast_input_event) || EQ (event, Vunread_command_event)) - abort (); + ABORT (); len = XVECTOR_LENGTH (Vthis_command_keys); for (i = 0; i < len; i++) if (EQ (event, XVECTOR_DATA (Vthis_command_keys) [i])) - abort (); + ABORT (); if (!NILP (Vrecent_keys_ring)) { int recent_ring_len = XVECTOR_LENGTH (Vrecent_keys_ring); for (i = 0; i < recent_ring_len; i++) if (EQ (event, XVECTOR_DATA (Vrecent_keys_ring) [i])) - abort (); + ABORT (); } } #endif /* 0 */ @@ -1110,7 +1110,7 @@ event_chain = XEVENT_NEXT (event_chain); } - abort (); + ABORT (); return Qnil; } @@ -1324,7 +1324,7 @@ if (CHAR_OR_CHAR_INTP (XEVENT_KEY_KEYSYM (event))) c = XCHAR_OR_CHAR_INT (XEVENT_KEY_KEYSYM (event)); else if (!SYMBOLP (XEVENT_KEY_KEYSYM (event))) - abort (); + ABORT (); else if (map_device_key_names && !NILP (Vcharacter_set_property) /* Allow window-system-specific extensibility of keysym->code mapping */ @@ -1542,20 +1542,20 @@ UNGCPRO; return; } - case magic_eval_event: eicat_c (buf, "magic-eval"); return; - case pointer_motion_event: eicat_c (buf, "motion"); return; - case misc_user_event: eicat_c (buf, "misc-user"); return; - case eval_event: eicat_c (buf, "eval"); return; - case process_event: eicat_c (buf, "process"); return; - case timeout_event: eicat_c (buf, "timeout"); return; - case empty_event: eicat_c (buf, "empty"); return; - case dead_event: eicat_c (buf, "DEAD-EVENT"); return; + case magic_eval_event: eicat_ascii (buf, "magic-eval"); return; + case pointer_motion_event: eicat_ascii (buf, "motion"); return; + case misc_user_event: eicat_ascii (buf, "misc-user"); return; + case eval_event: eicat_ascii (buf, "eval"); return; + case process_event: eicat_ascii (buf, "process"); return; + case timeout_event: eicat_ascii (buf, "timeout"); return; + case empty_event: eicat_ascii (buf, "empty"); return; + case dead_event: eicat_ascii (buf, "DEAD-EVENT"); return; default: - abort (); + ABORT (); return; } #define modprint(x,y) \ - do { if (brief) eicat_c (buf, (y)); else eicat_c (buf, (x)); } while (0) + do { if (brief) eicat_ascii (buf, (y)); else eicat_ascii (buf, (x)); } while (0) if (mod & XEMACS_MOD_CONTROL) modprint ("control-", "C-"); if (mod & XEMACS_MOD_META) modprint ("meta-", "M-"); if (mod & XEMACS_MOD_SUPER) modprint ("super-", "S-"); @@ -1564,7 +1564,7 @@ if (mod & XEMACS_MOD_SHIFT) modprint ("shift-", "Sh-"); if (mouse_p) { - eicat_c (buf, "button"); + eicat_ascii (buf, "button"); --mouse_p; } @@ -1574,7 +1574,7 @@ eicat_ch (buf, XCHAR (key)); else if (SYMBOLP (key)) { - const Char_ASCII *str = 0; + const Ascbyte *str = 0; if (brief) { if (EQ (key, QKlinefeed)) str = "LFD"; @@ -1586,14 +1586,14 @@ else if (EQ (key, QKbackspace)) str = "BS"; } if (str) - eicat_c (buf, str); + eicat_ascii (buf, str); else eicat_lstr (buf, XSYMBOL (key)->name); } else - abort (); + ABORT (); if (mouse_p) - eicat_c (buf, "up"); + eicat_ascii (buf, "up"); } void @@ -1740,7 +1740,7 @@ return Qempty; default: - abort (); + ABORT (); return Qnil; } } @@ -2130,9 +2130,9 @@ || TOOLBAR_BUTTONP (ret_obj1) #endif )) - abort (); + ABORT (); if (!NILP (ret_obj2) && !(EXTENTP (ret_obj2) || CONSP (ret_obj2))) - abort (); + ABORT (); if (char_x) *char_x = ret_x; @@ -2480,7 +2480,7 @@ switch (EVENT_TYPE (e)) { - default: abort (); + default: ABORT (); case process_event: props = cons3 (Qprocess, EVENT_PROCESS_PROCESS (e), props); @@ -2634,8 +2634,6 @@ void vars_of_events (void) { - reinit_vars_of_events (); - DEFVAR_LISP ("character-set-property", &Vcharacter_set_property /* This is used to map e.g. `ocircumflex' to the appropriate character under X. This value of this variable (a symbol, normally `x-iso8859-1' if not nil) diff --text -u 'xemacs-21.5.18/src/events.h' 'xemacs-21.5.19/src/events.h' Index: ./src/events.h --- ./src/events.h Fri Feb 7 20:50:53 2003 +++ ./src/events.h Fri Nov 5 08:06:27 2004 @@ -27,164 +27,13 @@ #include "systime.h" -/* 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 These callbacks tell the underlying implementation to - unselect_process_cb 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 These callbacks tell the underlying implementation - unselect_console_cb to add or remove a console from the list of consoles - which are polled for user-input. - - select_device_cb These callbacks are used by Unixoid event loops - unselect_device_cb (those that use select() and file descriptors and - have a separate input fd per device). - - create_io_streams_cb These callbacks are called by process code to - delete_io_streams_cb 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. -*/ - /* - Stream pairs description - ------------------------ - 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. +See also + + (Info-goto-node "(internals)Event Stream Callback Routines") + (Info-goto-node "(internals)Stream Pairs") + */ /* typedef unsigned int USID; in lisp.h */ diff --text -u 'xemacs-21.5.18/src/extents.c' 'xemacs-21.5.19/src/extents.c' Index: ./src/extents.c --- ./src/extents.c Tue Sep 21 04:19:42 2004 +++ ./src/extents.c Fri Feb 4 01:14:06 2005 @@ -1,6 +1,6 @@ /* Copyright (c) 1994, 1995 Free Software Foundation, Inc. Copyright (c) 1995 Sun Microsystems, Inc. - Copyright (c) 1995, 1996, 2000, 2002, 2003 Ben Wing. + Copyright (c) 1995, 1996, 2000, 2002, 2003, 2004, 2005 Ben Wing. This file is part of XEmacs. @@ -264,14 +264,6 @@ offset_past_gap = elsize * (gap + gapsize) els_past_gap = numels - gap - - #### The current layout will not cut it for dumping purposes. If we - need to dump one of these structures, we will have to rearrange things - so that the gap array data and other fields are in one single memory - block. Either this is a pointer off of struct gap_array, or it is - struct gap_array itself; in the latter case, the interface below has to - be modified so that functions that change the array pass in a ** rather - than a *, since the pointer may move. */ @@ -1036,8 +1028,8 @@ extern const struct sized_memory_description gap_array_marker_description; static const struct memory_description gap_array_marker_description_1[] = { - { XD_STRUCT_PTR, offsetof (Gap_Array_Marker, next), 1, - &gap_array_marker_description }, + { XD_BLOCK_PTR, offsetof (Gap_Array_Marker, next), 1, + { &gap_array_marker_description } }, { XD_END } }; @@ -1050,12 +1042,12 @@ { XD_INT, offsetof (Gap_Array, gap) }, { XD_INT, offsetof (Gap_Array, offset_past_gap) }, { XD_INT, offsetof (Gap_Array, els_past_gap) }, - { XD_STRUCT_PTR, offsetof (Gap_Array, markers), 1, - &gap_array_marker_description, XD_FLAG_NO_KKCC }, - { XD_STRUCT_ARRAY, offsetof (Gap_Array, array), XD_INDIRECT (0, 0), - &lisp_object_description }, - { XD_STRUCT_ARRAY, XD_INDIRECT (1, offsetof (Gap_Array, array)), - XD_INDIRECT (2, 0), &lisp_object_description }, + { XD_BLOCK_PTR, offsetof (Gap_Array, markers), 1, + { &gap_array_marker_description }, XD_FLAG_NO_KKCC }, + { XD_BLOCK_ARRAY, offsetof (Gap_Array, array), XD_INDIRECT (0, 0), + { &lisp_object_description } }, + { XD_BLOCK_ARRAY, XD_INDIRECT (1, offsetof (Gap_Array, array)), + XD_INDIRECT (2, 0), { &lisp_object_description } }, { XD_END } }; @@ -1067,10 +1059,10 @@ extern const struct sized_memory_description extent_list_marker_description; static const struct memory_description extent_list_marker_description_1[] = { - { XD_STRUCT_PTR, offsetof (Extent_List_Marker, m), 1, - &gap_array_marker_description }, - { XD_STRUCT_PTR, offsetof (Extent_List_Marker, next), 1, - &extent_list_marker_description }, + { XD_BLOCK_PTR, offsetof (Extent_List_Marker, m), 1, + { &gap_array_marker_description } }, + { XD_BLOCK_PTR, offsetof (Extent_List_Marker, next), 1, + { &extent_list_marker_description } }, { XD_END } }; @@ -1080,9 +1072,12 @@ }; static const struct memory_description extent_list_description_1[] = { - { XD_STRUCT_PTR, offsetof (Extent_List, start), 1, &lispobj_gap_array_description }, - { XD_STRUCT_PTR, offsetof (Extent_List, end), 1, &lispobj_gap_array_description, XD_FLAG_NO_KKCC }, - { XD_STRUCT_PTR, offsetof (Extent_List, markers), 1, &extent_list_marker_description, XD_FLAG_NO_KKCC }, + { XD_BLOCK_PTR, offsetof (Extent_List, start), 1, + { &lispobj_gap_array_description } }, + { XD_BLOCK_PTR, offsetof (Extent_List, end), 1, + { &lispobj_gap_array_description }, XD_FLAG_NO_KKCC }, + { XD_BLOCK_PTR, offsetof (Extent_List, markers), 1, + { &extent_list_marker_description }, XD_FLAG_NO_KKCC }, { XD_END } }; @@ -1092,7 +1087,8 @@ }; static const struct memory_description stack_of_extents_description_1[] = { - { XD_STRUCT_PTR, offsetof (Stack_Of_Extents, extents), 1, &extent_list_description }, + { XD_BLOCK_PTR, offsetof (Stack_Of_Extents, extents), 1, + { &extent_list_description } }, { XD_END } }; @@ -1102,10 +1098,10 @@ }; static const struct memory_description extent_info_description [] = { - { XD_STRUCT_PTR, offsetof (struct extent_info, extents), 1, - &extent_list_description }, - { XD_STRUCT_PTR, offsetof (struct extent_info, soe), 1, - &stack_of_extents_description, XD_FLAG_NO_KKCC }, + { XD_BLOCK_PTR, offsetof (struct extent_info, extents), 1, + { &extent_list_description } }, + { XD_BLOCK_PTR, offsetof (struct extent_info, soe), 1, + { &stack_of_extents_description }, XD_FLAG_NO_KKCC }, { XD_END } }; @@ -2028,7 +2024,7 @@ case ME_ALL_EXTENTS_OPEN: start_open = 1, end_open = 1; break; case ME_ALL_EXTENTS_CLOSED_OPEN: start_open = 0, end_open = 1; break; case ME_ALL_EXTENTS_OPEN_CLOSED: start_open = 1, end_open = 0; break; - default: abort(); return 0; + default: ABORT(); return 0; } start = buffer_or_string_bytexpos_to_startind (obj, from, @@ -2064,7 +2060,7 @@ retval = (start <= exs && exs <= end) || (start <= exe && exe <= end); break; default: - abort(); return 0; + ABORT(); return 0; } return flags & ME_NEGATE_IN_REGION ? !retval : retval; } @@ -3169,7 +3165,7 @@ Lisp_Object obj2 = Qnil; /* Destroyed extents have 't' in the object field, causing - extent_object() to abort (maybe). */ + extent_object() to ABORT (maybe). */ if (EXTENT_LIVE_P (XEXTENT (obj))) obj2 = extent_object (XEXTENT (obj)); @@ -4789,10 +4785,10 @@ #ifdef ERROR_CHECK_EXTENTS if (extent_start (extent) > indice && extent_start (extent) < indice + closure->length) - abort (); + ABORT (); if (extent_end (extent) > indice && extent_end (extent) < indice + closure->length) - abort (); + ABORT (); #endif /* The extent-adjustment code adjusted the extent's endpoints as if @@ -4977,11 +4973,10 @@ call3 (hook, exobj, startobj, endobj); else { - Lisp_Object tail; - EXTERNAL_LIST_LOOP (tail, hook) + EXTERNAL_LIST_LOOP_2 (elt, hook) /* #### Shouldn't this perform the same Fset_buffer() check as above? */ - call3 (XCAR (tail), exobj, startobj, endobj); + call3 (elt, exobj, startobj, endobj); } return 0; } @@ -5092,13 +5087,15 @@ } thecons = Vextent_face_reusable_list; - EXTERNAL_LIST_LOOP (cons, list) - { - Lisp_Object face = Fget_face (XCAR (cons)); - - XCAR (thecons) = Fface_name (face); - thecons = XCDR (thecons); - } + { + EXTERNAL_LIST_LOOP_2 (face, list) + { + face = Fget_face (face); + + XCAR (thecons) = Fface_name (face); + thecons = XCDR (thecons); + } + } list = Fgethash (Vextent_face_reusable_list, Vextent_face_memoize_hash_table, Qnil); @@ -5289,7 +5286,7 @@ case GL_INSIDE_MARGIN: return Qinside_margin; case GL_WHITESPACE: return Qwhitespace; default: - abort (); + ABORT (); return Qnil; /* unreached */ } } @@ -7088,21 +7085,28 @@ } Bytexpos -next_single_property_change (Bytexpos pos, Lisp_Object prop, - Lisp_Object object, Bytexpos limit) +next_previous_single_property_change (Bytexpos pos, Lisp_Object prop, + Lisp_Object object, Bytexpos limit, + Boolint next, Boolint text_props_only) { Lisp_Object extent, value; int limit_was_nil; - + enum extent_at_flag at_flag = next ? EXTENT_AT_AFTER : EXTENT_AT_BEFORE; if (limit < 0) { - limit = buffer_or_string_accessible_end_byte (object); + limit = (next ? buffer_or_string_accessible_end_byte : + buffer_or_string_accessible_begin_byte) (object); limit_was_nil = 1; } else limit_was_nil = 0; - extent = extent_at (pos, object, prop, 0, EXTENT_AT_AFTER, 0); + /* Retrieve initial property value to compare against */ + extent = extent_at (pos, object, prop, 0, at_flag, 0); + /* If we only want text-prop extents, ignore all others */ + if (text_props_only && !NILP (extent) && + NILP (Fextent_property (extent, Qtext_prop, Qnil))) + extent = Qnil; if (!NILP (extent)) value = Fextent_property (extent, prop, Qnil); else @@ -7110,10 +7114,15 @@ while (1) { - pos = extent_find_end_of_run (object, pos, 1); - if (pos >= limit) - break; /* property is the same all the way to the end */ - extent = extent_at (pos, object, prop, 0, EXTENT_AT_AFTER, 0); + pos = (next ? extent_find_end_of_run : extent_find_beginning_of_run) + (object, pos, 1); + if (next ? pos >= limit : pos <= limit) + break; /* property is the same all the way to the beginning/end */ + extent = extent_at (pos, object, prop, 0, at_flag, 0); + /* If we only want text-prop extents, ignore all others */ + if (text_props_only && !NILP (extent) && + NILP (Fextent_property (extent, Qtext_prop, Qnil))) + extent = Qnil; if ((NILP (extent) && !NILP (value)) || (!NILP (extent) && !EQ (value, Fextent_property (extent, prop, Qnil)))) @@ -7126,43 +7135,24 @@ return limit; } -Bytexpos -previous_single_property_change (Bytexpos pos, Lisp_Object prop, - Lisp_Object object, Bytexpos limit) +static Lisp_Object +next_previous_single_property_change_fn (Lisp_Object pos, Lisp_Object prop, + Lisp_Object object, Lisp_Object limit, + Boolint next, Boolint text_props_only) { - Lisp_Object extent, value; - int limit_was_nil; - - if (limit < 0) - { - limit = buffer_or_string_accessible_begin_byte (object); - limit_was_nil = 1; - } - else - limit_was_nil = 0; - - extent = extent_at (pos, object, prop, 0, EXTENT_AT_BEFORE, 0); - if (!NILP (extent)) - value = Fextent_property (extent, prop, Qnil); - else - value = Qnil; + Bytexpos xpos; + Bytexpos blim; - while (1) - { - pos = extent_find_beginning_of_run (object, pos, 1); - if (pos <= limit) - break; /* property is the same all the way to the end */ - extent = extent_at (pos, object, prop, 0, EXTENT_AT_BEFORE, 0); - if ((NILP (extent) && !NILP (value)) || - (!NILP (extent) && !EQ (value, - Fextent_property (extent, prop, Qnil)))) - return pos; - } + object = decode_buffer_or_string (object); + xpos = get_buffer_or_string_pos_byte (object, pos, 0); + blim = !NILP (limit) ? get_buffer_or_string_pos_byte (object, limit, 0) : -1; + blim = next_previous_single_property_change (xpos, prop, object, blim, + next, text_props_only); - if (limit_was_nil) - return -1; + if (blim < 0) + return Qnil; else - return limit; + return make_int (buffer_or_string_bytexpos_to_charxpos (object, blim)); } DEFUN ("next-single-property-change", Fnext_single_property_change, @@ -7182,22 +7172,14 @@ a particular character, it is undefined which value is considered to be the value of PROP. (Note that this situation will not happen if you always use the text-property primitives.) + +This function looks only at extents created using the text-property primitives. +To look at all extents, use `next-single-char-property-change'. */ (pos, prop, object, limit)) { - Bytexpos xpos; - Bytexpos blim; - - object = decode_buffer_or_string (object); - xpos = get_buffer_or_string_pos_byte (object, pos, 0); - blim = !NILP (limit) ? get_buffer_or_string_pos_byte (object, limit, 0) : -1; - - blim = next_single_property_change (xpos, prop, object, blim); - - if (blim < 0) - return Qnil; - else - return make_int (buffer_or_string_bytexpos_to_charxpos (object, blim)); + return next_previous_single_property_change_fn (pos, prop, object, limit, + 1, 1); } DEFUN ("previous-single-property-change", Fprevious_single_property_change, @@ -7217,22 +7199,69 @@ a particular character, it is undefined which value is considered to be the value of PROP. (Note that this situation will not happen if you always use the text-property primitives.) + +This function looks only at extents created using the text-property primitives. +To look at all extents, use `next-single-char-property-change'. */ (pos, prop, object, limit)) { - Bytexpos xpos; - Bytexpos blim; + return next_previous_single_property_change_fn (pos, prop, object, limit, + 0, 1); +} - object = decode_buffer_or_string (object); - xpos = get_buffer_or_string_pos_byte (object, pos, 0); - blim = !NILP (limit) ? get_buffer_or_string_pos_byte (object, limit, 0) : -1; +DEFUN ("next-single-char-property-change", Fnext_single_char_property_change, + 2, 4, 0, /* +Return the position of next property change for a specific property. +Scans characters forward from POS till it finds a change in the PROP + property, then returns the position of the change. The optional third + argument OBJECT is the buffer or string to scan (defaults to the current + buffer). +The property values are compared with `eq'. +Return nil if the property is constant all the way to the end of OBJECT. +If the value is non-nil, it is a position greater than POS, never equal. - blim = previous_single_property_change (xpos, prop, object, blim); +If the optional fourth argument LIMIT is non-nil, don't search + past position LIMIT; return LIMIT if nothing is found before LIMIT. +If two or more extents with conflicting non-nil values for PROP overlap + a particular character, it is undefined which value is considered to be + the value of PROP. (Note that this situation will not happen if you always + use the text-property primitives.) - if (blim < 0) - return Qnil; - else - return make_int (buffer_or_string_bytexpos_to_charxpos (object, blim)); +This function looks at all extents. To look at only extents created using the +text-property primitives, use `next-single-char-property-change'. +*/ + (pos, prop, object, limit)) +{ + return next_previous_single_property_change_fn (pos, prop, object, limit, + 1, 0); +} + +DEFUN ("previous-single-char-property-change", + Fprevious_single_char_property_change, + 2, 4, 0, /* +Return the position of next property change for a specific property. +Scans characters backward from POS till it finds a change in the PROP + property, then returns the position of the change. The optional third + argument OBJECT is the buffer or string to scan (defaults to the current + buffer). +The property values are compared with `eq'. +Return nil if the property is constant all the way to the start of OBJECT. +If the value is non-nil, it is a position less than POS, never equal. + +If the optional fourth argument LIMIT is non-nil, don't search back + past position LIMIT; return LIMIT if nothing is found until LIMIT. +If two or more extents with conflicting non-nil values for PROP overlap + a particular character, it is undefined which value is considered to be + the value of PROP. (Note that this situation will not happen if you always + use the text-property primitives.) + +This function looks at all extents. To look at only extents created using the +text-property primitives, use `next-single-char-property-change'. +*/ + (pos, prop, object, limit)) +{ + return next_previous_single_property_change_fn (pos, prop, object, limit, + 0, 0); } #ifdef MEMORY_USAGE_STATS @@ -7371,6 +7400,8 @@ DEFSUBR (Ftext_prop_extent_paste_function); DEFSUBR (Fnext_single_property_change); DEFSUBR (Fprevious_single_property_change); + DEFSUBR (Fnext_single_char_property_change); + DEFSUBR (Fprevious_single_char_property_change); } void @@ -7392,8 +7423,6 @@ void vars_of_extents (void) { - reinit_vars_of_extents (); - DEFVAR_INT ("mouse-highlight-priority", &mouse_highlight_priority /* The priority to use for the mouse-highlighting pseudo-extent that is used to highlight extents with the `mouse-face' attribute set. diff --text -u 'xemacs-21.5.18/src/extents.h' 'xemacs-21.5.19/src/extents.h' Index: ./src/extents.h --- ./src/extents.h Fri Jun 21 06:18:30 2002 +++ ./src/extents.h Wed Jan 26 14:11:12 2005 @@ -110,7 +110,7 @@ EXFUN (Fmake_extent, 3); EXFUN (Fnext_extent_change, 2); EXFUN (Fprevious_extent_change, 2); -EXFUN (Fprevious_single_property_change, 4); +EXFUN (Fprevious_single_char_property_change, 4); EXFUN (Fset_extent_endpoints, 4); EXFUN (Fset_extent_parent, 2); EXFUN (Fset_extent_property, 3); @@ -125,10 +125,11 @@ Bytexpos extent_endpoint_byte (EXTENT extent, int endp); Charxpos extent_endpoint_char (EXTENT extent, int endp); -Bytexpos next_single_property_change (Bytexpos pos, Lisp_Object prop, - Lisp_Object object, Bytexpos limit); -Bytexpos previous_single_property_change (Bytexpos pos, Lisp_Object prop, - Lisp_Object object, Bytexpos limit); +Bytexpos next_previous_single_property_change (Bytexpos pos, Lisp_Object prop, + Lisp_Object object, + Bytexpos limit, + Boolint next, + Boolint text_props_only); Lisp_Object get_char_property (Bytexpos position, Lisp_Object prop, Lisp_Object object, enum extent_at_flag fl, int text_props_only); diff --text -u 'xemacs-21.5.18/src/faces.c' 'xemacs-21.5.19/src/faces.c' Index: ./src/faces.c --- ./src/faces.c Tue Sep 21 04:19:42 2004 +++ ./src/faces.c Tue Jan 25 08:33:54 2005 @@ -318,7 +318,7 @@ if (EQ (keyw, Qname)) name_seen = 1; else - abort (); + ABORT (); } if (!name_seen) @@ -1974,7 +1974,7 @@ #if defined (HAVE_X_WINDOWS) || defined (HAVE_GTK) - const Char_ASCII *fonts[] = + const Ascbyte *fonts[] = { /************** ISO-8859 fonts *************/ @@ -2104,7 +2104,7 @@ "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", "*" }; - const Char_ASCII **fontptr; + const Ascbyte **fontptr; #ifdef HAVE_X_WINDOWS for (fontptr = fonts + countof(fonts) - 1; fontptr >= fonts; fontptr--) @@ -2126,13 +2126,13 @@ #ifdef HAVE_MS_WINDOWS { - const Char_ASCII *mswfonts[] = + const Ascbyte *mswfonts[] = { "Courier New:Regular:10::", "Courier:Regular:10::", ":Regular:10::" }; - const Char_ASCII **mswfontptr; + const Ascbyte **mswfontptr; for (mswfontptr = mswfonts + countof (mswfonts) - 1; mswfontptr >= mswfonts; mswfontptr--) diff --text -u 'xemacs-21.5.18/src/file-coding.c' 'xemacs-21.5.19/src/file-coding.c' Index: ./src/file-coding.c --- ./src/file-coding.c Wed Sep 22 11:06:46 2004 +++ ./src/file-coding.c Fri Feb 4 01:14:06 2005 @@ -69,359 +69,6 @@ Removed the conditionals. */ -/* sjt sez: - -There should be no elementary coding systems in the Lisp API, only chains. -Chains should be declared, not computed, as a sequence of coding formats. -(Probably the internal representation can be a vector for efficiency but -programmers would probably rather work with lists.) A stream has a token -type. Most streams are octet streams. Text is a stream of characters (in -_internal_ format; a file on disk is not text!) An octet-stream has no -implicit semantics, so its format must always be specified. The only type -currently having semantics is characters. This means that the chain [euc-jp --> internal -> shift_jis) may be specified (euc-jp, shift_jis), and if no -euc-jp -> shift_jis converter is available, then the chain is automatically -constructed. (N.B. I f we have fixed width buffers in the future, then we -could have ASCII -> 8-bit char -> 16-bit char -> ISO-2022-JP (with escape -sequences). - -EOL handling is a char <-> char coding. It should not be part of another -coding system except as a convenience for users. For text coding, -automatically insert EOL handlers between char <-> octet boundaries. -*/ - -/* Comments about future work - ------------------------------------------------------------------- - ABOUT DETECTION ------------------------------------------------------------------- - - however, in general the detection code has major problems and needs lots - of work: - - -- instead of merely "yes" or "no" for particular categories, we need a - more flexible system, with various levels of likelihood. Currently - I've created a system with six levels, as follows: - - [see file-coding.h] - - Let's consider what this might mean for an ASCII text detector. (In - order to have accurate detection, especially given the iteration I - proposed below, we need active detectors for *all* types of data we - might reasonably encounter, such as ASCII text files, binary files, - and possibly other sorts of ASCII files, and not assume that simply - "falling back to no detection" will work at all well.) - - An ASCII text detector DOES NOT report ASCII text as level 0, since - that's what the detector is looking for. Such a detector ideally - wants all bytes in the range 0x20 - 0x7E (no high bytes!), except for - whitespace control chars and perhaps a few others; LF, CR, or CRLF - sequences at regular intervals (where "regular" might mean an average - < 100 chars and 99% < 300 for code and other stuff of the "text file - w/line breaks" variety, but for the "text file w/o line breaks" - variety, excluding blank lines, averages could easily be 600 or more - with 2000-3000 char "lines" not so uncommon); similar statistical - variance between odds and evens (not Unicode); frequent occurrences of - the space character; letters more common than non-letters; etc. Also - checking for too little variability between frequencies of characters - and for exclusion of particular characters based on character ranges - can catch ASCII encodings like base-64, UUEncode, UTF-7, etc. - Granted, this doesn't even apply to everything called "ASCII", and we - could potentially distinguish off ASCII for code, ASCII for text, - etc. as separate categories. However, it does give us a lot to work - off of, in deciding what likelihood to choose -- and it shows there's - in fact a lot of detectable patterns to look for even in something - seemingly so generic as ASCII. The detector would report most text - files in level 1 or level 2. EUC encodings, Shift-JIS, etc. probably - go to level -1 because they also pass the EOL test and all other tests - for the ASCII part of the text, but have lots of high bytes, which in - essence turn them into binary. Aberrant text files like something in - BASE64 encoding might get placed in level 0, because they pass most - tests but fail dramatically the frequency test; but they should not be - reported as any lower, because that would cause explicit prompting, - and the user should be able any valid text file without prompting. - The escape sequences and the base-64-type checks might send 7-bit - iso2022 to 0, but probably not -1, for similar reasons. - - -- The assumed algorithm for the above detection levels is to in essence - sort categories first by detection level and then by priority. - Perhaps, however, we would want smarter algorithms, or at least - something user-controllable -- in particular, when (other than no - category at level 0 or greater) do we prompt the user to pick a - category? - - -- Improvements in how the detection algorithm works: we want to handle - lots of different ways something could be encoded, including multiple - stacked encodings. trying to specify a series of detection levels - (check for base64 first, then check for gzip, then check for an i18n - decoding, then for crlf) won't generally work. for example, what - about the same encoding appearing more than once? for example, take - euc-jp, base64'd, then gzip'd, then base64'd again: this could well - happen, and you could specify the encodings specifically as - base64|gzip|base64|euc-jp, but we'd like to autodetect it without - worrying about exactly what order these things appear in. we should - allow for iterating over detection/decoding cycles until we reach - some maximum (we got stuck in a loop, due to incorrect category - tables or detection algorithms), have no reported detection levels - over -1, or we end up with no change after a decoding pass (i.e. the - coding system associated with a chosen category was `no-conversion' - or something equivalent). it might make sense to divide things into - two phases (internal and external), where the internal phase has a - separate category list and would probably mostly end up handling EOL - detection; but the i think about it, the more i disagree. with - properly written detectors, and properly organized tables (in - general, those decodings that are more "distinctive" and thus - detectable with greater certainty go lower on the list), we shouldn't - need two phases. for example, let's say the example above was also - in CRLF format. The EOL detector (which really detects *plain text* - with a particular EOL type) would return at most level 0 for all - results until the text file is reached, whereas the base64, gzip or - euc-jp decoders will return higher. Once the text file is reached, - the EOL detector will return 0 or higher for the CRLF encoding, and - all other detectors will return 0 or lower; thus, we will successfully - proceed through CRLF decoding, or at worst prompt the user. (The only - external-vs-internal distinction that might make sense here is to - favor coding systems of the correct source type over those that - require conversion between external and internal; if done right, this - could allow the CRLF detector to return level 1 for all CRLF-encoded - text files, even those that look like Base-64 or similar encoding, so - that CRLF encoding will always get decoded without prompting, but not - interfere with other decoders. On the other hand, this - external-vs-internal distinction may not matter at all -- with - automatic internal-external conversion, CRLF decoding can occur - before or after decoding of euc-jp, base64, iso2022, or similar, - without any difference in the final results.) - - #### What are we trying to say? In base64, the CRLF decoding before - base64 decoding is irrelevant, they will be thrown out as whitespace - is not significant in base64. - - [sjt considers all of this to be rather bogus. Ideas like "greater - certainty" and "distinctive" can and should be quantified. The issue - of proper table organization should be a question of optimization.] - - [sjt wonders if it might not be a good idea to use Unicode's newline - character as the internal representation so that (for non-Unicode - coding systems) we can catch EOL bugs on Unix too.] - - -- There need to be two priority lists and two - category->coding-system lists. Once is general, the other - category->langenv-specific. The user sets the former, the langenv - category->the latter. The langenv-specific entries take precedence - category->over the others. This works similarly to the - category->category->Unicode charset priority list. - - -- The simple list of coding categories per detectors is not enough. - Instead of coding categories, we need parameters. For example, - Unicode might have separate detectors for UTF-8, UTF-7, UTF-16, - and perhaps UCS-4; or UTF-16/UCS-4 would be one detection type. - UTF-16 would have parameters such as "little-endian" and "needs BOM", - and possibly another one like "collapse/expand/leave alone composite - sequences" once we add this support. Usually these parameters - correspond directly to a coding system parameter. Different - likelihood values can be specified for each parameter as well as for - the detection type as a whole. The user can specify particular - coding systems for a particular combination of detection type and - parameters, or can give "default parameters" associated with a - detection type. In the latter case, we create a new coding system as - necessary that corresponds to the detected type and parameters. - - -- a better means of presentation. rather than just coming up - with the new file decoded according to the detected coding - system, allow the user to browse through the file and - conveniently reject it if it looks wrong; then detection - starts again, but with that possibility removed. in cases where - certainty is low and thus more than one possibility is presented, - the user can browse each one and select one or reject them all. - - -- fail-safe: even after the user has made a choice, if they - later on realize they have the wrong coding system, they can - go back, and we've squirreled away the original data so they - can start the process over. this may be tricky. - - -- using a larger buffer for detection. we use just a small - piece, which can give quite random results. we may need to - buffer up all the data we look through because we can't - necessarily rewind. the idea is we proceed until we get a - result that's at least at a certain level of certainty - (e.g. "probable") or we reached a maximum limit of how much - we want to buffer. - - -- dealing with interactive systems. we might need to go ahead - and present the data before we've finished detection, and - then re-decode it, perhaps multiple times, as we get better - detection results. - - -- Clearly some of these are more important than others. at the - very least, the "better means of presentation" should be - implemented as soon as possible, along with a very simple means - of fail-safe whenever the data is readibly available, e.g. it's - coming from a file, which is the most common scenario. - ---ben [at least that's what sjt thinks] - -***** - -While this is clearly something of an improvement over earlier designs, -it doesn't deal with the most important issue: to do better than categories -(which in the medium term is mostly going to mean "which flavor of Unicode -is this?"), we need to look at statistical behavior rather than ruling out -categories via presence of specific sequences. This means the stream -processor should - - (1) keep octet distributions (octet, 2-, 3-, 4- octet sequences) - (2) in some kind of compressed form - (3) look for "skip features" (eg, characteristic behavior of leading - bytes for UTF-7, UTF-8, UTF-16, Mule code) - (4) pick up certain "simple" regexps - (5) provide "triggers" to determine when statistical detectors should be - invoked, such as octet count - (6) and "magic" like Unicode signatures or file(1) magic. - ---sjt - - ------------------------------------------------------------------- - 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.) - --------------------------------------------------------------------------- -ABOUT PDUMP, UNICODE, AND RUNNING XEMACS FROM A DIRECTORY WITH WEIRD CHARS --------------------------------------------------------------------------- - --- 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. - --------------------------------------------------------------------------- - HANDLING WRITING A FILE SAFELY, WITHOUT DATA LOSS --------------------------------------------------------------------------- - - -- 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" coding systems can perhaps - be presented at the end, which will lose only a few characters - and are perhaps what the users were looking for. - - [sjt sez this whole step is a crock. If a universal coding system - is unacceptable, the user had better know what he/she is doing, - and explicitly specify a lossy encoding. - In principle, we can simply check for characters being writable as - we go along. Eg, via an "unrepresentable character handler." We - still have the buffer contents. If we can't successfully save, - then ask the user what to do. (Do we ever simply destroy previous - file version before completing a write?)] - - 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. - - [sjt -- something is very confused, here; safe charsets should be - defined as those charsets all of whose characters can be encoded.] - - 3. same thing (error checking, list of alternatives, etc.) needs - to happen when reading! all of this will be a lot of work! - - - --ben - - I don't much like Ben's scheme. First, this isn't an issue of I/O, - it's a coding issue. It can happen in many places, not just on stream - I/O. Error checking should take place on all translations. Second, - the two-pass algorithm should be avoided if possible. In some cases - (eg, output to a tty) we won't be able to go back and change the - previously output data. Third, the whole idea of having a buffer full - of arbitrary characters which we're going to somehow shoehorn into a - file based on some twit user's less than informed idea of a coding system - is kind of laughable from the start. If we're going to say that a buffer - has a coding system, shouldn't we enforce restrictions on what you can - put into it? Fourth, what's the point of having safe charsets if some - of the characters in them are unsafe? Fifth, what makes you think we're - going to have a list of charsets? It seems to me that there might be - reasons to have user-defined charsets (eg, "German" vs "French" subsets - of ISO 8859/15). Sixth, the idea of having language environment determine - precedence doesn't seem very useful to me. Users who are working with a - language that corresponds to the language environment are not going to - run into safe charsets problems. It's users who are outside of their - usual language environment who run into trouble. Also, the reason for - specifying anything other than a universal coding system is normally - restrictions imposed by other users or applications. Seventh, the - statistical feedback isn't terribly useful. Users rarely "want" a - coding system, they want their file saved in a useful way. We could - add a FORCE argument to conversions for those who really want a specific - coding system. But mostly, a user might want to edit out a few unsafe - characters. So (up to some maximum) we should keep a list of unsafe - text positions, and provide a convenient function for traversing them. - - --sjt -*/ - #include <config.h> #include "lisp.h" @@ -459,7 +106,8 @@ static coding_system_type_entry_dynarr *the_coding_system_type_entry_dynarr; static const struct memory_description cste_description_1[] = { - { XD_STRUCT_PTR, offsetof (coding_system_type_entry, meths), 1, &coding_system_methods_description }, + { XD_BLOCK_PTR, offsetof (coding_system_type_entry, meths), 1, + { &coding_system_methods_description } }, { XD_END } }; @@ -523,8 +171,8 @@ static const struct memory_description struct_detector_description_1[] = { - { XD_STRUCT_PTR, offsetof (struct detector, cats), 1, - &detector_category_dynarr_description }, + { XD_BLOCK_PTR, offsetof (struct detector, cats), 1, + { &detector_category_dynarr_description } }, { XD_END } }; @@ -698,14 +346,14 @@ static const struct memory_description coding_system_description[] = { - { XD_STRUCT_PTR, offsetof (Lisp_Coding_System, methods), 1, - &coding_system_methods_description }, + { XD_BLOCK_PTR, offsetof (Lisp_Coding_System, methods), 1, + { &coding_system_methods_description } }, #define MARKED_SLOT(x) { XD_LISP_OBJECT, offsetof (Lisp_Coding_System, x) }, #define MARKED_SLOT_ARRAY(slot, size) \ { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Coding_System, slot), size }, #include "coding-system-slots.h" - { XD_STRUCT_ARRAY, offsetof (Lisp_Coding_System, data), 1, - coding_system_extra_description_map }, + { XD_BLOCK_ARRAY, offsetof (Lisp_Coding_System, data), 1, + { coding_system_extra_description_map } }, { XD_END } }; @@ -1083,7 +731,7 @@ { switch (type) { - default: abort (); + default: ABORT (); case EOL_LF: return Qlf; case EOL_CRLF: return Qcrlf; case EOL_CR: return Qcr; @@ -1093,8 +741,8 @@ struct subsidiary_type { - Char_ASCII *extension; - Char_ASCII *mnemonic_ext; + Ascbyte *extension; + Ascbyte *mnemonic_ext; enum eol_type eol; }; @@ -1108,7 +756,7 @@ setup_eol_coding_systems (Lisp_Object codesys) { int len = XSTRING_LENGTH (XSYMBOL (XCODING_SYSTEM_NAME (codesys))->name); - Ibyte *codesys_name = (Ibyte *) ALLOCA (len + 7); + Ibyte *codesys_name = alloca_ibytes (len + 7); int mlen = -1; Ibyte *codesys_mnemonic = 0; Lisp_Object codesys_name_sym, sub_codesys; @@ -1120,7 +768,7 @@ if (STRINGP (XCODING_SYSTEM_MNEMONIC (codesys))) { mlen = XSTRING_LENGTH (XCODING_SYSTEM_MNEMONIC (codesys)); - codesys_mnemonic = (Ibyte *) ALLOCA (mlen + 7); + codesys_mnemonic = alloca_ibytes (mlen + 7); memcpy (codesys_mnemonic, XSTRING_DATA (XCODING_SYSTEM_MNEMONIC (codesys)), mlen); } @@ -1140,14 +788,14 @@ for (i = 0; i < countof (coding_subsidiary_list); i++) { - Char_ASCII *extension = coding_subsidiary_list[i].extension; - Char_ASCII *mnemonic_ext = coding_subsidiary_list[i].mnemonic_ext; + Ascbyte *extension = coding_subsidiary_list[i].extension; + Ascbyte *mnemonic_ext = coding_subsidiary_list[i].mnemonic_ext; enum eol_type eol = coding_subsidiary_list[i].eol; - qxestrcpy_c (codesys_name + len, extension); + qxestrcpy_ascii (codesys_name + len, extension); codesys_name_sym = intern_int (codesys_name); if (mlen != -1) - qxestrcpy_c (codesys_mnemonic + mlen, mnemonic_ext); + qxestrcpy_ascii (codesys_mnemonic + mlen, mnemonic_ext); sub_codesys = Fcopy_coding_system (codesys, codesys_name_sym); if (mlen != -1) @@ -1217,7 +865,7 @@ */ static Lisp_Object -make_coding_system_1 (Lisp_Object name_or_existing, Char_ASCII *prefix, +make_coding_system_1 (Lisp_Object name_or_existing, Ascbyte *prefix, Lisp_Object type, Lisp_Object description, Lisp_Object props) { @@ -1384,7 +1032,7 @@ } Lisp_Object -make_internal_coding_system (Lisp_Object existing, Char_ASCII *prefix, +make_internal_coding_system (Lisp_Object existing, Ascbyte *prefix, Lisp_Object type, Lisp_Object description, Lisp_Object props) { @@ -1932,7 +1580,7 @@ case EOL_LF: new_coding_system = CODING_SYSTEM_EOL_LF (cs); break; case EOL_CR: new_coding_system = CODING_SYSTEM_EOL_CR (cs); break; case EOL_CRLF: new_coding_system = CODING_SYSTEM_EOL_CRLF (cs); break; - default: abort (); return Qnil; + default: ABORT (); return Qnil; } return NILP (new_coding_system) ? coding_system : new_coding_system; @@ -2080,8 +1728,10 @@ extern const struct sized_memory_description undecided_coding_stream_description; static const struct memory_description coding_stream_data_description_1 []= { - { XD_STRUCT_PTR, chain_coding_system, 1, &chain_coding_stream_description}, - { XD_STRUCT_PTR, undecided_coding_system, 1, &undecided_coding_stream_description}, + { XD_BLOCK_PTR, chain_coding_system, 1, + { &chain_coding_stream_description } }, + { XD_BLOCK_PTR, undecided_coding_system, 1, + { &undecided_coding_stream_description } }, { XD_END } }; @@ -2095,7 +1745,7 @@ { XD_LISP_OBJECT, offsetof (struct coding_stream, codesys) }, { XD_LISP_OBJECT, offsetof (struct coding_stream, other_end) }, { XD_UNION, offsetof (struct coding_stream, data), - XD_INDIRECT (0, 0), &coding_stream_data_description }, + XD_INDIRECT (0, 0), { &coding_stream_data_description } }, { XD_END } }; @@ -2581,49 +2231,14 @@ for this] ------> [BUFFER] */ - /* Of course, this is just horrible. BYTE<->CHAR should only be available - to I/O routines. It should not be visible to Mule proper. - A comment on the implementation. Hrvoje and Kyle worry about the - inefficiency of repeated copying among buffers that chained coding - systems entail. But this may not be as time inefficient as it appears - in the Mule ("house rules") context. The issue is how do you do chain - coding systems without copying? In theory you could have - - IChar external_to_raw (ExtChar *cp, State *s); - IChar decode_utf16 (IChar c, State *s); - IChar decode_crlf (ExtChar *cp, State *s); - - typedef Ichar (*Converter[]) (Ichar, State*); - - Converter utf16[2] = { &decode_utf16, &decode_crlf }; - - void convert (ExtChar *inbuf, IChar *outbuf, Converter cvtr) - { - int i; - ExtChar c; - State s; - - while (c = external_to_raw (*inbuf++, &s)) - { - for (i = 0; i < sizeof(cvtr)/sizeof(Converter); ++i) - if (s.ready) - c = (*cvtr[i]) (c, &s); - } - if (s.ready) - *outbuf++ = c; - } - - But this is a lot of function calls; what Ben is doing is basically - reducing this to one call per buffer-full. The only way to avoid this - is to hardcode all the "interesting" coding systems, maybe using - inline or macros to give structure. But this is still a huge amount - of work, and code. - - One advantage to the call-per-char approach is that we might be able - to do something about the marker/extent destruction that coding - normally entails. - */ + /* #### See comment + + EFFICIENCY OF CODING CONVERSION WITH MULTIPLE COPIES/CHAINS + + in text.c. + */ + while (1) { char tempbuf[1024]; /* some random amount */ @@ -2717,8 +2332,8 @@ static const struct memory_description chain_coding_system_description[] = { { XD_INT, offsetof (struct chain_coding_system, count) }, - { XD_STRUCT_PTR, offsetof (struct chain_coding_system, chain), - XD_INDIRECT (0, 0), &lisp_object_description }, + { XD_BLOCK_PTR, offsetof (struct chain_coding_system, chain), + XD_INDIRECT (0, 0), { &lisp_object_description } }, { XD_LISP_OBJECT, offsetof (struct chain_coding_system, canonicalize_after_coding) }, { XD_END } @@ -2726,8 +2341,8 @@ static const struct memory_description chain_coding_stream_description_1 [] = { { XD_INT, offsetof (struct chain_coding_stream, lstream_count) }, - { XD_STRUCT_PTR, offsetof (struct chain_coding_stream, lstreams), - XD_INDIRECT (0, 0), &lisp_object_description }, + { XD_BLOCK_PTR, offsetof (struct chain_coding_stream, lstreams), + XD_INDIRECT (0, 0), { &lisp_object_description } }, { XD_END } }; @@ -2985,26 +2600,29 @@ { if (EQ (key, Qchain)) { - Lisp_Object tail; Lisp_Object *cslist; int count = 0; int i; - EXTERNAL_LIST_LOOP (tail, value) - { - Fget_coding_system (XCAR (tail)); - count++; - } + { + EXTERNAL_LIST_LOOP_2 (elt, value) + { + Fget_coding_system (elt); + count++; + } + } cslist = xnew_array (Lisp_Object, count); XCODING_SYSTEM_CHAIN_CHAIN (codesys) = cslist; count = 0; - EXTERNAL_LIST_LOOP (tail, value) - { - cslist[count] = Fget_coding_system (XCAR (tail)); - count++; - } + { + EXTERNAL_LIST_LOOP_2 (elt, value) + { + cslist[count] = Fget_coding_system (elt); + count++; + } + } XCODING_SYSTEM_CHAIN_COUNT (codesys) = count; @@ -3064,7 +2682,7 @@ case 3: return DECODES_CHARACTER_TO_CHARACTER; } - abort (); + ABORT (); return DECODES_BYTE_TO_BYTE; } @@ -3221,7 +2839,7 @@ data->subtype == EOL_CRLF ? "crlf" : data->subtype == EOL_CR ? "cr" : data->subtype == EOL_AUTODETECT ? "nil" : - (abort(), "")); + (ABORT(), "")); } static enum source_sink_type @@ -3269,7 +2887,7 @@ case EOL_CRLF: return Qcrlf; case EOL_CR: return Qcr; case EOL_AUTODETECT: return Qnil; - default: abort (); + default: ABORT (); } } @@ -3421,7 +3039,7 @@ case EOL_CRLF: return Fget_coding_system (Qconvert_eol_crlf); case EOL_CR: return Fget_coding_system (Qconvert_eol_cr); case EOL_AUTODETECT: return str->codesys; - default: abort (); return Qnil; + default: ABORT (); return Qnil; } } @@ -3469,8 +3087,8 @@ static const struct memory_description undecided_coding_stream_description_1 [] = { { XD_LISP_OBJECT, offsetof (struct undecided_coding_stream, actual) }, - { XD_STRUCT_ARRAY, offsetof (struct undecided_coding_stream, c), - 1, &chain_coding_stream_description }, + { XD_BLOCK_ARRAY, offsetof (struct undecided_coding_stream, c), + 1, { &chain_coding_stream_description } }, { XD_END } }; @@ -3641,7 +3259,7 @@ return Dynarr_at (cats, j).sym; } - abort (); + ABORT (); return Qnil; /* (usually) not reached */ } @@ -3662,7 +3280,7 @@ #undef FROB } - abort (); + ABORT (); return Qnil; /* (usually) not reached */ } @@ -3926,10 +3544,10 @@ blanks). If found, return it, otherwise nil. */ static Lisp_Object -snarf_coding_system (const Ibyte *p, Bytecount len) +snarf_coding_system (const UExtbyte *p, Bytecount len) { Bytecount n; - Ibyte *name; + UExtbyte *name; while (*p == ' ' || *p == '\t') p++, len--; len = min (len, 1000); @@ -3948,7 +3566,9 @@ if (n > 0) { name[n] = '\0'; - return find_coding_system_for_text_file (intern_int (name), 0); + /* This call to intern_int() is OK because we already verified that + there are only ASCII characters in the string */ + return find_coding_system_for_text_file (intern_int ((Ibyte *) name), 0); } return Qnil; @@ -3983,6 +3603,7 @@ { const UExtbyte *p; const UExtbyte *scan_end; + Bytecount cookie_len; /* Look for initial "-*-"; mode line prefix */ for (p = data, @@ -4024,20 +3645,26 @@ break; } -#if 0 - /* #### Totally wrong as is, rewrite */ - /* Look for initial ;;;###coding system */ + /* Look for ;;;###coding system */ + + cookie_len = LENGTH (";;;###coding system: "); + for (p = data, + scan_end = data + len - cookie_len; + p <= scan_end; + p++) { - Bytecount ind = fast_string_match (QScoding_system_cookie, - data, Qnil, 0, len, 0, ERROR_ME_NOT, - 1); - if (ind >= 0) - return - snarf_coding_system (data + ind + LENGTH (";;;###coding system: "), - len - ind - LENGTH (";;;###coding system: ")); + if (*p == ';' && !memcmp (p, ";;;###coding system: ", cookie_len)) + { + const UExtbyte *suffix; + + p += cookie_len; + suffix = p; + while (suffix < scan_end && !isspace (*suffix)) + suffix++; + return snarf_coding_system (p, suffix - p); + } } -#endif /* 0 */ return Qnil; } @@ -4324,7 +3951,6 @@ int *category_to_priority = alloca_array (int, coding_detector_category_count); int i, j; - Lisp_Object rest; /* First generate a list that maps coding categories to priorities. */ @@ -4333,14 +3959,16 @@ /* Highest priority comes from the specified list. */ i = 0; - EXTERNAL_LIST_LOOP (rest, list) - { - int cat = coding_category_symbol_to_id (XCAR (rest)); + { + EXTERNAL_LIST_LOOP_2 (elt, list) + { + int cat = coding_category_symbol_to_id (elt); - if (category_to_priority[cat] >= 0) - sferror ("Duplicate coding category in list", XCAR (rest)); - category_to_priority[cat] = i++; - } + if (category_to_priority[cat] >= 0) + sferror ("Duplicate coding category in list", elt); + category_to_priority[cat] = i++; + } + } /* Now go through the existing categories by priority to retrieve the categories not yet specified and preserve their priority @@ -4837,7 +4465,7 @@ make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); the_coding_system_type_entry_dynarr = Dynarr_new (coding_system_type_entry); - dump_add_root_struct_ptr (&the_coding_system_type_entry_dynarr, + dump_add_root_block_ptr (&the_coding_system_type_entry_dynarr, &csted_description); Vcoding_system_type_list = Qnil; @@ -4855,7 +4483,7 @@ sizeof (coding_category_by_priority)); all_coding_detectors = Dynarr_new2 (detector_dynarr, struct detector); - dump_add_root_struct_ptr (&all_coding_detectors, + dump_add_root_block_ptr (&all_coding_detectors, &detector_dynarr_description); dump_add_opaque_int (&coding_system_tick); @@ -4955,8 +4583,6 @@ void vars_of_file_coding (void) { - reinit_vars_of_file_coding (); - /* We always have file-coding support */ Fprovide (intern ("file-coding")); diff --text -u 'xemacs-21.5.18/src/file-coding.h' 'xemacs-21.5.19/src/file-coding.h' Index: ./src/file-coding.h --- ./src/file-coding.h Wed Sep 22 11:06:47 2004 +++ ./src/file-coding.h Fri Nov 5 08:06:28 2004 @@ -480,7 +480,7 @@ defsymbol_nodump (&ty##_coding_system_methods->predicate_symbol, \ pred_sym); \ add_entry_to_coding_system_type_list (ty##_coding_system_methods); \ - dump_add_root_struct_ptr (&ty##_coding_system_methods, \ + dump_add_root_block_ptr (&ty##_coding_system_methods, \ &coding_system_methods_description); \ } while (0) @@ -1046,7 +1046,7 @@ Ichar decode_big5_char (int o1, int o2); void add_entry_to_coding_system_type_list (struct coding_system_methods *m); Lisp_Object make_internal_coding_system (Lisp_Object existing, - Char_ASCII *prefix, + Ascbyte *prefix, Lisp_Object type, Lisp_Object description, Lisp_Object props); diff --text -u 'xemacs-21.5.18/src/fileio.c' 'xemacs-21.5.19/src/fileio.c' Index: ./src/fileio.c --- ./src/fileio.c Tue Sep 21 04:19:43 2004 +++ ./src/fileio.c Fri Jan 28 11:36:24 2005 @@ -1,6 +1,6 @@ /* File IO for XEmacs. Copyright (C) 1985-1988, 1992-1995 Free Software Foundation, Inc. - Copyright (C) 1996, 2001, 2002, 2003 Ben Wing. + Copyright (C) 1996, 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -23,6 +23,7 @@ /* More syncing: FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> (Note: Sync messages from Marc Paquette may indicate incomplete synching, so beware.) */ +/* Some functions synched with FSF 21.0.103. */ /* Mule-ized completely except for the #if 0-code including decrypt-string and encrypt-string. --ben 7-2-00 */ /* #if 0-code Mule-ized, 2-22-03. --ben */ @@ -38,6 +39,7 @@ #include "frame.h" #include "insdel.h" #include "lstream.h" +#include "profile.h" #include "process.h" #include "redisplay.h" #include "sysdep.h" @@ -129,6 +131,8 @@ Lisp_Object Qcompute_buffer_file_truename; +Lisp_Object QSin_expand_file_name; + EXFUN (Frunning_temacs_p, 0); /* DATA can be anything acceptable to signal_error (). @@ -267,7 +271,7 @@ /* This function does not GC */ /* This function can be called during GC */ /* This function must not munge the match data. */ - Lisp_Object chain, inhibited_handlers; + Lisp_Object inhibited_handlers; CHECK_STRING (filename); @@ -276,22 +280,22 @@ else inhibited_handlers = Qnil; - EXTERNAL_LIST_LOOP (chain, Vfile_name_handler_alist) - { - Lisp_Object elt = XCAR (chain); - if (CONSP (elt)) - { - Lisp_Object string = XCAR (elt); - if (STRINGP (string) - && (fast_lisp_string_match (string, filename) >= 0)) - { - Lisp_Object handler = XCDR (elt); - if (NILP (Fmemq (handler, inhibited_handlers))) - return handler; - } - } - QUIT; - } + { + EXTERNAL_LIST_LOOP_2 (elt, Vfile_name_handler_alist) + { + if (CONSP (elt)) + { + Lisp_Object string = XCAR (elt); + if (STRINGP (string) + && (fast_lisp_string_match (string, filename) >= 0)) + { + Lisp_Object handler = XCDR (elt); + if (NILP (Fmemq (handler, inhibited_handlers))) + return handler; + } + } + } + } return Qnil; } @@ -325,6 +329,25 @@ } + +Ibyte * +find_end_of_directory_component (const Ibyte *path, Bytecount len) +{ + const Ibyte *p = path + len; + + while (p != path && !IS_DIRECTORY_SEP (p[-1]) +#ifdef WIN32_FILENAMES + /* only recognise drive specifier at the beginning */ + && !(p[-1] == ':' + /* handle the "/:d:foo" and "/:foo" cases correctly */ + && ((p == path + 2 && !IS_DIRECTORY_SEP (*path)) + || (p == path + 4 && IS_DIRECTORY_SEP (*path)))) +#endif + ) p--; + + return (Ibyte *) p; +} + DEFUN ("file-name-directory", Ffile_name_directory, 1, 1, 0, /* Return the directory component in file name FILENAME. Return nil if FILENAME does not include a directory. @@ -352,17 +375,7 @@ #endif beg = XSTRING_DATA (filename); /* XEmacs: no need to alloca-copy here */ - p = beg + XSTRING_LENGTH (filename); - - while (p != beg && !IS_DIRECTORY_SEP (p[-1]) -#ifdef WIN32_FILENAMES - /* only recognise drive specifier at the beginning */ - && !(p[-1] == ':' - /* handle the "/:d:foo" and "/:foo" cases correctly */ - && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg)) - || (p == beg + 4 && IS_DIRECTORY_SEP (*beg)))) -#endif - ) p--; + p = find_end_of_directory_component (beg, XSTRING_LENGTH (filename)); if (p == beg) return Qnil; @@ -373,8 +386,7 @@ Ibyte *res; Ibyte *wd = mswindows_getdcwd (toupper (*beg) - 'A' + 1); - res = alloca_array (Ibyte, - (wd ? qxestrlen (wd) : 0) + 10); /* go overboard */ + res = alloca_ibytes ((wd ? qxestrlen (wd) : 0) + 10); /* go overboard */ res[0] = '\0'; if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':') { @@ -523,7 +535,11 @@ return call2_check_string (handler, Qfile_name_as_directory, filename); buf = alloca_ibytes (XSTRING_LENGTH (filename) + 10); - return build_intstring (file_name_as_directory (buf, XSTRING_DATA (filename))); + file_name_as_directory (buf, XSTRING_DATA (filename)); + if (qxestrcmp (buf, XSTRING_DATA (filename))) + return build_intstring (buf); + else + return filename; } /* @@ -576,7 +592,7 @@ handler = Ffind_file_name_handler (directory, Qdirectory_file_name); if (!NILP (handler)) return call2_check_string (handler, Qdirectory_file_name, directory); - buf = (Ibyte *) ALLOCA (XSTRING_LENGTH (directory) + 20); + buf = alloca_ibytes (XSTRING_LENGTH (directory) + 20); directory_file_name (XSTRING_DATA (directory), buf); return build_intstring (buf); } @@ -736,6 +752,9 @@ int length; Lisp_Object handler = Qnil; struct gcpro gcpro1, gcpro2, gcpro3; + PROFILE_DECLARE (); + + PROFILE_RECORD_ENTERING_SECTION (QSin_expand_file_name); /* both of these get set below */ GCPRO3 (name, default_directory, handler); @@ -746,8 +765,10 @@ call the corresponding file handler. */ handler = Ffind_file_name_handler (name, Qexpand_file_name); if (!NILP (handler)) - RETURN_UNGCPRO (call3_check_string (handler, Qexpand_file_name, - name, default_directory)); + RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, + call3_check_string + (handler, Qexpand_file_name, + name, default_directory)); /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ if (NILP (default_directory)) @@ -763,8 +784,9 @@ { handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); if (!NILP (handler)) - RETURN_UNGCPRO (call3 (handler, Qexpand_file_name, - name, default_directory)); + RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, + call3 (handler, Qexpand_file_name, + name, default_directory)); } o = XSTRING_DATA (default_directory); @@ -928,13 +950,14 @@ } } xfree (newnm, Ibyte *); - RETURN_UNGCPRO (name); + RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, name); } #endif /* WIN32_FILENAMES */ #ifndef WIN32_NATIVE if (nm == XSTRING_DATA (name)) - RETURN_UNGCPRO (name); - RETURN_UNGCPRO (build_intstring (nm)); + RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, name); + RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, + build_intstring (nm)); #endif /* not WIN32_NATIVE */ } } @@ -978,7 +1001,7 @@ { for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++) DO_NOTHING; - o = (Ibyte *) ALLOCA (p - nm + 1); + o = alloca_ibytes (p - nm + 1); memcpy (o, nm, p - nm); o [p - nm] = 0; @@ -1048,7 +1071,7 @@ if (!newdir) { /* Either nm starts with /, or drive isn't mounted. */ - newdir = (Ibyte *) ALLOCA (4); + newdir = alloca_ibytes (4); newdir[0] = DRIVE_LETTER (drive); newdir[1] = ':'; newdir[2] = '/'; @@ -1112,8 +1135,8 @@ } if (!IS_DIRECTORY_SEP (nm[0])) { - Ibyte *tmp = (Ibyte *) ALLOCA (qxestrlen (newdir) + - qxestrlen (nm) + 2); + Ibyte *tmp = alloca_ibytes (qxestrlen (newdir) + + qxestrlen (nm) + 2); file_name_as_directory (tmp, newdir); qxestrcat (tmp, nm); nm = tmp; @@ -1152,10 +1175,9 @@ { if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) { - newdir = - (Ibyte *) - qxestrcpy ((Ibyte *) ALLOCA (qxestrlen (newdir) + 1), - newdir); + /* !!#### Use ei API */ + newdir = qxestrcpy (alloca_ibytes (qxestrlen (newdir) + 1), + newdir); p = newdir + 2; while (*p && !IS_DIRECTORY_SEP (*p)) p++; p++; @@ -1179,7 +1201,7 @@ #endif ) { - Ibyte *temp = (Ibyte *) ALLOCA (length); + Ibyte *temp = alloca_ibytes (length); memcpy (temp, newdir, length - 1); temp[length - 1] = 0; newdir = temp; @@ -1195,10 +1217,10 @@ /* Reserve space for drive specifier and escape prefix, since either or both may need to be inserted. (The Microsoft x86 compiler produces incorrect code if the following two lines are combined.) */ - target = (Ibyte *) ALLOCA (tlen + 4); + target = alloca_ibytes (tlen + 4); target += 4; #else /* not WIN32_FILENAMES */ - target = (Ibyte *) ALLOCA (tlen); + target = alloca_ibytes (tlen); #endif /* not WIN32_FILENAMES */ *target = 0; @@ -1303,10 +1325,11 @@ Lisp_Object result = build_intstring (newtarget); xfree (newtarget, Ibyte *); - RETURN_UNGCPRO (result); + RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, result); } #else /* not WIN32_FILENAMES */ - RETURN_UNGCPRO (make_string (target, o - target)); + RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, + make_string (target, o - target)); #endif /* not WIN32_FILENAMES */ } @@ -1343,7 +1366,7 @@ } { - Ibyte resolved_path[PATH_MAX]; + Ibyte resolved_path[PATH_MAX_INTERNAL]; Bytecount elen = XSTRING_LENGTH (expanded_name); Ibyte *path; Ibyte *p; @@ -1362,7 +1385,7 @@ p = path; /* Try doing it all at once. */ - if (!qxe_realpath (path, resolved_path)) + if (!qxe_realpath (path, resolved_path, 0)) { /* Didn't resolve it -- have to do it one component at a time. */ /* "realpath" is a typically useless, stupid un*x piece of crap. @@ -1381,7 +1404,11 @@ resolved_name are undefined." Since we depend on undocumented semantics of various system - realpath()s, we just use our own version in realpath.c. */ + realpath()s, we just use our own version in realpath.c. + + Note also that our own version differs in its semantics from any + standard version, since it accepts and returns internal-format + text, not external-format. */ for (;;) { Ibyte *pos; @@ -1404,7 +1431,7 @@ if (p != pos) p = 0; - if (qxe_realpath (path, resolved_path)) + if (qxe_realpath (path, resolved_path, 0)) { if (p) *p = DIRECTORY_SEP; @@ -1562,7 +1589,7 @@ } /* Copy out the variable name */ - target = (Ibyte *) ALLOCA (s - o + 1); + target = alloca_ibytes (s - o + 1); qxestrncpy (target, o, s - o); target[s - o] = 0; #ifdef WIN32_NATIVE @@ -1581,7 +1608,7 @@ /* If substitution required, recopy the filename and do it */ /* Make space in stack frame for the new copy */ - xnm = (Ibyte *) ALLOCA (XSTRING_LENGTH (filename) + total + 1); + xnm = alloca_ibytes (XSTRING_LENGTH (filename) + total + 1); x = xnm; /* Copy the rest of the name through, replacing $ constructs with values */ @@ -1613,7 +1640,7 @@ } /* Copy out the variable name */ - target = (Ibyte *) ALLOCA (s - o + 1); + target = alloca_ibytes (s - o + 1); qxestrncpy (target, o, s - o); target[s - o] = 0; #ifdef WIN32_NATIVE @@ -2340,7 +2367,7 @@ if (!NILP (handler)) RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath)); -#if defined(WIN32_FILENAMES) +#if defined (WIN32_FILENAMES) /* Under MS-DOS and Windows, open does not work for directories. */ UNGCPRO; if (qxe_access (XSTRING_DATA (abspath), 0) == 0) @@ -2445,9 +2472,42 @@ val = make_string (buf, valsize); xfree (buf, Ibyte *); return val; -#else /* not HAVE_READLINK */ +#elif defined (WIN32_NATIVE) + if (mswindows_shortcuts_are_symlinks) + { + /* We want to resolve the directory component and leave the rest + alone. */ + Ibyte *path = XSTRING_DATA (filename); + Ibyte *dirend = + find_end_of_directory_component (path, XSTRING_LENGTH (filename)); + Ibyte *fname; + DECLARE_EISTRING (dir); + + if (dirend != path) + { + Ibyte *resdir; + DECLARE_EISTRING (resname); + + eicpy_raw (dir, path, dirend - path); + PATHNAME_RESOLVE_LINKS (eidata (dir), resdir); + eicpy_rawz (resname, resdir); + eicat_rawz (resname, dirend); + path = eidata (resname); + } + + fname = mswindows_read_link (path); + if (!fname) + return Qnil; + { + Lisp_Object val = build_intstring (fname); + xfree (fname, Ibyte *); + return val; + } + } + return Qnil; +#else return Qnil; -#endif /* not HAVE_READLINK */ +#endif } DEFUN ("file-directory-p", Ffile_directory_p, 1, 1, 0, /* @@ -2501,7 +2561,7 @@ return call2 (handler, Qfile_accessible_directory_p, filename); -#if !defined(WIN32_NATIVE) +#if !defined (WIN32_NATIVE) if (NILP (Ffile_directory_p (filename))) return (Qnil); else @@ -3137,22 +3197,16 @@ if (inserted > 0) { - Lisp_Object p; - struct gcpro ngcpro1; - - NGCPRO1 (p); - EXTERNAL_LIST_LOOP (p, Vafter_insert_file_functions) + GC_EXTERNAL_LIST_LOOP_2 (p, Vafter_insert_file_functions) { - Lisp_Object insval = - call1 (XCAR (p), make_int (inserted)); + Lisp_Object insval = call1 (p, make_int (inserted)); if (!NILP (insval)) { CHECK_NATNUM (insval); inserted = XINT (insval); } - QUIT; } - NUNGCPRO; + END_GC_EXTERNAL_LIST_LOOP (p); } UNGCPRO; @@ -3666,6 +3720,7 @@ */ (string, key)) { + /* !!#### Needs work */ Extbyte *encrypted_string, *raw_key; Extbyte *string_ext, *key_ext; Bytecount string_size_ext, key_size_ext, rounded_size, extra, key_size; @@ -3920,7 +3975,7 @@ and if so, tries to avoid touching lisp objects. The only time that Fdo_auto_save() is called while GC is in progress - is if we're going down, as a result of an abort() or a kill signal. + is if we're going down, as a result of an ABORT() or a kill signal. It's fairly important that we generate autosave files in that case! */ @@ -4307,6 +4362,10 @@ void vars_of_fileio (void) { + QSin_expand_file_name = + build_msg_string ("(in expand-file-name)"); + staticpro (&QSin_expand_file_name); + DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format /* *Format in which to write auto-save files. Should be a list of symbols naming formats that are defined in `format-alist'. @@ -4405,8 +4464,6 @@ what the normal separator is. */ ); Vdirectory_sep_char = make_char (DEFAULT_DIRECTORY_SEP); - - reinit_vars_of_fileio (); } void diff --text -u 'xemacs-21.5.18/src/filelock.c' 'xemacs-21.5.19/src/filelock.c' Index: ./src/filelock.c --- ./src/filelock.c Wed Oct 1 00:26:46 2003 +++ ./src/filelock.c Fri Nov 5 08:06:29 2004 @@ -96,7 +96,7 @@ /* Write the name of the lock file for FN into LFNAME. Length will be that of FN plus two more for the leading `.#' plus one for the null. */ #define MAKE_LOCK_NAME(lock, file) \ - (lock = (Ibyte *) ALLOCA (XSTRING_LENGTH (file) + 2 + 1), \ + (lock = alloca_ibytes (XSTRING_LENGTH (file) + 2 + 1), \ fill_in_lock_file_name (lock, file)) static void @@ -141,8 +141,8 @@ host_name = (Ibyte *) ""; lock_info_str = - (Ibyte *) ALLOCA (qxestrlen (user_name) + qxestrlen (host_name) - + LOCK_PID_MAX + 5); + alloca_ibytes (qxestrlen (user_name) + qxestrlen (host_name) + + LOCK_PID_MAX + 5); qxesprintf (lock_info_str, "%s@%s.%d", user_name, host_name, qxe_getpid ()); @@ -194,7 +194,7 @@ read it to determine return value, so allocate it. */ if (!owner) { - owner = (lock_info_type *) ALLOCA (sizeof (lock_info_type)); + owner = alloca_new (lock_info_type); local_owner = 1; } @@ -207,7 +207,7 @@ return -1; } len = at - lfinfo; - owner->user = (Ibyte *) xmalloc (len + 1); + owner->user = xnew_ibytes (len + 1); qxestrncpy (owner->user, lfinfo, len); owner->user[len] = 0; @@ -216,7 +216,7 @@ /* The host is everything in between. */ len = dot - at - 1; - owner->host = (Ibyte *) xmalloc (len + 1); + owner->host = xnew_ibytes (len + 1); qxestrncpy (owner->host, at + 1, len); owner->host[len] = 0; @@ -349,9 +349,9 @@ goto done; /* Else consider breaking the lock */ - locker = (Ibyte *) ALLOCA (qxestrlen (lock_info.user) - + qxestrlen (lock_info.host) - + LOCK_PID_MAX + 9); + locker = alloca_ibytes (qxestrlen (lock_info.user) + + qxestrlen (lock_info.host) + + LOCK_PID_MAX + 9); qxesprintf (locker, "%s@%s (pid %d)", lock_info.user, lock_info.host, lock_info.pid); FREE_LOCK_INFO (lock_info); diff --text -u 'xemacs-21.5.18/src/fns.c' 'xemacs-21.5.19/src/fns.c' Index: ./src/fns.c --- ./src/fns.c Tue Sep 21 04:19:43 2004 +++ ./src/fns.c Tue Jan 25 08:33:55 2005 @@ -741,7 +741,7 @@ break; default: val = Qnil; - abort (); + ABORT (); } } @@ -1031,7 +1031,7 @@ } else { - abort (); /* unreachable, since Flength (sequence) did not get + ABORT (); /* unreachable, since Flength (sequence) did not get an error */ return Qnil; } @@ -3229,7 +3229,7 @@ { /* The string data of `sequence' might be relocated during GC. */ Bytecount slen = XSTRING_LENGTH (sequence); - Ibyte *p = alloca_array (Ibyte, slen); + Ibyte *p = alloca_ibytes (slen); Ibyte *end = p + slen; memcpy (p, XSTRING_DATA (sequence), slen); @@ -3254,7 +3254,7 @@ } } else - abort (); /* unreachable, since Flength (sequence) did not get an error */ + ABORT (); /* unreachable, since Flength (sequence) did not get an error */ if (vals) UNGCPRO; @@ -3350,22 +3350,22 @@ */ (old, new)) { - Lisp_Object tail, oldtail = old, prevoldtail = Qnil; + Lisp_Object oldtail = old, prevoldtail = Qnil; - EXTERNAL_LIST_LOOP (tail, new) + EXTERNAL_LIST_LOOP_2 (elt, new) { if (!NILP (oldtail)) { CHECK_CONS (oldtail); - XCAR (oldtail) = XCAR (tail); + XCAR (oldtail) = elt; } else if (!NILP (prevoldtail)) { - XCDR (prevoldtail) = Fcons (XCAR (tail), Qnil); + XCDR (prevoldtail) = Fcons (elt, Qnil); prevoldtail = XCDR (prevoldtail); } else - old = oldtail = Fcons (XCAR (tail), Qnil); + old = oldtail = Fcons (elt, Qnil); if (!NILP (oldtail)) { @@ -3383,7 +3383,7 @@ } Lisp_Object -add_suffix_to_symbol (Lisp_Object symbol, const Char_ASCII *ascii_string) +add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) { return Fintern (concat2 (Fsymbol_name (symbol), build_string (ascii_string)), @@ -3391,7 +3391,7 @@ } Lisp_Object -add_prefix_to_symbol (const Char_ASCII *ascii_string, Lisp_Object symbol) +add_prefix_to_symbol (const Ascbyte *ascii_string, Lisp_Object symbol) { return Fintern (concat2 (build_string (ascii_string), Fsymbol_name (symbol)), @@ -3873,7 +3873,7 @@ encoded_length = base64_encode_1 (XLSTREAM (input), encoded, NILP (no_line_break)); if (encoded_length > allength) - abort (); + ABORT (); Lstream_delete (XLSTREAM (input)); /* Now we have encoded the region, so we insert the new contents @@ -3915,7 +3915,7 @@ encoded_length = base64_encode_1 (XLSTREAM (input), encoded, NILP (no_line_break)); if (encoded_length > allength) - abort (); + ABORT (); Lstream_delete (XLSTREAM (input)); result = make_string (encoded, encoded_length); unbind_to (speccount); @@ -3948,7 +3948,7 @@ decoded = (Ibyte *) MALLOC_OR_ALLOCA (length * MAX_ICHAR_LEN); decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); if (decoded_length > length * MAX_ICHAR_LEN) - abort (); + ABORT (); Lstream_delete (XLSTREAM (input)); /* Now we have decoded the region, so we insert the new contents @@ -3989,7 +3989,7 @@ decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); if (decoded_length > length * MAX_ICHAR_LEN) - abort (); + ABORT (); Lstream_delete (XLSTREAM (input)); result = make_string (decoded, decoded_length); diff --text -u 'xemacs-21.5.18/src/font-lock.c' 'xemacs-21.5.19/src/font-lock.c' Index: ./src/font-lock.c --- ./src/font-lock.c Fri Feb 14 18:50:17 2003 +++ ./src/font-lock.c Tue Jan 25 08:33:55 2005 @@ -529,7 +529,7 @@ context_cache.context = context_comment; context_cache.ccontext = ccontext_none; context_cache.style = SINGLE_SYNTAX_STYLE (syncode); - if (context_cache.style == comment_style_none) abort (); + if (context_cache.style == comment_style_none) ABORT (); } break; @@ -621,7 +621,7 @@ { context_cache.ccontext = ccontext_start2; context_cache.style = SYNTAX_START_STYLE (prev_syncode, syncode); - if (context_cache.style == comment_style_none) abort (); + if (context_cache.style == comment_style_none) ABORT (); } else if ((SYNTAX_CODE_COMMENT_BITS (syncode) & SYNTAX_FIRST_CHAR_START) && @@ -659,18 +659,18 @@ of a comment-end sequence. ie, '/xxx foo xxx/' or '/xxx foo x/', where 'x' = '*' -- mct */ { - if (context_cache.style == comment_style_none) abort (); + if (context_cache.style == comment_style_none) ABORT (); context_cache.ccontext = ccontext_end1; } else if (context_cache.ccontext == ccontext_start1) { - if (context_cache.context != context_none) abort (); + if (context_cache.context != context_none) ABORT (); context_cache.ccontext = ccontext_none; } else if (context_cache.ccontext == ccontext_end1) { - if (context_cache.context != context_block_comment) abort (); + if (context_cache.context != context_block_comment) ABORT (); context_cache.context = context_none; context_cache.ccontext = ccontext_start2; } @@ -679,7 +679,7 @@ context_cache.context == context_none) { context_cache.context = context_block_comment; - if (context_cache.style == comment_style_none) abort (); + if (context_cache.style == comment_style_none) ABORT (); } else if (context_cache.ccontext == ccontext_none && context_cache.context == context_block_comment) @@ -703,7 +703,7 @@ case context_block_comment: return Qblock_comment; case context_generic_comment: return Qblock_comment; case context_generic_string: return Qstring; - default: abort (); return Qnil; /* suppress compiler warning */ + default: ABORT (); return Qnil; /* suppress compiler warning */ } } @@ -853,7 +853,6 @@ void vars_of_font_lock (void) { - reinit_vars_of_font_lock (); } #endif /* USE_C_FONT_LOCK */ diff --text -u 'xemacs-21.5.18/src/frame-gtk.c' 'xemacs-21.5.19/src/frame-gtk.c' Index: ./src/frame-gtk.c --- ./src/frame-gtk.c Tue Sep 21 04:19:44 2004 +++ ./src/frame-gtk.c Tue Jan 25 08:33:56 2005 @@ -1111,7 +1111,7 @@ } else { - /* abort()? */ + /* ABORT()? */ stderr_out ("POINTER_IMAGE_INSTANCEP (f->pointer) failed!\n"); } } @@ -1423,7 +1423,7 @@ } } else - abort (); + ABORT (); #ifdef HAVE_TOOLBARS /* Setting the background clears the entire frame area diff --text -u 'xemacs-21.5.18/src/frame-msw.c' 'xemacs-21.5.19/src/frame-msw.c' Index: ./src/frame-msw.c --- ./src/frame-msw.c Tue Sep 21 04:19:44 2004 +++ ./src/frame-msw.c Fri Nov 5 08:06:30 2004 @@ -401,7 +401,7 @@ client part. So, if non-client are is covered and client area is not, we return true. */ GetClientRect (hwnd, &rc_me); - MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2); + MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT) (void *) (&rc_me), 2); /* First see if we're off the desktop */ GetWindowRect (GetDesktopWindow (), &rc_other); @@ -1170,8 +1170,6 @@ void vars_of_frame_mswindows (void) { - reinit_vars_of_frame_mswindows (); - DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /* Controls whether to use system or XEmacs defaults for frame size. If nil then reasonable defaults are used for initial frame sizes. If t diff --text -u 'xemacs-21.5.18/src/frame-x.c' 'xemacs-21.5.19/src/frame-x.c' Index: ./src/frame-x.c --- ./src/frame-x.c Tue Sep 21 04:19:44 2004 +++ ./src/frame-x.c Tue Jan 25 08:33:56 2005 @@ -1,6 +1,6 @@ /* Functions for the X window system. Copyright (C) 1989, 1992-5, 1997 Free Software Foundation, Inc. - Copyright (C) 1995, 1996, 2001, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -21,9 +21,9 @@ /* Synched up with: Not synched with FSF. */ -/* Substantially rewritten for XEmacs. */ +/* This file has been Mule-ized, Ben Wing, 10-14-04. */ -/* 7-8-00 !!#### This file needs definite Mule review. */ +/* Substantially rewritten for XEmacs. */ #include <config.h> #include "lisp.h" @@ -221,14 +221,14 @@ void x_wm_mark_shell_size_user_specified (Widget wmshell) { - if (! XtIsWMShell (wmshell)) abort (); + if (! XtIsWMShell (wmshell)) ABORT (); EmacsShellSetSizeUserSpecified (wmshell); } void x_wm_mark_shell_position_user_specified (Widget wmshell) { - if (! XtIsWMShell (wmshell)) abort (); + if (! XtIsWMShell (wmshell)) ABORT (); EmacsShellSetPositionUserSpecified (wmshell); } @@ -237,7 +237,7 @@ void x_wm_set_shell_iconic_p (Widget shell, int iconic_p) { - if (! XtIsWMShell (shell)) abort (); + if (! XtIsWMShell (shell)) ABORT (); /* Because of questionable logic in Shell.c, this sequence can't work: @@ -267,12 +267,12 @@ Arg al [2]; if (!XtIsWMShell (wmshell)) - abort (); + ABORT (); if (cw <= 0 || ch <= 0) - abort (); + ABORT (); - XtSetArg (al [0], XtNwidthInc, cw); - XtSetArg (al [1], XtNheightInc, ch); + XtSetArg (al[0], XtNwidthInc, cw); + XtSetArg (al[1], XtNheightInc, ch); XtSetValues (wmshell, al, 2); } @@ -282,15 +282,15 @@ Arg al [2]; if (!XtIsWMShell (wmshell)) - abort (); + ABORT (); #ifdef DEBUG_GEOMETRY_MANAGEMENT /* See comment in EmacsShell.c */ printf ("x_wm_set_variable_size: %d %d\n", width, height); fflush (stdout); #endif - XtSetArg (al [0], XtNwidthCells, width); - XtSetArg (al [1], XtNheightCells, height); + XtSetArg (al[0], XtNwidthCells, width); + XtSetArg (al[1], XtNheightCells, height); XtSetValues (wmshell, al, 2); } @@ -314,7 +314,7 @@ int format = 0; unsigned long nitems = 0; unsigned long bytes_after; - unsigned char *prop_return = 0; /* semantically a void* */ + Rawbyte *prop_return = 0; /* semantically a void* */ if (Success == XGetWindowProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d), 0, 100, False, XA_ATOM, @@ -330,7 +330,7 @@ else if (atoms[nitems] == DEVICE_XATOM_WM_TAKE_FOCUS (d)) need_focus = 0; } - if (prop_return) XFree ((char *) prop_return); + if (prop_return) XFree ((CRawbyte *) prop_return); } { Atom props [10]; @@ -339,19 +339,19 @@ if (need_focus) props[count++] = DEVICE_XATOM_WM_TAKE_FOCUS (d); if (count) XChangeProperty (dpy, w, DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32, - PropModeAppend, (unsigned char *) props, count); + PropModeAppend, (Rawbyte *) props, count); } } static void -x_wm_store_class_hints (Widget shell, char *frame_name) +x_wm_store_class_hints (Widget shell, Extbyte *frame_name) { Display *dpy = XtDisplay (shell); - char *app_name, *app_class; + Extbyte *app_name, *app_class; XClassHint classhint; if (!XtIsWMShell (shell)) - abort (); + ABORT (); XtGetApplicationNameAndClass (dpy, &app_name, &app_class); classhint.res_name = frame_name; @@ -360,6 +360,7 @@ } #ifndef HAVE_WMCOMMAND + static void x_wm_maybe_store_wm_command (struct frame *f) { @@ -367,12 +368,12 @@ struct device *d = XDEVICE (FRAME_DEVICE (f)); if (!XtIsWMShell (w)) - abort (); + ABORT (); if (NILP (DEVICE_X_WM_COMMAND_FRAME (d))) { int argc; - char **argv; + Wexttext **argv; make_argc_argv (Vcommand_line_args, &argc, &argv); XSetCommand (XtDisplay (w), XtWindow (w), argv, argc); free_argc_argv (argv); @@ -410,6 +411,7 @@ } } + #endif /* !HAVE_WMCOMMAND */ int @@ -418,7 +420,7 @@ Atom actual_type; int actual_format; unsigned long nitems, bytesafter; - unsigned char *datap = 0; + Rawbyte *datap = 0; Widget widget; int result = -1; struct device *d = XDEVICE (FRAME_DEVICE (f)); @@ -434,7 +436,7 @@ unsigned long *ul_result_ptr = (unsigned long *) datap; if (nitems <= 2) /* "suggested" by ICCCM version 1 */ result = (int) ul_result_ptr[0]; - XFree ((char *) datap); + XFree ((CRawbyte *) datap); } return result; @@ -643,7 +645,7 @@ for (ptr = value; *ptr; ptr++) if (!byte_ascii_p (*ptr)) { - const char * tmp; + const Extbyte *tmp; encoding = DEVICE_XATOM_COMPOUND_TEXT (XDEVICE (FRAME_DEVICE (f))); C_STRING_TO_EXTERNAL (value, tmp, Qctext); new_XtValue = (String) tmp; @@ -685,12 +687,12 @@ x_set_initial_frame_size (struct frame *f, int flags, int x, int y, int w, int h) { - char shell_geom [255]; + Ascbyte shell_geom[255]; int xval, yval; - char xsign, ysign; - char uspos = !!(flags & (XValue | YValue)); - char ussize = !!(flags & (WidthValue | HeightValue)); - char *temp; + Ascbyte xsign, ysign; + Boolbyte uspos = !!(flags & (XValue | YValue)); + Boolbyte ussize = !!(flags & (WidthValue | HeightValue)); + Ascbyte *temp; /* assign the correct size to the EmacsFrame widget ... */ EmacsFrameSetCharSize (FRAME_X_TEXT_WIDGET (f), w, h); @@ -708,7 +710,7 @@ if (uspos || ussize) { - temp = (char *) xmalloc (1 + strlen (shell_geom)); + temp = xnew_ascbytes (1 + strlen (shell_geom)); strcpy (temp, shell_geom); FRAME_X_GEOM_FREE_ME_PLEASE (f) = temp; } @@ -742,21 +744,27 @@ if (STRINGP (prop)) { - const char *extprop; + const Extbyte *extprop; if (XSTRING_LENGTH (prop) == 0) continue; - LISP_STRING_TO_EXTERNAL (prop, extprop, Qctext); + LISP_STRING_TO_EXTERNAL (prop, extprop, Qxt_widget_arg_encoding); if (STRINGP (val)) { const Extbyte *extval; Bytecount extvallen; + /* !!#### I seriously doubt there is a single external format + for the value of a widget argument; it depends on the + semantics of the argument. So use of + Qxt_widget_arg_encoding is totally bogus. --ben */ TO_EXTERNAL_FORMAT (LISP_STRING, val, ALLOCA, (extval, extvallen), - Qctext); + Qxt_widget_arg_encoding); XtVaSetValues (w, XtVaTypedArg, extprop, + /* !!#### Verify this + 1 and document + as zero-termination */ XtRString, extval, extvallen + 1, (XtArgVal) NULL); } @@ -769,6 +777,7 @@ { Lisp_Object str = Fget (prop, Qx_resource_name, Qnil); int int_p = !NILP (Fget (prop, Qintegerp, Qnil)); + Extbyte *strext; if (NILP (prop) || NILP (str)) { @@ -796,14 +805,14 @@ /* Kludge the width/height so that we interpret them in characters instead of pixels. Yuck yuck yuck. */ - if (!strcmp ((char *) XSTRING_DATA (str), "width")) + if (!qxestrcmp_ascii (XSTRING_DATA (str), "width")) { CHECK_INT (val); width = XINT (val); width_specified_p = True; continue; } - if (!strcmp ((char *) XSTRING_DATA (str), "height")) + if (!qxestrcmp_ascii (XSTRING_DATA (str), "height")) { CHECK_INT (val); height = XINT (val); @@ -811,14 +820,14 @@ continue; } /* Further kludge the x/y. */ - if (!strcmp ((char *) XSTRING_DATA (str), "x")) + if (!qxestrcmp_ascii (XSTRING_DATA (str), "x")) { CHECK_INT (val); x = (Position) XINT (val); x_position_specified_p = True; continue; } - if (!strcmp ((char *) XSTRING_DATA (str), "y")) + if (!qxestrcmp_ascii (XSTRING_DATA (str), "y")) { CHECK_INT (val); y = (Position) XINT (val); @@ -827,41 +836,46 @@ } /* Have you figured out by now that this entire function is one gigantic kludge? */ - if (!strcmp ((char *) XSTRING_DATA (str), - "internalBorderWidth")) + if (!qxestrcmp_ascii (XSTRING_DATA (str), "internalBorderWidth")) { internal_border_width_specified = True; } + LISP_STRING_TO_EXTERNAL (str, strext, Qxt_widget_arg_encoding); if (int_p) { CHECK_INT (val); - Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), XINT (val)); + Xt_SET_VALUE (w, strext, XINT (val)); } else if (EQ (val, Qt)) { - Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), True); /* XtN...*/ + Xt_SET_VALUE (w, strext, True); /* XtN...*/ } else if (EQ (val, Qnil)) { - Xt_SET_VALUE (w, (char *) XSTRING_DATA (str), False); /* XtN...*/ + Xt_SET_VALUE (w, strext, False); /* XtN...*/ } else { + const Extbyte *extval; + Bytecount extvallen; CHECK_STRING (val); + + TO_EXTERNAL_FORMAT (LISP_STRING, val, + ALLOCA, (extval, extvallen), + Qxt_widget_arg_encoding); XtVaSetValues (w, XtVaTypedArg, /* XtN... */ - (char *) XSTRING_DATA (str), - XtRString, - XSTRING_DATA (val), - XSTRING_LENGTH (val) + 1, + strext, + /* !!#### Verify this + 1 and document + as zero-termination */ + XtRString, extval, extvallen + 1, (XtArgVal) NULL); } #ifdef HAVE_SCROLLBARS - if (!strcmp ((char *) XSTRING_DATA (str), "scrollBarWidth") - || !strcmp ((char *) XSTRING_DATA (str), - "scrollBarHeight")) + if (!qxestrcmp_ascii (XSTRING_DATA (str), "scrollBarWidth") + || !qxestrcmp_ascii (XSTRING_DATA (str), "scrollBarHeight")) { x_update_frame_scrollbars (f); } @@ -941,36 +955,131 @@ if (!frame_title_format_already_set) { /* No doubt there's a less stupid way to do this. */ - char *results [2]; - XtResource resources [2]; - results [0] = results [1] = 0; - resources [0].resource_name = XtNtitle; - resources [0].resource_class = XtCTitle; - resources [0].resource_type = XtRString; - resources [0].resource_size = sizeof (String); - resources [0].resource_offset = 0; - resources [0].default_type = XtRString; - resources [0].default_addr = 0; - resources [1].resource_name = XtNiconName; - resources [1].resource_class = XtCIconName; - resources [1].resource_type = XtRString; - resources [1].resource_size = sizeof (String); - resources [1].resource_offset = sizeof (char *); - resources [1].default_type = XtRString; - resources [1].default_addr = 0; + Extbyte *results[2]; + XtResource resources[2]; + results[0] = results[1] = 0; + resources[0].resource_name = XtNtitle; + resources[0].resource_class = XtCTitle; + resources[0].resource_type = XtRString; + resources[0].resource_size = sizeof (String); + resources[0].resource_offset = 0; + resources[0].default_type = XtRString; + resources[0].default_addr = 0; + resources[1].resource_name = XtNiconName; + resources[1].resource_class = XtCIconName; + resources[1].resource_type = XtRString; + resources[1].resource_size = sizeof (String); + resources[1].resource_offset = sizeof (Extbyte *); + resources[1].default_type = XtRString; + resources[1].default_addr = 0; XtGetSubresources (XtParent (shell), (XtPointer) results, shell->core.name, shell->core.widget_class->core_class.class_name, resources, XtNumber (resources), 0, 0); if (results[0]) - Vframe_title_format = build_string (results[0]); + Vframe_title_format = build_ext_string (results[0], Qctext); if (results[1]) - Vframe_icon_title_format = build_string (results[1]); + Vframe_icon_title_format = build_ext_string (results[1], Qctext); } frame_title_format_already_set = 1; } +#if defined (HAVE_CDE) || defined (HAVE_OFFIX_DND) + +static Extbyte * +start_drag_internal_1 (Lisp_Object event, Lisp_Object data, + Lisp_Object encoding, XEvent *x_event, int listp, + Widget *wid_out, Bytecount *len_out, + int *num_items_out) +{ + struct frame *f; + Widget wid; + struct device *d; + struct x_device *xd; + XWindowAttributes win_attrib; + int modifier = 0, state = 0; + Extbyte *dnd_data; + Lisp_Event *lisp_event; + + CHECK_EVENT (event); + lisp_event = XEVENT (event); + if (EVENT_TYPE (lisp_event) != button_press_event) + invalid_argument ("Need button-press event for drag", event); + f = decode_x_frame (FW_FRAME (EVENT_CHANNEL (lisp_event))); + wid = FRAME_X_TEXT_WIDGET (f); + d = XDEVICE (FRAME_DEVICE (f)); + xd = DEVICE_X_DATA (d); + *num_items_out = 0; + + if (listp) + { + DECLARE_EISTRING (ei); + + EXTERNAL_LIST_LOOP_2 (elt, data) + { + CHECK_STRING (elt); + eicat_lstr (ei, elt); + eicat_ch (ei, '\0'); + (*num_items_out)++; + } + eicat_ch (ei, '\0'); + SIZED_C_STRING_TO_SIZED_EXTERNAL_MALLOC (eidata (ei), eilen (ei), + dnd_data, *len_out, + encoding); + } + else + { + CHECK_STRING (data); + LISP_STRING_TO_SIZED_EXTERNAL_MALLOC (data, dnd_data, *len_out, + encoding); + *len_out += EXTTEXT_ZTERM_SIZE; + (*num_items_out)++; + } + + /* not so gross hack that converts an emacs event back to a XEvent */ + + x_event->xbutton.type = ButtonPress; + x_event->xbutton.send_event = False; + x_event->xbutton.display = XtDisplayOfObject (wid); + x_event->xbutton.window = XtWindowOfObject (wid); + x_event->xbutton.root = XRootWindow (x_event->xbutton.display, 0); + x_event->xbutton.subwindow = 0; + x_event->xbutton.time = lisp_event->timestamp; + x_event->xbutton.x = EVENT_BUTTON_X (lisp_event); + x_event->xbutton.y = EVENT_BUTTON_Y (lisp_event); + if (Success == XGetWindowAttributes (x_event->xbutton.display, + x_event->xbutton.window, + &win_attrib)) + { + x_event->xbutton.x_root = win_attrib.x + EVENT_BUTTON_X (lisp_event); + x_event->xbutton.y_root = win_attrib.y + EVENT_BUTTON_Y (lisp_event); + } + else + { + x_event->xbutton.x_root = EVENT_BUTTON_X (lisp_event); /* this is wrong */ + x_event->xbutton.y_root = EVENT_BUTTON_Y (lisp_event); + } + + modifier = EVENT_BUTTON_MODIFIERS (lisp_event); + if (modifier & XEMACS_MOD_SHIFT) state |= ShiftMask; + if (modifier & XEMACS_MOD_CONTROL) state |= ControlMask; + if (modifier & XEMACS_MOD_META) state |= xd->MetaMask; + if (modifier & XEMACS_MOD_SUPER) state |= xd->SuperMask; + if (modifier & XEMACS_MOD_HYPER) state |= xd->HyperMask; + if (modifier & XEMACS_MOD_ALT) state |= xd->AltMask; + state |= Button1Mask << (EVENT_BUTTON_BUTTON (lisp_event) - 1); + + x_event->xbutton.state = state; + x_event->xbutton.button = EVENT_BUTTON_BUTTON (lisp_event); + x_event->xbutton.same_screen = True; + + *wid_out = wid; + return dnd_data; +} + +#endif /* defined (HAVE_CDE) || defined (HAVE_OFFIX_DND) */ + #ifdef HAVE_CDE #include <Dt/Dt.h> #include <Dt/Dnd.h> @@ -985,7 +1094,7 @@ XtPointer callData) { DtDndDragFinishCallbackStruct *dragFinishInfo = - (DtDndDragFinishCallbackStruct *)callData; + (DtDndDragFinishCallbackStruct *) callData; DtDndContext *dragData = dragFinishInfo->dragData; int i; @@ -996,7 +1105,7 @@ { for (i = 0; i < dragData->numItems; i++) { - XtFree((char *) dragData->data.buffers[i].bp); + XtFree ((CRawbyte *) dragData->data.buffers[i].bp); if (dragData->data.buffers[i].name) XtFree(dragData->data.buffers[i].name); } @@ -1020,8 +1129,8 @@ { DtDndConvertCallbackStruct *convertInfo = (DtDndConvertCallbackStruct *) callData; - char *textdata = (char *) clientData; - char *textptr = NULL; + Extbyte *textdata = (Extbyte *) clientData; + Extbyte *textptr = NULL; int i; if (convertInfo == NULL) @@ -1036,19 +1145,19 @@ return; } - for (textptr=textdata, i=0; - i<convertInfo->dragData->numItems; - textptr+=strlen(textptr)+1, i++) + for (textptr = textdata, i = 0; + i < convertInfo->dragData->numItems; + textptr += strlen (textptr) + 1, i++) { if (convertInfo->dragData->protocol == DtDND_BUFFER_TRANSFER) { - convertInfo->dragData->data.buffers[i].bp = XtNewString(textptr); - convertInfo->dragData->data.buffers[i].size = strlen(textptr); + convertInfo->dragData->data.buffers[i].bp = XtNewString (textptr); + convertInfo->dragData->data.buffers[i].size = strlen (textptr); convertInfo->dragData->data.buffers[i].name = NULL; } else { - convertInfo->dragData->data.files[i] = XtNewString(textptr); + convertInfo->dragData->data.files[i] = XtNewString (textptr); } } @@ -1056,7 +1165,7 @@ } static Lisp_Object -abort_current_drag(Lisp_Object arg) +abort_current_drag (Lisp_Object arg) { if (CurrentDragWidget && drag_not_done) { @@ -1077,140 +1186,46 @@ */ (event, dragtype, dragdata)) { - if (EVENTP (event)) - { - struct frame *f = decode_x_frame (Fselected_frame (Qnil)); - XEvent x_event; - Widget wid = FRAME_X_TEXT_WIDGET (f); - Display *display = XtDisplayOfObject (wid); - struct device *d = get_device_from_display (display); - struct x_device *xd = DEVICE_X_DATA (d); - XWindowAttributes win_attrib; - int modifier = 0, state = 0; - char *Ctext; - int numItems = 0, textlen = 0, pos = 0; - Lisp_Event *lisp_event = XEVENT (event); - Lisp_Object item = Qnil; - struct gcpro gcpro1; - - /* only drag if this is really a press */ - if (EVENT_TYPE(lisp_event) != button_press_event - || !LISTP(dragdata)) - return Qnil; - - GCPRO1 (item); - - /* - * not so cross hack that converts a emacs event back to a XEvent - */ - - x_event.xbutton.type = ButtonPress; - x_event.xbutton.send_event = False; - x_event.xbutton.display = XtDisplayOfObject(wid); - x_event.xbutton.window = XtWindowOfObject(wid); - x_event.xbutton.root = XRootWindow(x_event.xbutton.display, 0); - x_event.xbutton.subwindow = 0; - x_event.xbutton.time = lisp_event->timestamp; - x_event.xbutton.x = EVENT_BUTTON_X (lisp_event); - x_event.xbutton.y = EVENT_BUTTON_Y (lisp_event); - if (Success == XGetWindowAttributes (x_event.xbutton.display, - x_event.xbutton.window, - &win_attrib)) - { - x_event.xbutton.x_root = win_attrib.x + EVENT_BUTTON_X (lisp_event); - x_event.xbutton.y_root = win_attrib.y + EVENT_BUTTON_Y (lisp_event); - } - else - { - x_event.xbutton.x_root = EVENT_BUTTON_X (lisp_event); /* this is wrong */ - x_event.xbutton.y_root = EVENT_BUTTON_Y (lisp_event); - } - modifier = EVENT_BUTTON_MODIFIERS (lisp_event); - if (modifier & XEMACS_MOD_SHIFT) state |= ShiftMask; - if (modifier & XEMACS_MOD_CONTROL) state |= ControlMask; - if (modifier & XEMACS_MOD_META) state |= xd->MetaMask; - if (modifier & XEMACS_MOD_SUPER) state |= xd->SuperMask; - if (modifier & XEMACS_MOD_HYPER) state |= xd->HyperMask; - if (modifier & XEMACS_MOD_ALT) state |= xd->AltMask; - state |= Button1Mask << (EVENT_BUTTON_BUTTON (lisp_event)-1); - - x_event.xbutton.state = state; - x_event.xbutton.button = EVENT_BUTTON_BUTTON (lisp_event); - x_event.xkey.same_screen = True; - - /* convert data strings into a big string */ - item = dragdata; - while (!NILP (item)) - { - if (!STRINGP (XCAR (item))) - { - numItems=0; - break; - } - textlen += XSTRING_LENGTH (XCAR (item)) + 1; - numItems++; - item = XCDR (item); - } - - if (numItems) - { - /* - * concatenate all strings given to one large string, with - * \0 as separator. List is ended by \0. - */ - Ctext = (char *)xmalloc (textlen+1); - Ctext[0] = 0; - - item = dragdata; - while (!NILP (item)) - { - if (!STRINGP (XCAR (item))) - { - numItems=0; - xfree(Ctext, char *); - Ctext=NULL; - break; - } - strcpy (Ctext+pos, (const char *)XSTRING_DATA (XCAR (item))); - pos += XSTRING_LENGTH (XCAR (item)) + 1; - item = XCDR (item); - } - Ctext[pos] = 0; - - dnd_convert_cb_rec[0].callback = x_cde_convert_callback; - dnd_convert_cb_rec[0].closure = (XtPointer) Ctext; - dnd_convert_cb_rec[1].callback = NULL; - dnd_convert_cb_rec[1].closure = NULL; - - dnd_destroy_cb_rec[0].callback = x_cde_destroy_callback; - dnd_destroy_cb_rec[0].closure = (XtPointer) Ctext; - dnd_destroy_cb_rec[1].callback = NULL; - dnd_destroy_cb_rec[1].closure = NULL; - - CurrentDragWidget = - DtDndDragStart (wid, &x_event, - (NILP(dragtype)?DtDND_BUFFER_TRANSFER:DtDND_FILENAME_TRANSFER), - numItems, - XmDROP_COPY, - dnd_convert_cb_rec, - dnd_destroy_cb_rec, - NULL, 0); - } + Extbyte *dnd_data; + XEvent x_event; + Bytecount dnd_len; + Widget wid; + int num_items; + + dnd_data = start_drag_internal_1 (event, dragdata, Qdt_dnd_encoding, + &x_event, 1, + &wid, &dnd_len, &num_items); + + dnd_convert_cb_rec[0].callback = x_cde_convert_callback; + dnd_convert_cb_rec[0].closure = (XtPointer) dnd_data; + dnd_convert_cb_rec[1].callback = NULL; + dnd_convert_cb_rec[1].closure = NULL; + + dnd_destroy_cb_rec[0].callback = x_cde_destroy_callback; + dnd_destroy_cb_rec[0].closure = (XtPointer) dnd_data; + dnd_destroy_cb_rec[1].callback = NULL; + dnd_destroy_cb_rec[1].closure = NULL; + + CurrentDragWidget = + DtDndDragStart (wid, &x_event, + (NILP (dragtype) ? DtDND_BUFFER_TRANSFER : + DtDND_FILENAME_TRANSFER), + num_items, + XmDROP_COPY, + dnd_convert_cb_rec, + dnd_destroy_cb_rec, + NULL, 0); - UNGCPRO; - - return numItems?Qt:Qnil; - } + xfree (dnd_data, Extbyte *); - return Qnil; + return num_items ? Qt : Qnil; } static void x_cde_transfer_callback (Widget widget, XtPointer clientData, XtPointer callData) { - char *filePath, *hurl; - int ii, enqueue=1; + int ii, enqueue = 1; Lisp_Object frame = Qnil; Lisp_Object l_type = Qnil; Lisp_Object l_data = Qnil; @@ -1239,53 +1254,62 @@ for (ii = 0; ii < transferInfo->dropData->numItems; ii++) { - filePath = transferInfo->dropData->data.files[ii]; - hurl = dnd_url_hexify_string ((char *)filePath, "file:"); - /* #### Mule-izing required */ - l_data = Fcons (make_string ((Ibyte* )hurl, - strlen (hurl)), - l_data); - xfree (hurl, char *); + Ibyte *fileint; + Ibyte *hurl; + + EXTERNAL_TO_C_STRING (transferInfo->dropData->data.files[ii], + fileint, Qfile_name); + + hurl = dnd_url_hexify_string (fileint, "file:"); + l_data = Fcons (build_intstring (hurl), l_data); + xfree (hurl, Ibyte *); } } else if (transferInfo->dropData->protocol == DtDND_BUFFER_TRANSFER) { - int speccount = specpdl_depth(); + int speccount = specpdl_depth (); - /* Problem: all buffers a treated as text/plain!!! - Solution: Also support DtDND_TEXT_TRANSFER + /* !!#### Problem: all buffers a treated as text/plain!!! + Not appropriate for intl text. Note that there is a function + DtDtsBufferToDataType(), but I don't know what the possible + return values are. + Solution (?): Also support DtDND_TEXT_TRANSFER (compound text) perhaps implementation of the Motif protocol (which is the base of CDE) will clear this */ l_type = Qdragdrop_MIME; - record_unwind_protect(abort_current_drag, Qnil); + record_unwind_protect (abort_current_drag, Qnil); drag_not_done = 1; for (ii = 0; ii < transferInfo->dropData->numItems; ii++) { /* let us forget this name thing for now... */ /* filePath = transferInfo->dropData->data.buffers[ii].name; path = (filePath == NULL) ? Qnil - : make_string ((Ibyte *)filePath, strlen (filePath)); */ + : build_ext_string (filePath, Q???); */ /* what, if the data is no text, and how can I tell it? */ - l_data = Fcons ( list3 ( list1 ( make_string ((Ibyte *)"text/plain", 10) ), - make_string ((Ibyte *)"8bit", 4), - make_string ((Ibyte *)transferInfo->dropData->data.buffers[ii].bp, - transferInfo->dropData->data.buffers[ii].size) ), - l_data ); + l_data = + Fcons (list3 (list1 (build_string ("text/plain")), + build_string ("8bit"), + make_ext_string + (transferInfo->dropData->data.buffers[ii].bp, + transferInfo->dropData->data.buffers[ii].size, + /* !!#### what goes here? */ + Qdt_dnd_encoding)), + l_data); } drag_not_done = 0; unbind_to (speccount); } else /* the other cases: NOOP_TRANSFER */ - enqueue=0; + enqueue = 0; /* The Problem: no button and mods from CDE... */ if (enqueue) - enqueue_misc_user_event_pos ( frame, Qdragdrop_drop_dispatch, - Fcons (l_type, l_data), - 0 /* this is the button */, - 0 /* these are the mods */, - transferInfo->x, - transferInfo->y); + enqueue_misc_user_event_pos (frame, Qdragdrop_drop_dispatch, + Fcons (l_type, l_data), + 0 /* this is the button */, + 0 /* these are the mods */, + transferInfo->x, + transferInfo->y); UNGCPRO; return; @@ -1303,115 +1327,30 @@ */ (event, data, dtyp)) { - if (EVENTP(event)) - { - struct frame *f = decode_x_frame (Fselected_frame (Qnil)); - XEvent x_event; - Widget wid = FRAME_X_TEXT_WIDGET (f); - Display *display = XtDisplayOfObject (wid); - struct device *d = get_device_from_display (display); - struct x_device *xd = DEVICE_X_DATA (d); - XWindowAttributes win_attrib; - int modifier = 0, state = 0; - char *dnd_data = NULL; - long dnd_len = 0; - int dnd_typ = DndText, dnd_dealloc = 0; - Lisp_Event *lisp_event = XEVENT (event); - - /* only drag if this is really a press */ - if (EVENT_TYPE(lisp_event) != button_press_event) - return Qnil; - - /* get the desired type */ - if (!NILP (dtyp) && INTP (dtyp)) - dnd_typ = XINT (dtyp); - - if (dnd_typ == DndFiles) - { - Lisp_Object run = data; - int len = 0; - - if (NILP ( Flistp (data))) - return Qnil; - - /* construct the data from a list of files */ - dnd_len = 1; - dnd_data = (char *) xmalloc (1); - *dnd_data = 0; - while (!NILP (run)) - { - if (!STRINGP (XCAR (run))) - { - xfree (dnd_data, char *); - return Qnil; - } - len = XSTRING_LENGTH (XCAR (run)) + 1; - dnd_data = (char *) xrealloc (dnd_data, dnd_len + len); - strcpy (dnd_data + dnd_len - 1, (const char *)XSTRING_DATA (XCAR (run))); - dnd_len += len; - run = XCDR (run); - } - - dnd_data[dnd_len - 1] = 0; /* the list-ending zero */ - dnd_dealloc = 1; + Extbyte *dnd_data; + XEvent x_event; + Bytecount dnd_len; + Widget wid; + int num_items; + int dnd_type = DndText; - } - else - { - if (!STRINGP (data)) - return Qnil; + if (!NILP (dtyp)) + { + CHECK_INT (dtyp); + dnd_type = XINT (dtyp); + } - /* and what's with MULE data ??? */ - dnd_data = (char *)XSTRING_DATA (data); - dnd_len = XSTRING_LENGTH (data) + 1; /* the zero */ + dnd_data = start_drag_internal_1 (event, data, Qoffix_dnd_encoding, + &x_event, dnd_type == DndFiles, + &wid, &dnd_len, &num_items); - } + DndSetData (dnd_type, (UExtbyte *) dnd_data, dnd_len); + xfree (dnd_data, Extbyte *); - /* not so gross hack that converts an emacs event back to a XEvent */ - - x_event.xbutton.type = ButtonPress; - x_event.xbutton.send_event = False; - x_event.xbutton.display = XtDisplayOfObject(wid); - x_event.xbutton.window = XtWindowOfObject(wid); - x_event.xbutton.root = XRootWindow(x_event.xkey.display, 0); - x_event.xbutton.subwindow = 0; - x_event.xbutton.time = lisp_event->timestamp; - x_event.xbutton.x = EVENT_BUTTON_X (lisp_event); - x_event.xbutton.y = EVENT_BUTTON_Y (lisp_event); - if (Success == XGetWindowAttributes (x_event.xbutton.display, - x_event.xbutton.window, - &win_attrib)) - { - x_event.xbutton.x_root = win_attrib.x + EVENT_BUTTON_X (lisp_event); - x_event.xbutton.y_root = win_attrib.y + EVENT_BUTTON_Y (lisp_event); - } - else - { - x_event.xbutton.x_root = EVENT_BUTTON_X (lisp_event); /* this is wrong */ - x_event.xbutton.y_root = EVENT_BUTTON_Y (lisp_event); - } + /* the next thing blocks everything... */ + if (DndHandleDragging (wid, &x_event)) + return Qt; - modifier = EVENT_BUTTON_MODIFIERS (lisp_event); - if (modifier & XEMACS_MOD_SHIFT) state |= ShiftMask; - if (modifier & XEMACS_MOD_CONTROL) state |= ControlMask; - if (modifier & XEMACS_MOD_META) state |= xd->MetaMask; - if (modifier & XEMACS_MOD_SUPER) state |= xd->SuperMask; - if (modifier & XEMACS_MOD_HYPER) state |= xd->HyperMask; - if (modifier & XEMACS_MOD_ALT) state |= xd->AltMask; - state |= Button1Mask << (EVENT_BUTTON_BUTTON (lisp_event)-1); - - x_event.xbutton.state = state; - x_event.xbutton.button = EVENT_BUTTON_BUTTON (lisp_event); - x_event.xkey.same_screen = True; - - DndSetData(dnd_typ, (unsigned char *)dnd_data, dnd_len); - if (dnd_dealloc) - xfree (dnd_data, char *); - - /* the next thing blocks everything... */ - if (DndHandleDragging(wid, &x_event)) - return Qt; - } return Qnil; } @@ -1516,7 +1455,7 @@ unsigned int h = 40; int flags = 0; - char *geom = 0, *ew_geom = 0; + Ascbyte *geom = 0, *ew_geom = 0; Boolean iconic_p = False, ew_iconic_p = False; Widget wmshell = FRAME_X_SHELL_WIDGET (f); @@ -1618,7 +1557,7 @@ /* OK, we're a top-level shell. */ if (!XtIsWMShell (wmshell)) - abort (); + ABORT (); /* If the EmacsFrame doesn't have a geometry but the shell does, treat that as the geometry of the frame. @@ -1846,8 +1785,8 @@ #ifdef EXTERNAL_WIDGET Window window_id = 0; #endif - const char *name; - Arg al [25]; + const Extbyte *name; + Arg al[25]; int ac = 0; Widget text, container, shell; Widget parentwid = 0; @@ -1879,26 +1818,29 @@ #ifndef EXTERNAL_WIDGET if (!NILP (lisp_window_id)) - signal_error (Qunimplemented, "support for external widgets was not enabled at compile-time", Qunbound); + signal_error + (Qunimplemented, + "support for external widgets was not enabled at compile-time", + Qunbound); #else if (!NILP (lisp_window_id)) { - char *string; + Ibyte *string; CHECK_STRING (lisp_window_id); - string = (char *) XSTRING_DATA (lisp_window_id); + string = XSTRING_DATA (lisp_window_id); if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X')) - sscanf (string+2, "%lxu", &window_id); + qxesscanf_ascii_1 (string + 2, "%lxu", &window_id); #if 0 else if (string[0] == 'w') { - sscanf (string+1, "%x", &parent_widget); + qxesscanf_ascii (string + 1, "%x", &parent_widget); if (parent_widget) window_id = XtWindow (parent_widget); } #endif else - sscanf (string, "%lu", &window_id); + qxesscanf_ascii_1 (string, "%lu", &window_id); if (!is_valid_window (window_id, d)) signal_ferror (Qinvalid_argument, "Invalid window %lu", (unsigned long) window_id); @@ -2009,14 +1951,14 @@ ShellWidget shell_widget = (ShellWidget) widget; XtGrabKind call_data = XtGrabNone; - XtCallCallbacks (widget, XtNpopupCallback, (XtPointer)&call_data); + XtCallCallbacks (widget, XtNpopupCallback, (XtPointer) &call_data); shell_widget->shell.popped_up = TRUE; shell_widget->shell.grab_kind = XtGrabNone; shell_widget->shell.spring_loaded = False; if (shell_widget->shell.create_popup_child_proc != NULL) - (*(shell_widget->shell.create_popup_child_proc))(widget); + (*(shell_widget->shell.create_popup_child_proc)) (widget); /* The XtSetValues below are not in XtPopup menu. We just want to make absolutely sure... */ @@ -2113,7 +2055,7 @@ */ XChangeProperty (XtDisplay (frame_widget), XtWindow (frame_widget), DEVICE_XATOM_WM_PROTOCOLS (d), XA_ATOM, 32, PropModeAppend, - (unsigned char*) NULL, 0); + (Rawbyte *) NULL, 0); x_send_synthetic_mouse_event (f); } @@ -2225,9 +2167,9 @@ /* Store the X data into the widget. */ { - Arg al [2]; - XtSetArg (al [0], XtNiconPixmap, x_pixmap); - XtSetArg (al [1], XtNiconMask, x_mask); + Arg al[2]; + XtSetArg (al[0], XtNiconPixmap, x_pixmap); + XtSetArg (al[1], XtNiconMask, x_mask); XtSetValues (FRAME_X_SHELL_WIDGET (f), al, 2); } } @@ -2290,11 +2232,11 @@ Dimension frame_h = DisplayHeight (dpy, DefaultScreen (dpy)); Dimension shell_w, shell_h, shell_bord; int win_gravity; - Arg al [3]; + Arg al[3]; - XtSetArg (al [0], XtNwidth, &shell_w); - XtSetArg (al [1], XtNheight, &shell_h); - XtSetArg (al [2], XtNborderWidth, &shell_bord); + XtSetArg (al[0], XtNwidth, &shell_w); + XtSetArg (al[1], XtNheight, &shell_h); + XtSetArg (al[2], XtNborderWidth, &shell_bord); XtGetValues (w, al, 3); win_gravity = @@ -2311,9 +2253,9 @@ come back at the right place. We can't look at s->visible to determine whether it is iconified because it might not be up-to-date yet (the queue might not be processed). */ - XtSetArg (al [0], XtNwinGravity, win_gravity); - XtSetArg (al [1], XtNx, xoff); - XtSetArg (al [2], XtNy, yoff); + XtSetArg (al[0], XtNwinGravity, win_gravity); + XtSetArg (al[1], XtNx, xoff); + XtSetArg (al[2], XtNy, yoff); XtSetValues (w, al, 3); /* Sometimes you will find that @@ -2684,7 +2626,7 @@ if (FRAME_X_GEOM_FREE_ME_PLEASE (f)) { - xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f), char *); + xfree (FRAME_X_GEOM_FREE_ME_PLEASE (f), Ascbyte *); FRAME_X_GEOM_FREE_ME_PLEASE (f) = 0; } @@ -2696,7 +2638,7 @@ } static void -x_update_frame_external_traits (struct frame* frm, Lisp_Object name) +x_update_frame_external_traits (struct frame *frm, Lisp_Object name) { Arg al[10]; int ac = 0; @@ -2742,7 +2684,7 @@ } } else - abort (); + ABORT (); XtSetValues (FRAME_X_TEXT_WIDGET (frm), al, ac); diff --text -u 'xemacs-21.5.18/src/frame.c' 'xemacs-21.5.19/src/frame.c' Index: ./src/frame.c --- ./src/frame.c Tue Sep 21 04:19:45 2004 +++ ./src/frame.c Fri Feb 4 01:30:36 2005 @@ -144,13 +144,13 @@ static const struct memory_description frame_data_description_1 []= { #ifdef HAVE_GTK - { XD_STRUCT_PTR, gtk_console, 1, >k_frame_data_description}, + { XD_BLOCK_PTR, gtk_console, 1, { >k_frame_data_description} }, #endif #ifdef HAVE_MS_WINDOWS - { XD_STRUCT_PTR, mswindows_console, 1, &mswindows_frame_data_description}, + { XD_BLOCK_PTR, mswindows_console, 1, { &mswindows_frame_data_description} }, #endif #ifdef HAVE_X_WINDOWS - { XD_STRUCT_PTR, x_console, 1, &x_frame_data_description}, + { XD_BLOCK_PTR, x_console, 1, { &x_frame_data_description} }, #endif { XD_END } }; @@ -162,8 +162,8 @@ extern const struct sized_memory_description expose_ignore_description; static const struct memory_description expose_ignore_description_1 [] = { - { XD_STRUCT_PTR, offsetof (struct expose_ignore, next), - 1, &expose_ignore_description }, + { XD_BLOCK_PTR, offsetof (struct expose_ignore, next), + 1, { &expose_ignore_description } }, { XD_END } }; @@ -173,7 +173,7 @@ }; static const struct memory_description display_line_dynarr_pointer_description_1 []= { - { XD_STRUCT_PTR, 0, 1, &display_line_dynarr_description}, + { XD_BLOCK_PTR, 0, 1, { &display_line_dynarr_description} }, { XD_END } }; @@ -188,25 +188,25 @@ { XD_LISP_OBJECT_ARRAY, offsetof (struct frame, slot), size }, #include "frameslots.h" - { XD_STRUCT_PTR, offsetof (struct frame, subwindow_exposures), - 1, &expose_ignore_description }, - { XD_STRUCT_PTR, offsetof (struct frame, subwindow_exposures_tail), - 1, &expose_ignore_description }, + { XD_BLOCK_PTR, offsetof (struct frame, subwindow_exposures), + 1, { &expose_ignore_description } }, + { XD_BLOCK_PTR, offsetof (struct frame, subwindow_exposures_tail), + 1, { &expose_ignore_description } }, #ifdef HAVE_SCROLLBARS { XD_LISP_OBJECT, offsetof (struct frame, sb_vcache) }, { XD_LISP_OBJECT, offsetof (struct frame, sb_hcache) }, #endif /* HAVE_SCROLLBARS */ - { XD_STRUCT_ARRAY, offsetof (struct frame, current_display_lines), - 4, &display_line_dynarr_pointer_description }, - { XD_STRUCT_ARRAY, offsetof (struct frame, desired_display_lines), - 4, &display_line_dynarr_pointer_description }, + { XD_BLOCK_ARRAY, offsetof (struct frame, current_display_lines), + 4, { &display_line_dynarr_pointer_description } }, + { XD_BLOCK_ARRAY, offsetof (struct frame, desired_display_lines), + 4, { &display_line_dynarr_pointer_description } }, - { XD_STRUCT_PTR, offsetof (struct frame, framemeths), 1, - &console_methods_description }, + { XD_BLOCK_PTR, offsetof (struct frame, framemeths), 1, + { &console_methods_description } }, { XD_UNION, offsetof (struct frame, frame_data), - XD_INDIRECT (0, 0), &frame_data_description }, + XD_INDIRECT (0, 0), { &frame_data_description } }, { XD_END } }; @@ -881,7 +881,7 @@ /* use this instead of XFRAME (DEVICE_SELECTED_FRAME (d)) to catch the possibility of there being no frames on the device (just created). There is no point doing this inside of redisplay because errors - cause an abort(), indicating a flaw in the logic, and error_check_frame() + cause an ABORT(), indicating a flaw in the logic, and error_check_frame() will catch this just as well. */ struct frame * @@ -1445,12 +1445,12 @@ FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) { - Lisp_Object this = XCAR (frmcons); + Lisp_Object this_frame = XCAR (frmcons); - if (! EQ (this, frame) + if (! EQ (this_frame, frame) && EQ (frame, (WINDOW_FRAME (XWINDOW - (FRAME_MINIBUF_WINDOW (XFRAME (this))))))) + (FRAME_MINIBUF_WINDOW (XFRAME (this_frame))))))) { /* We've found another frame whose minibuffer is on this frame. */ @@ -1467,14 +1467,14 @@ FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) { - Lisp_Object this = XCAR (frmcons); + Lisp_Object this_frame = XCAR (frmcons); - if (! EQ (this, frame)) + if (! EQ (this_frame, frame)) { struct device *devcons_d = XDEVICE (XCAR (devcons)); if (EQ (frame, DEVMETH_OR_GIVEN (devcons_d, get_frame_parent, - (XFRAME (this)), + (XFRAME (this_frame)), Qnil))) /* We've found a popup frame whose parent is this frame. */ gui_error @@ -1715,22 +1715,22 @@ CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, con) { - Lisp_Object this; + Lisp_Object this_frame; struct frame *f1; - this = XCAR (frmcons); - f1 = XFRAME (this); + this_frame = XCAR (frmcons); + f1 = XFRAME (this_frame); /* Consider only frames on the same console and only those with minibuffers. */ if (FRAME_HAS_MINIBUF_P (f1)) { - frame_with_minibuf = this; + frame_with_minibuf = this_frame; if (FRAME_MINIBUF_ONLY_P (f1)) goto double_break_2; } - frame_on_same_console = this; + frame_on_same_console = this_frame; } double_break_2: @@ -1743,7 +1743,7 @@ that is prohibited at the top; you can't delete surrogate minibuffer frames. */ if (NILP (frame_with_minibuf)) - abort (); + ABORT (); con->default_minibuffer_frame = frame_with_minibuf; } @@ -1825,7 +1825,7 @@ break; default: - abort (); /* method is incorrectly written */ + ABORT (); /* method is incorrectly written */ } return 0; @@ -3213,7 +3213,7 @@ `left' coordinates to be recomputed even though no frame size change occurs. --kyle */ if (in_display || hold_frame_size_changes) - abort (); + ABORT (); frame = wrap_frame (f); diff --text -u 'xemacs-21.5.18/src/free-hook.c' 'xemacs-21.5.19/src/free-hook.c' Index: ./src/free-hook.c --- ./src/free-hook.c Tue Sep 21 04:19:45 2004 +++ ./src/free-hook.c Wed Jan 26 19:36:08 2005 @@ -131,7 +131,8 @@ #endif EMACS_INT present = (EMACS_INT) gethash (ptr, pointer_table, - (const void **) &size); + (const void **) + (void *) &size); if (!present) { @@ -141,7 +142,7 @@ /* I originally wrote: "There's really no need to drop core." I have seen the error of my ways. -slb */ if (strict_free_check) - abort (); + ABORT (); #endif printf("Freeing unmalloc'ed memory at %p\n", ptr); __free_hook = check_free; @@ -155,7 +156,7 @@ #if !defined(__linux__) /* See above comment. */ if (strict_free_check) - abort (); + ABORT (); #endif printf("Freeing %p twice\n", ptr); __free_hook = check_free; @@ -264,7 +265,7 @@ come from malloc. */ #if !defined(__linux__) /* see comment in check_free(). */ - abort (); + ABORT (); #endif printf("Realloc'ing unmalloc'ed pointer at %p\n", ptr); } @@ -445,7 +446,7 @@ note_block_input (char *file, int line) { note_block (file, line, block_type); - if (interrupt_input_blocked > 2) abort(); + if (interrupt_input_blocked > 2) ABORT(); } note_unblock_input (char* file, int line) @@ -485,15 +486,15 @@ if (type == ungcpro_type) { if (value == gcprolist) goto OK; - if (! gcprolist) abort (); + if (! gcprolist) ABORT (); if (value == gcprolist->next) goto OK; - if (! gcprolist->next) abort (); + if (! gcprolist->next) ABORT (); if (value == gcprolist->next->next) goto OK; - if (! gcprolist->next->next) abort (); + if (! gcprolist->next->next) ABORT (); if (value == gcprolist->next->next->next) goto OK; - if (! gcprolist->next->next->next) abort (); + if (! gcprolist->next->next->next) ABORT (); if (value == gcprolist->next->next->next->next) goto OK; - abort (); + ABORT (); OK:; } gcprohist[gcprohistptr].file = file; diff --text -u 'xemacs-21.5.18/src/gccache-gtk.c' 'xemacs-21.5.19/src/gccache-gtk.c' Index: ./src/gccache-gtk.c --- ./src/gccache-gtk.c Sun May 2 13:06:59 2004 +++ ./src/gccache-gtk.c Wed Jan 26 19:22:26 2005 @@ -91,12 +91,12 @@ }; #ifdef GCCACHE_HASH -static unsigned long +static Hashcode gc_cache_hash (const void *arg) { const struct gcv_and_mask *gcvm = (const struct gcv_and_mask *) arg; unsigned long *longs = (unsigned long *) &gcvm->gcv; - unsigned long hash = gcvm->mask; + Hashcode hash = gcvm->mask; unsigned int i; /* This could look at the mask and only use the used slots in the hash code. That would win in that we wouldn't have to initialize @@ -104,7 +104,7 @@ the hash function to be as fast as possible; some timings should be done. */ for (i = 0; i < (sizeof (GdkGCValues) / sizeof (unsigned long)); i++) - hash = (hash<<1) ^ *longs++; + hash = (hash << 1) ^ *longs++; return hash; } @@ -160,8 +160,8 @@ struct gc_cache_cell *cell, *next, *prev; struct gcv_and_mask gcvm; - if ((!!cache->head) != (!!cache->tail)) abort (); - if (cache->head && (cache->head->prev || cache->tail->next)) abort (); + if ((!!cache->head) != (!!cache->tail)) ABORT (); + if (cache->head && (cache->head->prev || cache->tail->next)) ABORT (); /* Gdk does not have the equivalent of 'None' for the clip_mask, so we need to check it carefully, or gdk_gc_new_with_values will @@ -216,10 +216,10 @@ cell->prev = cache->tail; cache->tail->next = cell; cache->tail = cell; - if (cache->head == cell) abort (); - if (cell->next) abort (); - if (cache->head->prev) abort (); - if (cache->tail->next) abort (); + if (cache->head == cell) ABORT (); + if (cell->next) ABORT (); + if (cache->head->prev) ABORT (); + if (cache->tail->next) ABORT (); return cell->gc; } @@ -241,7 +241,7 @@ #endif } else if (cache->size > GC_CACHE_SIZE) - abort (); + ABORT (); else { /* Allocate a new cell (don't put it in the list or table yet). */ diff --text -u 'xemacs-21.5.18/src/glyphs-eimage.c' 'xemacs-21.5.19/src/glyphs-eimage.c' Index: ./src/glyphs-eimage.c --- ./src/glyphs-eimage.c Tue Sep 21 04:19:45 2004 +++ ./src/glyphs-eimage.c Fri Feb 4 12:01:21 2005 @@ -2,7 +2,7 @@ Copyright (C) 1993, 1994, 1998 Free Software Foundation, Inc. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995 Tinker Systems - Copyright (C) 1995, 1996, 2001, 2002 Ben Wing + Copyright (C) 1995, 1996, 2001, 2002, 2004 Ben Wing Copyright (C) 1995 Sun Microsystems This file is part of XEmacs. @@ -104,6 +104,18 @@ BEGIN_C_DECLS +#ifdef WIN32_NATIVE +/* #### Yuck! More horrifitude. tiffio.h, below, includes <windows.h>, + which defines INT32 and INT16, the former differently and incompatibly + from jmorecfg.h, included by jpeglib.h. We can disable the stuff in + jmorecfg.h by defining XMD_H (clever, huh?); then we define these + typedefs the way that <windows.h> wants them (which is more correct, + anyway; jmorecfg.h defines INT32 as `long'). */ +#define XMD_H +typedef signed int INT32; +typedef signed short INT16; +#endif + #include <jpeglib.h> #include <jerror.h> @@ -140,7 +152,7 @@ /* Object that holds state info for JPEG decoding */ struct jpeg_decompress_struct *cinfo_ptr; /* EImage data */ - UChar_Binary *eimage; + Binbyte *eimage; }; static Lisp_Object @@ -157,7 +169,7 @@ retry_fclose (data->instream); if (data->eimage) - xfree (data->eimage, UChar_Binary *); + xfree (data->eimage, Binbyte *); return Qnil; } @@ -375,7 +387,7 @@ { Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); - const UChar_Binary *bytes; + const Binbyte *bytes; Bytecount len; /* #### This is a definite problem under Mule due to the amount of @@ -418,7 +430,8 @@ /* Step 6: Read in the data and put into EImage format (8bit RGB triples)*/ - unwind.eimage = (UChar_Binary*) xmalloc (cinfo.output_width * cinfo.output_height * 3); + unwind.eimage = + xnew_binbytes (cinfo.output_width * cinfo.output_height * 3); if (!unwind.eimage) signal_image_error("Unable to allocate enough memory for image", instantiator); @@ -426,7 +439,7 @@ JSAMPARRAY row_buffer; /* Output row buffer */ JSAMPLE *jp; int row_stride; /* physical row width in output buffer */ - UChar_Binary *op = unwind.eimage; + Binbyte *op = unwind.eimage; /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled @@ -458,11 +471,11 @@ int clr; if (jpeg_gray) { - UChar_Binary val; + Binbyte val; #if (BITS_IN_JSAMPLE == 8) - val = (UChar_Binary) *jp++; + val = (Binbyte) *jp++; #else /* other option is 12 */ - val = (UChar_Binary) (*jp++ >> 4); + val = (Binbyte) (*jp++ >> 4); #endif for (clr = 0; clr < 3; clr++) /* copy the same value into RGB */ *op++ = val; @@ -471,9 +484,9 @@ { for (clr = 0; clr < 3; clr++) #if (BITS_IN_JSAMPLE == 8) - *op++ = (UChar_Binary)*jp++; + *op++ = (Binbyte)*jp++; #else /* other option is 12 */ - *op++ = (UChar_Binary)(*jp++ >> 4); + *op++ = (Binbyte)(*jp++ >> 4); #endif } } @@ -535,7 +548,7 @@ struct gif_unwind_data { - UChar_Binary *eimage; + Binbyte *eimage; /* Object that holds the decoded data from a GIF file */ GifFileType *giffile; }; @@ -553,14 +566,14 @@ GifFree(data->giffile); } if (data->eimage) - xfree (data->eimage, UChar_Binary *); + xfree (data->eimage, Binbyte *); return Qnil; } typedef struct gif_memory_storage { - UChar_Binary *bytes; /* The data */ + Binbyte *bytes; /* The data */ Bytecount len; /* How big is it? */ Bytecount index; /* Where are we? */ } gif_memory_storage; @@ -613,7 +626,7 @@ int speccount = specpdl_depth (); gif_memory_storage mem_struct; struct gif_error_struct gif_err; - UChar_Binary *bytes; + Binbyte *bytes; Bytecount len; int height = 0; int width = 0; @@ -663,7 +676,7 @@ { ColorMapObject *cmo = unwind.giffile->SColorMap; int i, j, row, pass, interlace, slice; - UChar_Binary *eip; + Binbyte *eip; /* interlaced gifs have rows in this order: 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */ static int InterlacedOffset[] = { 0, 4, 2, 1 }; @@ -671,8 +684,8 @@ height = unwind.giffile->SHeight; width = unwind.giffile->SWidth; - unwind.eimage = (UChar_Binary*) - xmalloc (width * height * 3 * unwind.giffile->ImageCount); + unwind.eimage = + xnew_binbytes (width * height * 3 * unwind.giffile->ImageCount); if (!unwind.eimage) signal_image_error("Unable to allocate enough memory for image", instantiator); @@ -703,7 +716,7 @@ eip = unwind.eimage + (width * height * 3 * slice) + (row * width * 3); for (j = 0; j < width; j++) { - UChar_Binary pixel = + Binbyte pixel = unwind.giffile->SavedImages[slice].RasterBits[(i * width) + j]; *eip++ = cmo->Colors[pixel].Red; *eip++ = cmo->Colors[pixel].Green; @@ -778,7 +791,7 @@ struct png_memory_storage { - const UChar_Binary *bytes; /* The data */ + const Binbyte *bytes; /* The data */ Bytecount len; /* How big is it? */ Bytecount index; /* Where are we? */ }; @@ -826,7 +839,7 @@ struct png_unwind_data { FILE *instream; - UChar_Binary *eimage; + Binbyte *eimage; png_structp png_ptr; png_infop info_ptr; }; @@ -844,7 +857,7 @@ retry_fclose (data->instream); if (data->eimage) - xfree(data->eimage, UChar_Binary *); + xfree(data->eimage, Binbyte *); return Qnil; } @@ -904,7 +917,7 @@ /* Initialize the IO layer and read in header information */ { Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); - const UChar_Binary *bytes; + const Binbyte *bytes; Bytecount len; assert (!NILP (data)); @@ -922,12 +935,12 @@ { int y; - UChar_Binary **row_pointers; + Binbyte **row_pointers; height = info_ptr->height; width = info_ptr->width; /* Wow, allocate all the memory. Truly, exciting. */ - unwind.eimage = xnew_array_and_zero (UChar_Binary, width * height * 3); + unwind.eimage = xnew_array_and_zero (Binbyte, width * height * 3); /* libpng expects that the image buffer passed in contains a picture to draw on top of if the png has any transparencies. This could be a good place to pass that in... */ @@ -1026,7 +1039,7 @@ } #endif - xfree (row_pointers, UChar_Binary **); + xfree (row_pointers, Binbyte **); } /* now instantiate */ @@ -1069,7 +1082,7 @@ struct tiff_unwind_data { - UChar_Binary *eimage; + Binbyte *eimage; /* Object that holds the decoded data from a TIFF file */ TIFF *tiff; }; @@ -1086,14 +1099,14 @@ TIFFClose(data->tiff); } if (data->eimage) - xfree (data->eimage, UChar_Binary *); + xfree (data->eimage, Binbyte *); return Qnil; } typedef struct tiff_memory_storage { - UChar_Binary *bytes; /* The data */ + Binbyte *bytes; /* The data */ Bytecount len; /* How big is it? */ Bytecount index; /* Where are we? */ } tiff_memory_storage; @@ -1114,7 +1127,7 @@ tiff_memory_write (thandle_t UNUSED (data), tdata_t UNUSED (buf), tsize_t UNUSED (size)) { - abort(); + ABORT(); return 0; } @@ -1258,11 +1271,11 @@ TIFFSetWarningHandler ((TIFFErrorHandler)tiff_warning_func); { Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); - UChar_Binary *bytes; + Binbyte *bytes; Bytecount len; uint32 *raster; - UChar_Binary *ep; + Binbyte *ep; assert (!NILP (data)); @@ -1285,7 +1298,7 @@ TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height); - unwind.eimage = (UChar_Binary *) xmalloc (width * height * 3); + unwind.eimage = xnew_binbytes (width * height * 3); /* #### This is little more than proof-of-concept/function testing. It needs to be reimplemented via scanline reads for both memory @@ -1306,9 +1319,9 @@ rp = raster + (i * width); for (j = 0; j < (int) width; j++) { - *ep++ = (UChar_Binary)TIFFGetR(*rp); - *ep++ = (UChar_Binary)TIFFGetG(*rp); - *ep++ = (UChar_Binary)TIFFGetB(*rp); + *ep++ = (Binbyte)TIFFGetR(*rp); + *ep++ = (Binbyte)TIFFGetG(*rp); + *ep++ = (Binbyte)TIFFGetB(*rp); rp++; } } diff --text -u 'xemacs-21.5.18/src/glyphs-gtk.c' 'xemacs-21.5.19/src/glyphs-gtk.c' Index: ./src/glyphs-gtk.c --- ./src/glyphs-gtk.c Tue Sep 21 04:19:45 2004 +++ ./src/glyphs-gtk.c Wed Jan 26 19:22:26 2005 @@ -2,7 +2,7 @@ Copyright (C) 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995 Tinker Systems - Copyright (C) 1995, 1996, 2001, 2002 Ben Wing + Copyright (C) 1995, 1996, 2001, 2002, 2004 Ben Wing Copyright (C) 1995 Sun Microsystems This file is part of XEmacs. @@ -401,7 +401,7 @@ #endif else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { - abort(); + ABORT(); } else { @@ -482,7 +482,7 @@ return 1; } -static unsigned long +static Hashcode gtk_image_instance_hash (struct Lisp_Image_Instance *p, int UNUSED (depth)) { switch (IMAGE_INSTANCE_TYPE (p)) @@ -763,7 +763,7 @@ gint width, height, depth; if (!DEVICE_GTK_P (device)) - abort (); + ABORT (); IMAGE_INSTANCE_DEVICE (ii) = device; IMAGE_INSTANCE_TYPE (ii) = IMAGE_COLOR_PIXMAP; @@ -1010,7 +1010,7 @@ break; default: - abort (); + ABORT (); } } @@ -1163,7 +1163,7 @@ int force_mono; gint w, h; struct gcpro gcpro1, gcpro2, gcpro3; - const UChar_Binary * volatile dstring; + const Binbyte * volatile dstring; if (!DEVICE_GTK_P (XDEVICE (device))) gui_error ("Not a Gtk device", device); @@ -1224,9 +1224,9 @@ for (j = 0; j < image.ncolors; j++) { if (image.colorTable[j].symbolic != NULL && - !qxestrcasecmp_c(color_symbols[i].name, image.colorTable[j].symbolic)) + !qxestrcasecmp_ascii(color_symbols[i].name, image.colorTable[j].symbolic)) { - image.colorTable[j].c_color = (char*) xmalloc(16); + image.colorTable[j].c_color = xnew_ascbytes (16); sprintf(image.colorTable[j].c_color, "#%.4x%.4x%.4x", color_symbols[i].color.red, color_symbols[i].color.green, @@ -1304,7 +1304,7 @@ break; default: - abort (); + ABORT (); } UNGCPRO; @@ -1701,7 +1701,7 @@ Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); GdkColor fg, bg; GdkFont *source, *mask; - char source_name[PATH_MAX], mask_name[PATH_MAX], dummy; + char source_name[PATH_MAX_INTERNAL], mask_name[PATH_MAX_INTERNAL], dummy; int source_char, mask_char; int count; Lisp_Object foreground, background; @@ -1929,7 +1929,7 @@ if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { /* We don't support subwindows, but we do support widgets... */ - abort (); + ABORT (); } else /* must be a widget */ { @@ -1952,7 +1952,7 @@ if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { /* No subwindow support... */ - abort (); + ABORT (); } else /* must be a widget */ { @@ -2391,7 +2391,7 @@ else { /* Unknown button type... */ - abort(); + ABORT(); } } diff --text -u 'xemacs-21.5.18/src/glyphs-msw.c' 'xemacs-21.5.19/src/glyphs-msw.c' Index: ./src/glyphs-msw.c --- ./src/glyphs-msw.c Fri Oct 15 02:26:23 2004 +++ ./src/glyphs-msw.c Tue Jan 25 08:33:57 2005 @@ -1,6 +1,6 @@ /* mswindows-specific glyph objects. Copyright (C) 1998, 1999, 2000 Andy Piper. - Copyright (C) 2001, 2002, 2003 Ben Wing. + Copyright (C) 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -162,16 +162,16 @@ /************************************************************************/ static BITMAPINFO *convert_EImage_to_DIBitmap (Lisp_Object device, int width, int height, - UChar_Binary *pic, + Binbyte *pic, int *bit_count, - UChar_Binary **bmp_data) + Binbyte **bmp_data) { struct device *d = XDEVICE (device); int i, j; RGBQUAD *colortbl; int ncolors; BITMAPINFO *bmp_info; - UChar_Binary *ip, *dp; + Binbyte *ip, *dp; if (GetDeviceCaps (get_device_compdc (d), BITSPIXEL) > 0) { @@ -197,7 +197,7 @@ /* bitmap data needs to be in blue, green, red triples - in that order, eimage is in RGB format so we need to convert */ - *bmp_data = xnew_array_and_zero (UChar_Binary, bpline * height); + *bmp_data = xnew_array_and_zero (Binbyte, bpline * height); *bit_count = bpline * height; if (!bmp_data) @@ -237,7 +237,7 @@ return NULL; } - colortbl = (RGBQUAD *) (((UChar_Binary *) bmp_info) + + colortbl = (RGBQUAD *) (((Binbyte *) bmp_info) + sizeof (BITMAPINFOHEADER)); bmp_info->bmiHeader.biBitCount = 8; @@ -246,7 +246,7 @@ bmp_info->bmiHeader.biClrUsed = ncolors; bmp_info->bmiHeader.biClrImportant = ncolors; - *bmp_data = (UChar_Binary *) xmalloc_and_zero (bpline * height); + *bmp_data = xnew_array_and_zero (Binbyte, bpline * height); *bit_count = bpline * height; if (!*bmp_data) @@ -433,14 +433,14 @@ mswindows_init_image_instance_from_eimage (Lisp_Image_Instance *ii, int width, int height, int slices, - UChar_Binary *eimage, + Binbyte *eimage, int dest_mask, Lisp_Object instantiator, Lisp_Object domain) { Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); BITMAPINFO * bmp_info; - UChar_Binary * bmp_data; + Binbyte * bmp_data; int bmp_bits; COLORREF bkcolor; int slice; @@ -473,23 +473,23 @@ instantiator); xfree (bmp_info, BITMAPINFO *); - xfree (bmp_data, UChar_Binary *); + xfree (bmp_data, Binbyte *); } } inline static void -set_mono_pixel (UChar_Binary *bits, +set_mono_pixel (Binbyte *bits, int bpline, int height, int x, int y, int white) { int i; - UChar_Binary bitnum; + Binbyte bitnum; /* Find the byte on which this scanline begins */ i = (height - y - 1) * bpline; /* Find the byte containing this pixel */ i += (x >> 3); /* Which bit is it? */ - bitnum = (UChar_Binary) (7 - (x & 7)); + bitnum = (Binbyte) (7 - (x & 7)); if (white) /* Turn it on */ bits[i] |= (1 << bitnum); else /* Turn it off */ @@ -502,7 +502,7 @@ { HBITMAP mask; HGDIOBJ old = NULL; - UChar_Binary *dibits, *and_bits; + Binbyte *dibits, *and_bits; BITMAPINFO *bmp_info = (BITMAPINFO *) xmalloc_and_zero (sizeof (BITMAPINFO) + sizeof (RGBQUAD)); int i, j; @@ -535,7 +535,10 @@ if (!(mask = CreateDIBSection (hcdc, bmp_info, DIB_RGB_COLORS, - (void **)&and_bits, + /* The intermediate cast fools gcc into + not outputting strict-aliasing + complaints */ + (void **) (void *) &and_bits, 0,0))) { xfree (bmp_info, BITMAPINFO *); @@ -556,7 +559,7 @@ bmp_info->bmiHeader.biClrImportant = 0; bmp_info->bmiHeader.biSizeImage = height * bpline; - dibits = (UChar_Binary *) xmalloc_and_zero (bpline * height); + dibits = xnew_array_and_zero (Binbyte, bpline * height); if (GetDIBits (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (image), 0, @@ -575,7 +578,7 @@ { for (j = 0; j < height; j++) { - UChar_Binary *idx = &dibits[j * bpline + i * 3]; + Binbyte *idx = &dibits[j * bpline + i * 3]; if (RGB (idx[2], idx[1], idx[0]) == transparent_color) { @@ -598,7 +601,7 @@ DIB_RGB_COLORS); xfree (bmp_info, BITMAPINFO *); - xfree (dibits, UChar_Binary *); + xfree (dibits, Binbyte *); SelectObject(hcdc, old); @@ -788,7 +791,7 @@ } static int xpm_to_eimage (Lisp_Object image, const Extbyte *buffer, - UChar_Binary **data, + Binbyte **data, int *width, int *height, int *x_hot, int *y_hot, int *transp, @@ -798,7 +801,7 @@ XpmImage xpmimage; XpmInfo xpminfo; int result, i, j, transp_idx, maskbpline; - UChar_Binary *dptr; + Binbyte *dptr; unsigned int *sptr; COLORREF color; /* the american spelling virus hits again .. */ COLORREF *colortbl; @@ -836,7 +839,7 @@ *height = xpmimage.height; maskbpline = BPLINE ((~7UL & (unsigned long)(*width + 7)) / 8); - *data = xnew_array_and_zero (UChar_Binary, *width * *height * 3); + *data = xnew_array_and_zero (Binbyte, *width * *height * 3); if (!*data) { @@ -849,7 +852,7 @@ colortbl = xnew_array_and_zero (COLORREF, xpmimage.ncolors); if (!colortbl) { - xfree (*data, UChar_Binary *); + xfree (*data, Binbyte *); XpmFreeXpmImage (&xpmimage); XpmFreeXpmInfo (&xpminfo); return 0; @@ -874,7 +877,7 @@ { for (j = 0; j < nsymbols; j++) { - if (!qxestrcmp_c (color_symbols[j].name, + if (!qxestrcmp_ascii (color_symbols[j].name, xpmimage.colorTable[i].symbolic)) { colortbl[i] = color_symbols[j].color; @@ -905,7 +908,7 @@ } label_no_color: - xfree (*data, UChar_Binary *); + xfree (*data, Binbyte *); xfree (colortbl, COLORREF *); XpmFreeXpmImage (&xpmimage); XpmFreeXpmInfo (&xpminfo); @@ -947,10 +950,10 @@ Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); const Extbyte *bytes; Bytecount len; - UChar_Binary *eimage; + Binbyte *eimage; int width, height, x_hot, y_hot; BITMAPINFO* bmp_info; - UChar_Binary* bmp_data; + Binbyte* bmp_data; int bmp_bits; int nsymbols = 0, transp; struct color_symbol* color_symbols = NULL; @@ -995,7 +998,7 @@ signal_image_error ("XPM to EImage conversion failed", image_instance); } - xfree (eimage, UChar_Binary *); + xfree (eimage, Binbyte *); /* Now create the pixmap and set up the image instance */ init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, @@ -1003,7 +1006,7 @@ x_hot, y_hot, transp); xfree (bmp_info, BITMAPINFO *); - xfree (bmp_data, UChar_Binary *); + xfree (bmp_data, Binbyte *); } #endif /* HAVE_XPM */ @@ -1335,15 +1338,15 @@ byte order from left to right, big-endian within a byte. 0 = black, 1 = white. */ static HBITMAP -xbm_create_bitmap_from_data (HDC hdc, const UChar_Binary *data, +xbm_create_bitmap_from_data (HDC hdc, const Binbyte *data, int width, int height, int mask, COLORREF fg, COLORREF bg) { int old_width = (width + 7)/8; int new_width = BPLINE (2 * ((width + 15)/16)); - const UChar_Binary *offset; + const Binbyte *offset; void *bmp_buf = 0; - UChar_Binary *new_data, *new_offset; + Binbyte *new_data, *new_offset; int i, j; BITMAPINFO *bmp_info = (BITMAPINFO *) xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD)); @@ -1352,7 +1355,7 @@ if (!bmp_info) return NULL; - new_data = (UChar_Binary *) xmalloc_and_zero (height * new_width); + new_data = xnew_array_and_zero (Binbyte, height * new_width); if (!new_data) { @@ -1368,7 +1371,7 @@ for (j = 0; j < old_width; j++) { int bite = offset[j]; - new_offset[j] = ~ (UChar_Binary) + new_offset[j] = ~ (Binbyte) ((flip_table[bite & 0xf] << 4) + flip_table[bite >> 4]); } } @@ -1411,13 +1414,13 @@ if (!bitmap || !bmp_buf) { - xfree (new_data, UChar_Binary *); + xfree (new_data, Binbyte *); return NULL; } /* copy in the actual bitmap */ memcpy (bmp_buf, new_data, height * new_width); - xfree (new_data, UChar_Binary *); + xfree (new_data, Binbyte *); return bitmap; } @@ -1428,7 +1431,7 @@ static void init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii, int width, int height, - const UChar_Binary *bits, + const Binbyte *bits, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, @@ -1548,7 +1551,7 @@ break; default: - abort (); + ABORT (); } } @@ -1556,7 +1559,7 @@ xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, int dest_mask, int width, int height, - const UChar_Binary *bits) + const Binbyte *bits) { Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data); Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file); @@ -1566,7 +1569,7 @@ if (!NILP (mask_data)) { - UChar_Binary *ext_data; + Binbyte *ext_data; TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))), C_STRING_ALLOCA, ext_data, @@ -1594,7 +1597,7 @@ int dest_mask, Lisp_Object UNUSED (domain)) { Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); - const UChar_Binary *ext_data; + const Binbyte *ext_data; assert (!NILP (data)); @@ -1619,6 +1622,9 @@ instead of strings.h. */ #define SYSV32 BEGIN_C_DECLS +#ifndef __STDC__ /* Needed to avoid prototype warnings */ +#define __STDC__ +#endif #include <compface.h> END_C_DECLS @@ -1636,9 +1642,9 @@ { Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); int i, stattis; - UChar_Binary *p, *bits, *bp; + Binbyte *p, *bits, *bp; const CIbyte * volatile emsg = 0; - const UChar_Binary * volatile dstring; + const Binbyte * volatile dstring; assert (!NILP (data)); @@ -1646,7 +1652,7 @@ C_STRING_ALLOCA, dstring, Qbinary); - if ((p = (UChar_Binary *) strchr ((char *) dstring, ':'))) + if ((p = (Binbyte *) strchr ((char *) dstring, ':'))) { dstring = p + 1; } @@ -1674,11 +1680,11 @@ if (emsg) signal_image_error_2 (emsg, data, Qimage); - bp = bits = (UChar_Binary *) ALLOCA (PIXELS / 8); + bp = bits = alloca_binbytes (PIXELS / 8); /* the compface library exports char F[], which uses a single byte per pixel to represent a 48x48 bitmap. Yuck. */ - for (i = 0, p = (UChar_Binary *) F; i < (PIXELS / 8); ++i) + for (i = 0, p = (Binbyte *) F; i < (PIXELS / 8); ++i) { int n, b; /* reverse the bit order of each byte... */ @@ -1686,7 +1692,7 @@ { n |= ((*p++) << b); } - *bp++ = (UChar_Binary) n; + *bp++ = (Binbyte) n; } xbm_instantiate_1 (image_instance, instantiator, pointer_fg, @@ -2483,7 +2489,7 @@ else LISP_STRING_TO_TSTR (item, tvitem.item.pszText); - tvitem.item.cchTextMax = xetcslen ((Extbyte *) tvitem.item.pszText); + tvitem.item.cchTextMax = qxetcslen ((Extbyte *) tvitem.item.pszText); if ((ret = (HTREEITEM) qxeSendMessage (wnd, TVM_INSERTITEM, 0, (LPARAM) &tvitem)) == 0) @@ -2602,7 +2608,7 @@ LISP_STRING_TO_TSTR (item, tcitem.pszText); } - tcitem.cchTextMax = xetcslen ((Extbyte *) tcitem.pszText); + tcitem.cchTextMax = qxetcslen ((Extbyte *) tcitem.pszText); if ((ret = qxeSendMessage (wnd, TCM_INSERTITEM, i, (LPARAM) &tcitem)) < 0) gui_error ("error adding tab entry", item); @@ -2821,7 +2827,7 @@ if (EQ (prop, Q_text)) { Charcount tchar_len = qxeSendMessage (wnd, WM_GETTEXTLENGTH, 0, 0); - Extbyte *buf = (Extbyte *) ALLOCA (XETCHAR_SIZE * (tchar_len + 1)); + Extbyte *buf = alloca_extbytes (XETCHAR_SIZE * (tchar_len + 1)); qxeSendMessage (wnd, WM_GETTEXT, (WPARAM)tchar_len + 1, (LPARAM) buf); return build_tstr_string (buf); @@ -2858,7 +2864,7 @@ long item = qxeSendMessage (wnd, CB_GETCURSEL, 0, 0); Charcount tchar_len = qxeSendMessage (wnd, CB_GETLBTEXTLEN, (WPARAM)item, 0); - Extbyte *buf = (Extbyte *) ALLOCA (XETCHAR_SIZE * (tchar_len + 1)); + Extbyte *buf = alloca_extbytes (XETCHAR_SIZE * (tchar_len + 1)); qxeSendMessage (wnd, CB_GETLBTEXT, (WPARAM)item, (LPARAM) buf); return build_tstr_string (buf); } diff --text -u 'xemacs-21.5.18/src/glyphs-shared.c' 'xemacs-21.5.19/src/glyphs-shared.c' Index: ./src/glyphs-shared.c --- ./src/glyphs-shared.c Tue Sep 21 04:19:46 2004 +++ ./src/glyphs-shared.c Fri Nov 5 08:06:33 2004 @@ -190,14 +190,14 @@ * like the Xlib routine XReadBitmapfile as possible. */ static int -read_bitmap_data (FILE *fstream, int *width, int *height, UChar_Binary **datap, +read_bitmap_data (FILE *fstream, int *width, int *height, Binbyte **datap, int *x_hot, int *y_hot) { - UChar_Binary *data = NULL; /* working variable */ - Char_ASCII line[MAX_SIZE]; /* input line from file */ + Binbyte *data = NULL; /* working variable */ + Ascbyte line[MAX_SIZE]; /* input line from file */ int size; /* number of bytes of data */ - Char_ASCII name_and_type[MAX_SIZE]; /* an input line */ - Char_ASCII *type; /* for parsing */ + Ascbyte name_and_type[MAX_SIZE]; /* an input line */ + Ascbyte *type; /* for parsing */ int value; /* from an input line */ int version10p; /* boolean, old format */ int padding; /* to handle alignment */ @@ -270,12 +270,12 @@ bytes_per_line = (ww+7)/8 + padding; size = bytes_per_line * hh; - data = (UChar_Binary *) Xmalloc ((unsigned int) size); + data = (Binbyte *) Xmalloc ((unsigned int) size); if (!data) RETURN (BitmapNoMemory); if (version10p) { - UChar_Binary *ptr; + Binbyte *ptr; int bytes; for (bytes=0, ptr=data; bytes<size; (bytes += 2)) { @@ -286,7 +286,7 @@ *(ptr++) = value >> 8; } } else { - UChar_Binary *ptr; + Binbyte *ptr; int bytes; for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) { @@ -318,7 +318,7 @@ /* Remaining args are RETURNED */ int *width, int *height, - UChar_Binary **datap, + Binbyte **datap, int *x_hot, int *y_hot) { FILE *fstream; diff --text -u 'xemacs-21.5.18/src/glyphs-widget.c' 'xemacs-21.5.19/src/glyphs-widget.c' Index: ./src/glyphs-widget.c --- ./src/glyphs-widget.c Wed Sep 22 11:06:48 2004 +++ ./src/glyphs-widget.c Fri Nov 5 08:06:33 2004 @@ -187,31 +187,25 @@ static void check_valid_item_list (Lisp_Object items) { - Lisp_Object rest; - - CHECK_LIST (items); - EXTERNAL_LIST_LOOP (rest, items) + EXTERNAL_LIST_LOOP_2 (elt, items) { - if (STRINGP (XCAR (rest))) - CHECK_STRING (XCAR (rest)); - else if (VECTORP (XCAR (rest))) - gui_parse_item_keywords (XCAR (rest)); - else if (LISTP (XCAR (rest))) - check_valid_item_list (XCAR (rest)); + if (STRINGP (elt)) + CHECK_STRING (elt); + else if (VECTORP (elt)) + gui_parse_item_keywords (elt); + else if (LISTP (elt)) + check_valid_item_list (elt); else - invalid_argument ("Items must be vectors, lists or strings", items); + invalid_argument ("Item must be vector, list or string", elt); } } static void check_valid_instantiator_list (Lisp_Object data) { - Lisp_Object rest; - - CHECK_LIST (data); - EXTERNAL_LIST_LOOP (rest, data) + EXTERNAL_LIST_LOOP_2 (elt, data) { - check_valid_instantiator (XCAR (rest)); + check_valid_instantiator (elt); } } @@ -1952,7 +1946,6 @@ void vars_of_glyphs_widget (void) { - reinit_vars_of_glyphs_widget (); } diff --text -u 'xemacs-21.5.18/src/glyphs-x.c' 'xemacs-21.5.19/src/glyphs-x.c' Index: ./src/glyphs-x.c --- ./src/glyphs-x.c Tue Sep 21 04:19:46 2004 +++ ./src/glyphs-x.c Tue Jan 25 08:33:58 2005 @@ -2,7 +2,7 @@ Copyright (C) 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995 Tinker Systems - Copyright (C) 1995, 1996, 2001, 2002, 2003 Ben Wing + Copyright (C) 1995, 1996, 2001, 2002, 2003, 2004 Ben Wing Copyright (C) 1995 Sun Microsystems Copyright (C) 1999, 2000, 2002 Andy Piper @@ -163,7 +163,7 @@ /************************************************************************/ static XImage * convert_EImage_to_XImage (Lisp_Object device, int width, int height, - UChar_Binary *pic, unsigned long **pixtbl, + Binbyte *pic, unsigned long **pixtbl, int *npixels) { Display *dpy; @@ -172,7 +172,7 @@ XImage *outimg; int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j; int rd,gr,bl,q; - UChar_Binary *data, *ip, *dp; + Binbyte *data, *ip, *dp; quant_table *qtable = 0; union { UINT_32_BIT val; @@ -211,7 +211,7 @@ bits_per_pixel = outimg->bits_per_pixel; byte_cnt = bits_per_pixel >> 3; - data = (UChar_Binary *) xmalloc (outimg->bytes_per_line * height); + data = xnew_binbytes (outimg->bytes_per_line * height); if (!data) { XDestroyImage (outimg); @@ -843,7 +843,7 @@ x_init_image_instance_from_eimage (Lisp_Image_Instance *ii, int width, int height, int slices, - UChar_Binary *eimage, + Binbyte *eimage, int dest_mask, Lisp_Object instantiator, Lisp_Object UNUSED (domain)) @@ -893,7 +893,7 @@ static Pixmap pixmap_from_xbm_inline (Lisp_Object device, int width, int height, - Char_Binary *bits) + CBinbyte *bits) { return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE (device)), XtWindow (DEVICE_XT_APP_SHELL @@ -908,7 +908,7 @@ static void init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii, int width, int height, - Char_Binary *bits, + CBinbyte *bits, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, @@ -995,7 +995,7 @@ IMAGE_INSTANCE_PIXMAP_BG (ii) = background; IMAGE_INSTANCE_X_PIXMAP (ii) = XCreatePixmapFromBitmapData (dpy, draw, - (Char_Binary *) bits, width, height, + (CBinbyte *) bits, width, height, fg, bg, d); IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d; } @@ -1010,7 +1010,7 @@ source = XCreatePixmapFromBitmapData (dpy, draw, - (Char_Binary *) bits, width, height, + (CBinbyte *) bits, width, height, 1, 0, 1); if (NILP (foreground)) @@ -1037,7 +1037,7 @@ break; default: - abort (); + ABORT (); } } @@ -1045,7 +1045,7 @@ xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, int dest_mask, int width, int height, - Char_Binary *bits) + CBinbyte *bits) { Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data); Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file); @@ -1054,7 +1054,7 @@ if (!NILP (mask_data)) { - Char_Binary *ext_data; + CBinbyte *ext_data; LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (mask_data))), ext_data, Qbinary); @@ -1077,7 +1077,7 @@ int dest_mask, Lisp_Object UNUSED (domain)) { Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); - Char_Binary *ext_data; + CBinbyte *ext_data; assert (!NILP (data)); @@ -1164,7 +1164,7 @@ /* Duplicate the pixel value so that we still have a lock on it if the pixel we were passed is later freed. */ if (! XAllocColor (dpy, cmap, &color)) - abort (); /* it must be allocable since we're just duplicating it */ + ABORT (); /* it must be allocable since we're just duplicating it */ TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (cons), C_STRING_MALLOC, symbols[i].name, Qctext); @@ -1524,7 +1524,7 @@ break; default: - abort (); + ABORT (); } xpm_free (&xpmattrs); /* after we've read pixels and hotspot */ @@ -1562,9 +1562,9 @@ { Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); int i, stattis; - UChar_Binary *p, *bits, *bp; + Binbyte *p, *bits, *bp; const CIbyte * volatile emsg = 0; - const UChar_Binary * volatile dstring; + const Binbyte * volatile dstring; assert (!NILP (data)); @@ -1572,7 +1572,7 @@ C_STRING_ALLOCA, dstring, Qbinary); - if ((p = (UChar_Binary *) strchr ((char *) dstring, ':'))) + if ((p = (Binbyte *) strchr ((char *) dstring, ':'))) { dstring = p + 1; } @@ -1600,11 +1600,11 @@ if (emsg) signal_image_error_2 (emsg, data, Qimage); - bp = bits = (UChar_Binary *) ALLOCA (PIXELS / 8); + bp = bits = alloca_binbytes (PIXELS / 8); /* the compface library exports char F[], which uses a single byte per pixel to represent a 48x48 bitmap. Yuck. */ - for (i = 0, p = (UChar_Binary *) F; i < (PIXELS / 8); ++i) + for (i = 0, p = (Binbyte *) F; i < (PIXELS / 8); ++i) { int n, b; /* reverse the bit order of each byte... */ @@ -1612,11 +1612,11 @@ { n |= ((*p++) << b); } - *bp++ = (UChar_Binary) n; + *bp++ = (Binbyte) n; } xbm_instantiate_1 (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, 48, 48, (Char_Binary *) bits); + pointer_bg, dest_mask, 48, 48, (CBinbyte *) bits); } #endif /* HAVE_XFACE */ @@ -1838,7 +1838,7 @@ Display *dpy; XColor fg, bg; Font source, mask; - Ibyte source_name[PATH_MAX], mask_name[PATH_MAX], dummy; + Ibyte source_name[PATH_MAX_INTERNAL], mask_name[PATH_MAX_INTERNAL], dummy; int source_char, mask_char; int count; Lisp_Object foreground, background; diff --text -u 'xemacs-21.5.18/src/glyphs.c' 'xemacs-21.5.19/src/glyphs.c' Index: ./src/glyphs.c --- ./src/glyphs.c Wed Sep 22 11:06:48 2004 +++ ./src/glyphs.c Fri Feb 4 01:14:06 2005 @@ -1,7 +1,7 @@ /* Generic glyph/image implementation + display tables Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. Copyright (C) 1995 Tinker Systems - Copyright (C) 1995, 1996, 2000, 2001, 2002 Ben Wing + Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004 Ben Wing Copyright (C) 1995 Sun Microsystems Copyright (C) 1998, 1999, 2000 Andy Piper @@ -303,15 +303,12 @@ */ (console_type, list)) { - Lisp_Object tail; Lisp_Object *imlist = get_image_conversion_list (console_type); /* Check the list to make sure that it only has valid entries. */ - EXTERNAL_LIST_LOOP (tail, list) + EXTERNAL_LIST_LOOP_2 (mapping, list) { - Lisp_Object mapping = XCAR (tail); - /* Mapping form should be (STRING VECTOR) or (STRING VECTOR INTEGER) */ if (!CONSP (mapping) || !CONSP (XCDR (mapping)) || @@ -714,7 +711,7 @@ else if (governing_domain == GOVERNING_DOMAIN_DEVICE) domain = DOMAIN_DEVICE (domain); else - abort (); + ABORT (); return domain; } @@ -878,14 +875,14 @@ }; static const struct memory_description image_instance_data_description_1 [] = { - { XD_STRUCT_ARRAY, IMAGE_TEXT, - 1, &text_image_instance_description }, - { XD_STRUCT_ARRAY, IMAGE_MONO_PIXMAP, - 1, &pixmap_image_instance_description }, - { XD_STRUCT_ARRAY, IMAGE_COLOR_PIXMAP, - 1, &pixmap_image_instance_description }, - { XD_STRUCT_ARRAY, IMAGE_WIDGET, - 1, &subwindow_image_instance_description }, + { XD_BLOCK_ARRAY, IMAGE_TEXT, + 1, { &text_image_instance_description } }, + { XD_BLOCK_ARRAY, IMAGE_MONO_PIXMAP, + 1, { &pixmap_image_instance_description } }, + { XD_BLOCK_ARRAY, IMAGE_COLOR_PIXMAP, + 1, { &pixmap_image_instance_description } }, + { XD_BLOCK_ARRAY, IMAGE_WIDGET, + 1, { &subwindow_image_instance_description } }, { XD_END } }; @@ -901,7 +898,7 @@ { XD_LISP_OBJECT, offsetof (Lisp_Image_Instance, parent) }, { XD_LISP_OBJECT, offsetof (Lisp_Image_Instance, instantiator) }, { XD_UNION, offsetof (struct Lisp_Image_Instance, u), - XD_INDIRECT (0, 0), &image_instance_data_description }, + XD_INDIRECT (0, 0), { &image_instance_data_description } }, { XD_END } }; @@ -1090,7 +1087,7 @@ break; default: - abort (); + ABORT (); } MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), print_image_instance, @@ -1212,7 +1209,7 @@ break; default: - abort (); + ABORT (); } return DEVMETH_OR_GIVEN (DOMAIN_XDEVICE (i1->domain), @@ -1291,7 +1288,7 @@ break; default: - abort (); + ABORT (); } return HASH2 (hash, DEVMETH_OR_GIVEN @@ -1376,7 +1373,7 @@ case IMAGE_SUBWINDOW: return Qsubwindow; case IMAGE_WIDGET: return Qwidget; default: - abort (); + ABORT (); } return Qnil; /* not reached */ @@ -1385,7 +1382,6 @@ static int decode_image_instance_type_list (Lisp_Object list) { - Lisp_Object rest; int mask = 0; if (NILP (list)) @@ -1398,12 +1394,14 @@ return image_instance_type_to_mask (type); } - EXTERNAL_LIST_LOOP (rest, list) - { - enum image_instance_type type = - decode_image_instance_type (XCAR (rest), ERROR_ME); - mask |= image_instance_type_to_mask (type); - } + { + EXTERNAL_LIST_LOOP_2 (elt, list) + { + enum image_instance_type type = + decode_image_instance_type (elt, ERROR_ME); + mask |= image_instance_type_to_mask (type); + } + } return mask; } @@ -2301,7 +2299,7 @@ int UNUSED (dest_mask), Lisp_Object UNUSED (domain)) { /* handled specially in image_instantiate */ - abort (); + ABORT (); } @@ -2668,7 +2666,7 @@ int ok_if_data_invalid) { int w, h; - UChar_Binary *data; + Binbyte *data; int result; result = read_bitmap_data_from_file (name, &w, &h, &data, xhot, yhot); @@ -2919,11 +2917,13 @@ Lisp_Object pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid) { - char **data; + Ascbyte **data; int result; - char *fname = 0; + Extbyte *fname = 0; + Ibyte *resolved; - LISP_STRING_TO_EXTERNAL (name, fname, Qfile_name); + LISP_PATHNAME_RESOLVE_LINKS (name, resolved); + C_STRING_TO_EXTERNAL (resolved, fname, Qfile_name); result = XpmReadFileToData (fname, &data); if (result == XpmSuccess) @@ -3339,7 +3339,7 @@ Qunbound); } else - abort (); /* We're not allowed anything else currently. */ + ABORT (); /* We're not allowed anything else currently. */ /* If we don't have an instance at this point then create one. */ @@ -3416,7 +3416,7 @@ RETURN_UNGCPRO (instance); } - abort (); + ABORT (); return Qnil; /* not reached */ } @@ -3812,7 +3812,7 @@ | IMAGE_COLOR_PIXMAP_MASK; break; default: - abort (); + ABORT (); } /* I think Fmake_specifier can GC. I think set_specifier_fallback can GC. */ @@ -3937,7 +3937,7 @@ CHECK_GLYPH (glyph); switch (XGLYPH_TYPE (glyph)) { - default: abort (); + default: ABORT (); case GLYPH_BUFFER: return Qbuffer; case GLYPH_POINTER: return Qpointer; case GLYPH_ICON: return Qicon; @@ -5020,7 +5020,7 @@ continue; } else - abort (); + ABORT (); } } @@ -5264,7 +5264,8 @@ static const struct memory_description iife_description_1[] = { { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, symbol) }, { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, device) }, - { XD_STRUCT_PTR, offsetof (image_instantiator_format_entry, meths), 1, &iim_description }, + { XD_BLOCK_PTR, offsetof (image_instantiator_format_entry, meths), 1, + { &iim_description } }, { XD_END } }; @@ -5286,8 +5287,10 @@ static const struct memory_description iim_description_1[] = { { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, symbol) }, { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, device) }, - { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, keywords), 1, &iiked_description }, - { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, consoles), 1, &cted_description }, + { XD_BLOCK_PTR, offsetof (struct image_instantiator_methods, keywords), 1, + { &iiked_description } }, + { XD_BLOCK_PTR, offsetof (struct image_instantiator_methods, consoles), 1, + { &cted_description } }, { XD_END } }; @@ -5307,7 +5310,7 @@ Vimage_instantiator_format_list = Qnil; staticpro (&Vimage_instantiator_format_list); - dump_add_root_struct_ptr (&the_image_instantiator_format_entry_dynarr, &iifed_description); + dump_add_root_block_ptr (&the_image_instantiator_format_entry_dynarr, &iifed_description); INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing"); @@ -5418,8 +5421,6 @@ void vars_of_glyphs (void) { - reinit_vars_of_glyphs (); - Vthe_nothing_vector = vector1 (Qnothing); staticpro (&Vthe_nothing_vector); @@ -5435,34 +5436,6 @@ Vglyph_type_list = list3 (Qbuffer, Qpointer, Qicon); staticpro (&Vglyph_type_list); - /* The octal-escape glyph, control-arrow-glyph and - invisible-text-glyph are completely initialized in glyphs.el */ - - DEFVAR_LISP ("octal-escape-glyph", &Voctal_escape_glyph /* -What to prefix character codes displayed in octal with. -*/); - Voctal_escape_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed); - - DEFVAR_LISP ("control-arrow-glyph", &Vcontrol_arrow_glyph /* -What to use as an arrow for control characters. -*/); - Vcontrol_arrow_glyph = allocate_glyph (GLYPH_BUFFER, - redisplay_glyph_changed); - - DEFVAR_LISP ("invisible-text-glyph", &Vinvisible_text_glyph /* -What to use to indicate the presence of invisible text. -This is the glyph that is displayed when an ellipsis is called for -\(see `selective-display-ellipses' and `buffer-invisibility-spec'). -Normally this is three dots ("..."). -*/); - Vinvisible_text_glyph = allocate_glyph (GLYPH_BUFFER, - redisplay_glyph_changed); - - /* Partially initialized in glyphs.el */ - DEFVAR_LISP ("hscroll-glyph", &Vhscroll_glyph /* -What to display at the beginning of horizontally scrolled lines. -*/); - Vhscroll_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed); #ifdef HAVE_WINDOW_SYSTEM Fprovide (Qxbm); #endif @@ -5575,6 +5548,35 @@ */ ); Vcontinuation_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed); + /* The octal-escape glyph, control-arrow-glyph and + invisible-text-glyph are completely initialized in glyphs.el */ + + DEFVAR_LISP ("octal-escape-glyph", &Voctal_escape_glyph /* +What to prefix character codes displayed in octal with. +*/); + Voctal_escape_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed); + + DEFVAR_LISP ("control-arrow-glyph", &Vcontrol_arrow_glyph /* +What to use as an arrow for control characters. +*/); + Vcontrol_arrow_glyph = allocate_glyph (GLYPH_BUFFER, + redisplay_glyph_changed); + + DEFVAR_LISP ("invisible-text-glyph", &Vinvisible_text_glyph /* +What to use to indicate the presence of invisible text. +This is the glyph that is displayed when an ellipsis is called for +\(see `selective-display-ellipses' and `buffer-invisibility-spec'). +Normally this is three dots ("..."). +*/); + Vinvisible_text_glyph = allocate_glyph (GLYPH_BUFFER, + redisplay_glyph_changed); + + /* Partially initialized in glyphs.el */ + DEFVAR_LISP ("hscroll-glyph", &Vhscroll_glyph /* +What to display at the beginning of horizontally scrolled lines. +*/); + Vhscroll_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed); + /* Partially initialized in glyphs-x.c, glyphs.el */ DEFVAR_LISP ("xemacs-logo", &Vxemacs_logo /* The glyph used to display the XEmacs logo at startup. diff --text -u 'xemacs-21.5.18/src/glyphs.h' 'xemacs-21.5.19/src/glyphs.h' Index: ./src/glyphs.h --- ./src/glyphs.h Wed Sep 15 05:54:37 2004 +++ ./src/glyphs.h Fri Nov 5 08:06:34 2004 @@ -234,7 +234,7 @@ Dynarr_new (console_type_entry); \ add_entry_to_image_instantiator_format_list \ (Q##format, format##_image_instantiator_methods); \ - dump_add_root_struct_ptr (&format##_image_instantiator_methods, \ + dump_add_root_block_ptr (&format##_image_instantiator_methods, \ &iim_description); \ } while (0) @@ -312,7 +312,7 @@ add_entry_to_device_ii_format_list \ (Q##type, Q##format, type##_##format##_image_instantiator_methods); \ IIFORMAT_VALID_CONSOLE(type,format); \ - dump_add_root_struct_ptr (&type##_##format##_image_instantiator_methods, \ + dump_add_root_block_ptr (&type##_##format##_image_instantiator_methods, \ &iim_description); \ } while (0) @@ -925,7 +925,7 @@ Lisp_Object bitmap_to_lisp_data (Lisp_Object name, int *xhot, int *yhot, int ok_if_data_invalid); int read_bitmap_data_from_file (Lisp_Object filename, int *width, - int *height, UChar_Binary **datap, + int *height, Binbyte **datap, int *x_hot, int *y_hot); Lisp_Object xbm_mask_file_munging (Lisp_Object alist, Lisp_Object file, Lisp_Object mask_file, diff --text -u 'xemacs-21.5.18/src/gtk-glue.c' 'xemacs-21.5.19/src/gtk-glue.c' Index: ./src/gtk-glue.c --- ./src/gtk-glue.c Sun May 2 13:07:00 2004 +++ ./src/gtk-glue.c Tue Jan 25 08:33:59 2005 @@ -93,7 +93,7 @@ } else { - abort(); + ABORT(); } } @@ -130,7 +130,7 @@ } else { - abort(); + ABORT(); } } return (rval); @@ -181,7 +181,7 @@ } else { - abort(); + ABORT(); } #undef FROB } diff --text -u 'xemacs-21.5.18/src/gui-gtk.c' 'xemacs-21.5.19/src/gui-gtk.c' Index: ./src/gui-gtk.c --- ./src/gui-gtk.c Wed Jul 7 21:01:07 2004 +++ ./src/gui-gtk.c Fri Feb 4 01:30:37 2005 @@ -57,19 +57,19 @@ ungcpro_popup_callbacks (GUI_ID id) { Lisp_Object lid = make_int (id); - Lisp_Object this = assq_no_quit (lid, Vpopup_callbacks); - Vpopup_callbacks = delq_no_quit (this, Vpopup_callbacks); + Lisp_Object this_callback = assq_no_quit (lid, Vpopup_callbacks); + Vpopup_callbacks = delq_no_quit (this_callback, Vpopup_callbacks); } Lisp_Object get_gcpro_popup_callbacks (GUI_ID id) { Lisp_Object lid = make_int (id); - Lisp_Object this = assq_no_quit (lid, Vpopup_callbacks); + Lisp_Object this_callback = assq_no_quit (lid, Vpopup_callbacks); - if (!NILP (this)) + if (!NILP (this_callback)) { - return (XCDR (this)); + return (XCDR (this_callback)); } return (Qnil); } diff --text -u 'xemacs-21.5.18/src/gui-msw.c' 'xemacs-21.5.19/src/gui-msw.c' Index: ./src/gui-msw.c --- ./src/gui-msw.c Tue Sep 21 04:19:47 2004 +++ ./src/gui-msw.c Fri Nov 5 08:06:34 2004 @@ -115,7 +115,7 @@ mswindows_translate_menu_or_dialog_item (Lisp_Object item, Ichar *accel) { Bytecount len = XSTRING_LENGTH (item); - Ibyte *it = (Ibyte *) ALLOCA (2 * len + 42), *ptr = it; + Ibyte *it = alloca_ibytes (2 * len + 42), *ptr = it; memcpy (ptr, XSTRING_DATA (item), len + 1); if (accel) diff --text -u 'xemacs-21.5.18/src/gui-x.c' 'xemacs-21.5.19/src/gui-x.c' Index: ./src/gui-x.c --- ./src/gui-x.c Tue Sep 21 04:19:47 2004 +++ ./src/gui-x.c Fri Feb 4 01:30:37 2005 @@ -111,12 +111,12 @@ gcpro_popup_callbacks (LWLIB_ID id) { Lisp_Object lid = make_int (id); - Lisp_Object this = assq_no_quit (lid, Vpopup_callbacks); + Lisp_Object this_callback = assq_no_quit (lid, Vpopup_callbacks); - if (!NILP (this)) + if (!NILP (this_callback)) { - free_list (XCDR (this)); - XCDR (this) = snarf_widget_values_for_gcpro (id); + free_list (XCDR (this_callback)); + XCDR (this_callback) = snarf_widget_values_for_gcpro (id); } else Vpopup_callbacks = Fcons (Fcons (lid, snarf_widget_values_for_gcpro (id)), @@ -130,11 +130,11 @@ ungcpro_popup_callbacks (LWLIB_ID id) { Lisp_Object lid = make_int (id); - Lisp_Object this = assq_no_quit (lid, Vpopup_callbacks); + Lisp_Object this_callback = assq_no_quit (lid, Vpopup_callbacks); - assert (!NILP (this)); - free_list (XCDR (this)); - Vpopup_callbacks = delq_no_quit (this, Vpopup_callbacks); + assert (!NILP (this_callback)); + free_list (XCDR (this_callback)); + Vpopup_callbacks = delq_no_quit (this_callback, Vpopup_callbacks); } int @@ -388,7 +388,7 @@ else { Bytecount namelen = XSTRING_LENGTH (string); - Ibyte *chars = (Ibyte *) ALLOCA (namelen + 3); + Ibyte *chars = alloca_ibytes (namelen + 3); chars[0] = '%'; chars[1] = '_'; memcpy (chars + 2, name, namelen + 1); @@ -694,8 +694,6 @@ void vars_of_gui_x (void) { - reinit_vars_of_gui_x (); - Vpopup_callbacks = Qnil; staticpro (&Vpopup_callbacks); } diff --text -u 'xemacs-21.5.18/src/gui.c' 'xemacs-21.5.19/src/gui.c' Index: ./src/gui.c --- ./src/gui.c Tue Sep 21 04:19:47 2004 +++ ./src/gui.c Fri Nov 5 08:06:35 2004 @@ -818,13 +818,13 @@ Lisp_Gui_Item); DOESNT_RETURN -gui_error (const Char_ASCII *reason, Lisp_Object frob) +gui_error (const Ascbyte *reason, Lisp_Object frob) { signal_error (Qgui_error, reason, frob); } DOESNT_RETURN -gui_error_2 (const Char_ASCII *reason, Lisp_Object frob0, Lisp_Object frob1) +gui_error_2 (const Ascbyte *reason, Lisp_Object frob0, Lisp_Object frob1) { signal_error_2 (Qgui_error, reason, frob0, frob1); } diff --text -u 'xemacs-21.5.18/src/gutter.c' 'xemacs-21.5.19/src/gutter.c' Index: ./src/gutter.c --- ./src/gutter.c Tue Sep 21 04:19:48 2004 +++ ./src/gutter.c Tue Jan 25 08:33:59 2005 @@ -70,7 +70,7 @@ (frame)->right_gutter_was_visible = flag; \ break; \ default: \ - abort (); \ + ABORT (); \ } \ } while (0) @@ -87,7 +87,7 @@ case RIGHT_GUTTER: return frame->right_gutter_was_visible; default: - abort (); + ABORT (); return 0; /* To keep the compiler happy */ } } @@ -214,7 +214,7 @@ break; default: - abort (); + ABORT (); } } @@ -1065,11 +1065,9 @@ if (CONSP (instantiator)) { - Lisp_Object rest; - - EXTERNAL_LIST_LOOP (rest, instantiator) + EXTERNAL_LIST_LOOP_2 (elt, instantiator) { - if (!SYMBOLP (XCAR (rest))) + if (!SYMBOLP (elt)) invalid_argument ("Gutter visibility must be a boolean or list of symbols", instantiator); } diff --text -u 'xemacs-21.5.18/src/hash.c' 'xemacs-21.5.19/src/hash.c' Index: ./src/hash.c --- ./src/hash.c Wed Oct 1 00:26:50 2003 +++ ./src/hash.c Wed Jan 26 19:22:24 2005 @@ -1,6 +1,6 @@ /* Hash tables. Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. - Copyright (C) 2003 Ben Wing. + Copyright (C) 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -56,8 +56,19 @@ return h; } -Hashcode -string_hash (const char *xv) +static int +string_equal (const void *st1, const void *st2) +{ + if (!st1) + return st2 ? 0 : 1; + else if (!st2) + return 0; + else + return !strcmp ((const char *) st1, (const char *) st2); +} + +static Hashcode +string_hash (const void *xv) { Hashcode h = 0; unsigned const char *x = (unsigned const char *) xv; @@ -167,7 +178,7 @@ xfree (hash_table, struct hash_table *); } -struct hash_table* +struct hash_table * make_hash_table (Elemcount size) { struct hash_table *hash_table = xnew_and_zero (struct hash_table); @@ -178,6 +189,12 @@ } struct hash_table * +make_string_hash_table (Elemcount size) +{ + return make_general_hash_table (size, string_hash, string_equal); +} + +struct hash_table * make_general_hash_table (Elemcount size, hash_table_hash_function hash_function, hash_table_test_function test_function) diff --text -u 'xemacs-21.5.18/src/hash.h' 'xemacs-21.5.19/src/hash.h' Index: ./src/hash.h --- ./src/hash.h Thu Feb 13 18:57:07 2003 +++ ./src/hash.h Wed Jan 26 19:22:25 2005 @@ -45,6 +45,8 @@ automatically if the number of entries approaches the size */ struct hash_table *make_hash_table (Elemcount size); +struct hash_table *make_string_hash_table (Elemcount size); + struct hash_table *make_general_hash_table (Elemcount size, hash_table_hash_function hash_function, diff --text -u 'xemacs-21.5.18/src/hftctl.c' 'xemacs-21.5.19/src/hftctl.c' Index: ./src/hftctl.c --- ./src/hftctl.c Wed Oct 1 00:26:50 2003 +++ ./src/hftctl.c Fri Nov 5 08:06:35 2004 @@ -323,7 +323,7 @@ if (cmdlen) /* if arg structure to pass */ { size = sizeof (struct hfctlreq) + cmdlen; - if ((p.c = xmalloc(size)) == NULL) /* malloc one area */ + if ((p.c = xmalloc (size)) == NULL) /* malloc one area */ return (-1); memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct */ diff --text -u 'xemacs-21.5.18/src/hpplay.c' 'xemacs-21.5.19/src/hpplay.c' Index: ./src/hpplay.c --- ./src/hpplay.c Tue Sep 21 04:19:48 2004 +++ ./src/hpplay.c Fri Nov 5 08:06:35 2004 @@ -72,7 +72,7 @@ /* error handling */ void -player_error_internal (Audio * audio, Char_ASCII * text, long errorCode) +player_error_internal (Audio * audio, Ascbyte * text, long errorCode) { Extbyte errorbuff[132]; Ibyte *interr; @@ -186,7 +186,7 @@ int -play_sound_data (UChar_Binary * data, int UNUSED (length), int volume) +play_sound_data (Binbyte * data, int UNUSED (length), int volume) { SBucket *pSBucket; Audio *audio; @@ -227,7 +227,7 @@ if (status) player_error_internal( audio, "Bucket creation failed", status ); - APutSBucketData(audio, pSBucket, 0, (Char_Binary *) (data + header->header_size), header->data_length, &status); + APutSBucketData(audio, pSBucket, 0, (CBinbyte *) (data + header->header_size), header->data_length, &status); if (status) player_error_internal( audio, "Audio data copy failed", status ); diff --text -u 'xemacs-21.5.18/src/imgproc.c' 'xemacs-21.5.19/src/imgproc.c' Index: ./src/imgproc.c --- ./src/imgproc.c Wed Oct 1 00:26:50 2003 +++ ./src/imgproc.c Fri Nov 5 08:06:36 2004 @@ -45,10 +45,10 @@ #include "imgproc.h" static void -get_histogram(quant_table *qt, UChar_Binary *pic, +get_histogram(quant_table *qt, Binbyte *pic, int width, int height, Colorbox* box) { - register UChar_Binary *inptr; + register Binbyte *inptr; register int red, green, blue; register int j, i; @@ -340,7 +340,7 @@ ir = red >> (COLOR_DEPTH-C_DEPTH); ig = green >> (COLOR_DEPTH-C_DEPTH); ib = blue >> (COLOR_DEPTH-C_DEPTH); - ptr = (C_cell *)xmalloc(sizeof (C_cell)); + ptr = xnew (C_cell); *(qt->ColorCells + ir*C_LEN*C_LEN + ig*C_LEN + ib) = ptr; ptr->num_ents = 0; @@ -472,7 +472,7 @@ } quant_table * -build_EImage_quantable(UChar_Binary *eimage, int width, int height, int num_colors) +build_EImage_quantable(Binbyte *eimage, int width, int height, int num_colors) { quant_table *qt; Colorbox *box_list, *ptr; @@ -486,7 +486,7 @@ * STEP 1: create empty boxes */ qt->usedboxes = NULL; - box_list = qt->freeboxes = (Colorbox *)xmalloc (num_colors*sizeof (Colorbox)); + box_list = qt->freeboxes = xnew_array (Colorbox, num_colors); qt->freeboxes[0].next = &(qt->freeboxes[1]); qt->freeboxes[0].prev = NULL; for (i = 1; i < num_colors-1; ++i) diff --text -u 'xemacs-21.5.18/src/indent.c' 'xemacs-21.5.19/src/indent.c' Index: ./src/indent.c --- ./src/indent.c Fri Feb 7 20:50:53 2003 +++ ./src/indent.c Wed Jan 26 14:11:12 2005 @@ -71,8 +71,8 @@ Lisp_Object value; buffer = wrap_buffer (buf); - value = Fprevious_single_property_change (make_int (pos), Qinvisible, - buffer, Qnil); + value = Fprevious_single_char_property_change (make_int (pos), Qinvisible, + buffer, Qnil); if (NILP (value)) return 0; /* no visible position found */ else diff --text -u 'xemacs-21.5.18/src/input-method-xlib.c' 'xemacs-21.5.19/src/input-method-xlib.c' Index: ./src/input-method-xlib.c --- ./src/input-method-xlib.c Tue Sep 21 04:19:49 2004 +++ ./src/input-method-xlib.c Tue Jan 25 08:33:59 2005 @@ -514,7 +514,7 @@ case XLookupChars: break; default: - abort (); + ABORT (); } new_event.type = ClientMessage; @@ -661,9 +661,10 @@ if (p->count_styles == 0) { /* No valid styles? */ - char *buf = (char *)ALLOCA (strlen (fromVal->addr) - + strlen (DefaultXIMStyles) - + 100); + /* !!#### */ + char *buf = (char *) ALLOCA (strlen (fromVal->addr) + + strlen (DefaultXIMStyles) + + 100); XrmValue new_from; XtAppContext the_app_con = XtDisplayToApplicationContext (dpy); diff --text -u 'xemacs-21.5.18/src/insdel.c' 'xemacs-21.5.19/src/insdel.c' Index: ./src/insdel.c --- ./src/insdel.c Wed Oct 1 00:26:50 2003 +++ ./src/insdel.c Tue Jan 25 08:33:59 2005 @@ -2,7 +2,7 @@ Copyright (C) 1985, 1986, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 2001, 2002, 2003 Ben Wing. + Copyright (C) 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -65,19 +65,22 @@ #define SET_BUF_END_GAP_SIZE(buf, value) \ do { (buf)->text->end_gap_size = (value); } while (0) -/* Gap location. */ -#define BYTE_BUF_GPT(buf) ((buf)->text->gpt + 0) #define BUF_GPT_ADDR(buf) (BUF_BEG_ADDR (buf) + BYTE_BUF_GPT (buf) - 1) /* Set gap location. */ -#define SET_BYTE_BUF_GPT(buf, value) do { (buf)->text->gpt = (value); } while (0) +#define SET_BOTH_BUF_GPT(buf, cval, bval) \ +do \ +{ \ + (buf)->text->gpt = (bval); \ + (buf)->text->bufgpt = (cval); \ +} while (0) /* Set end of buffer. */ -#define SET_BOTH_BUF_Z(buf, val, bival) \ +#define SET_BOTH_BUF_Z(buf, cval, bval) \ do \ { \ - (buf)->text->z = (bival); \ - (buf)->text->bufz = (val); \ + (buf)->text->z = (bval); \ + (buf)->text->bufz = (cval); \ } while (0) /* Under Mule, we maintain two sentinels in the buffer: one at the @@ -254,10 +257,10 @@ bigger. --ben */ #define GAP_MOVE_CHUNK 300000 -/* Move the gap to POS, which is less than the current GPT. */ +/* Move the gap to CPOS/BPOS, which is less than the current GPT. */ static void -gap_left (struct buffer *buf, Bytebpos pos) +gap_left (struct buffer *buf, Charbpos cpos, Bytebpos bpos) { Ibyte *to, *from; Bytecount i; @@ -275,21 +278,23 @@ while (1) { /* I gets number of characters left to copy. */ - i = new_s1 - pos; + i = new_s1 - bpos; if (i == 0) break; /* If a quit is requested, stop copying now. - Change POS to be where we have actually moved the gap to. */ + Change BPOS to be where we have actually moved the gap to. */ if (QUITP) { - pos = new_s1; + bpos = new_s1; + cpos = bytebpos_to_charbpos (buf, bpos); break; } /* Move at most GAP_MOVE_CHUNK chars before checking again for a quit. */ if (i > GAP_MOVE_CHUNK) i = GAP_MOVE_CHUNK; - if (i >= 128) + if (i >= 10) /* was 128 but memmove() should be extremely efficient + nowadays */ { new_s1 -= i; from -= i; @@ -304,19 +309,19 @@ } } - /* Adjust markers, and buffer data structure, to put the gap at POS. - POS is where the loop above stopped, which may be what was specified + /* Adjust markers, and buffer data structure, to put the gap at BPOS. + BPOS is where the loop above stopped, which may be what was specified or may be where a quit was detected. */ MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) { - adjust_markers (mbuf, pos, BYTE_BUF_GPT (mbuf), BUF_GAP_SIZE (mbuf)); + adjust_markers (mbuf, bpos, BYTE_BUF_GPT (mbuf), BUF_GAP_SIZE (mbuf)); } MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) { - adjust_extents (wrap_buffer (mbuf), pos, BYTE_BUF_GPT (mbuf), + adjust_extents (wrap_buffer (mbuf), bpos, BYTE_BUF_GPT (mbuf), BUF_GAP_SIZE (mbuf)); } - SET_BYTE_BUF_GPT (buf, pos); + SET_BOTH_BUF_GPT (buf, cpos, bpos); SET_GAP_SENTINEL (buf); #ifdef ERROR_CHECK_EXTENTS MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) @@ -328,7 +333,7 @@ } static void -gap_right (struct buffer *buf, Bytebpos pos) +gap_right (struct buffer *buf, Charbpos cpos, Bytebpos bpos) { Ibyte *to, *from; Bytecount i; @@ -346,21 +351,23 @@ while (1) { /* I gets number of characters left to copy. */ - i = pos - new_s1; + i = bpos - new_s1; if (i == 0) break; /* If a quit is requested, stop copying now. - Change POS to be where we have actually moved the gap to. */ + Change BPOS to be where we have actually moved the gap to. */ if (QUITP) { - pos = new_s1; + bpos = new_s1; + cpos = bytebpos_to_charbpos (buf, bpos); break; } /* Move at most GAP_MOVE_CHUNK chars before checking again for a quit. */ if (i > GAP_MOVE_CHUNK) i = GAP_MOVE_CHUNK; - if (i >= 128) + if (i >= 10) /* was 128 but memmove() should be extremely efficient + nowadays */ { new_s1 += i; memmove (to, from, i); @@ -379,14 +386,14 @@ int gsize = BUF_GAP_SIZE (buf); MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) { - adjust_markers (mbuf, BYTE_BUF_GPT (mbuf) + gsize, pos + gsize, - gsize); + adjust_markers (mbuf, BYTE_BUF_GPT (mbuf) + gsize, bpos + gsize, - gsize); } MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) { adjust_extents (wrap_buffer (mbuf), BYTE_BUF_GPT (mbuf) + gsize, - pos + gsize, - gsize); + bpos + gsize, - gsize); } - SET_BYTE_BUF_GPT (buf, pos); + SET_BOTH_BUF_GPT (buf, cpos, bpos); SET_GAP_SENTINEL (buf); #ifdef ERROR_CHECK_EXTENTS MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) @@ -395,7 +402,7 @@ } #endif } - if (pos == BYTE_BUF_Z (buf)) + if (bpos == BYTE_BUF_Z (buf)) { /* merge gap with end gap */ @@ -407,18 +414,18 @@ QUIT; } -/* Move gap to position `pos'. +/* Move gap to position `bpos'. Note that this can quit! */ static void -move_gap (struct buffer *buf, Bytebpos pos) +move_gap (struct buffer *buf, Charbpos cpos, Bytebpos bpos) { if (! BUF_BEG_ADDR (buf)) - abort (); - if (pos < BYTE_BUF_GPT (buf)) - gap_left (buf, pos); - else if (pos > BYTE_BUF_GPT (buf)) - gap_right (buf, pos); + ABORT (); + if (bpos < BYTE_BUF_GPT (buf)) + gap_left (buf, cpos, bpos); + else if (bpos > BYTE_BUF_GPT (buf)) + gap_right (buf, cpos, bpos); } /* Merge the end gap into the gap */ @@ -427,7 +434,8 @@ merge_gap_with_end_gap (struct buffer *buf) { Lisp_Object tem; - Bytebpos real_gap_loc; + Charbpos real_gap_loc_char; + Bytebpos real_gap_loc_byte; Bytecount old_gap_size; Bytecount increment; @@ -440,20 +448,23 @@ tem = Vinhibit_quit; Vinhibit_quit = Qt; - real_gap_loc = BYTE_BUF_GPT (buf); + real_gap_loc_char = BUF_GPT (buf); + real_gap_loc_byte = BYTE_BUF_GPT (buf); old_gap_size = BUF_GAP_SIZE (buf); /* Pretend the end gap is the gap */ - SET_BYTE_BUF_GPT (buf, BYTE_BUF_Z (buf) + BUF_GAP_SIZE (buf)); + SET_BOTH_BUF_GPT (buf, BUF_Z (buf) + BUF_GAP_SIZE (buf), + BYTE_BUF_Z (buf) + BUF_GAP_SIZE (buf)); SET_BUF_GAP_SIZE (buf, increment); /* Move the new gap down to be consecutive with the end of the old one. This adjusts the markers properly too. */ - gap_left (buf, real_gap_loc + old_gap_size); + gap_left (buf, real_gap_loc_char + old_gap_size, + real_gap_loc_byte + old_gap_size); /* Now combine the two into one large gap. */ SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + old_gap_size); - SET_BYTE_BUF_GPT (buf, real_gap_loc); + SET_BOTH_BUF_GPT (buf, real_gap_loc_char, real_gap_loc_byte); SET_GAP_SENTINEL (buf); /* We changed the total size of the buffer (including gap), @@ -471,7 +482,8 @@ { Ibyte *result; Lisp_Object tem; - Bytebpos real_gap_loc; + Charbpos real_gap_loc_char; + Bytebpos real_gap_loc_byte; Bytecount old_gap_size; /* If we have to get more space, get enough to last a while. We use @@ -508,22 +520,25 @@ tem = Vinhibit_quit; Vinhibit_quit = Qt; - real_gap_loc = BYTE_BUF_GPT (buf); + real_gap_loc_char = BUF_GPT (buf); + real_gap_loc_byte = BYTE_BUF_GPT (buf); old_gap_size = BUF_GAP_SIZE (buf); /* Call the newly allocated space a gap at the end of the whole space. */ - SET_BYTE_BUF_GPT (buf, BYTE_BUF_Z (buf) + BUF_GAP_SIZE (buf)); + SET_BOTH_BUF_GPT (buf, BUF_Z (buf) + BUF_GAP_SIZE (buf), + BYTE_BUF_Z (buf) + BUF_GAP_SIZE (buf)); SET_BUF_GAP_SIZE (buf, increment); SET_BUF_END_GAP_SIZE (buf, 0); /* Move the new gap down to be consecutive with the end of the old one. This adjusts the markers properly too. */ - gap_left (buf, real_gap_loc + old_gap_size); + gap_left (buf, real_gap_loc_char + old_gap_size, + real_gap_loc_byte + old_gap_size); /* Now combine the two into one large gap. */ SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + old_gap_size); - SET_BYTE_BUF_GPT (buf, real_gap_loc); + SET_BOTH_BUF_GPT (buf, real_gap_loc_char, real_gap_loc_byte); SET_GAP_SENTINEL (buf); /* We changed the total size of the buffer (including gap), @@ -1130,7 +1145,7 @@ /* #### if debug-on-quit is invoked and the user changes the buffer, bad things can happen. This is a rampant problem in Emacs. */ - move_gap (buf, bytepos); /* may QUIT */ + move_gap (buf, pos, bytepos); /* may QUIT */ if (! GAP_CAN_HOLD_SIZE_P (buf, length_in_buffer)) { if (BUF_END_GAP_SIZE (buf) >= length_in_buffer) @@ -1166,7 +1181,8 @@ BUF_FORMAT (buf), wrap_buffer (buf), NULL); SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) - length_in_buffer); - SET_BYTE_BUF_GPT (buf, BYTE_BUF_GPT (buf) + length_in_buffer); + SET_BOTH_BUF_GPT (buf, BUF_GPT (buf) + cclen, + BYTE_BUF_GPT (buf) + length_in_buffer); MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) { SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) + cclen, @@ -1389,9 +1405,9 @@ /* Make sure the gap is somewhere in or next to what we are deleting. */ /* NOTE: Can QUIT! */ if (byte_to < BYTE_BUF_GPT (buf)) - gap_left (buf, byte_to); + gap_left (buf, to, byte_to); if (byte_from > BYTE_BUF_GPT (buf)) - gap_right (buf, byte_from); + gap_right (buf, from, byte_from); do_move_gap = 1; } @@ -1511,7 +1527,7 @@ } SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BYTE_BUF_Z (buf) - byte_numdel); if (do_move_gap) - SET_BYTE_BUF_GPT (buf, byte_from); + SET_BOTH_BUF_GPT (buf, from, byte_from); SET_GAP_SENTINEL (buf); #ifdef MULE @@ -1753,7 +1769,6 @@ void vars_of_insdel (void) { - reinit_vars_of_insdel (); } void @@ -1767,24 +1782,22 @@ memory_full (); SET_BUF_END_GAP_SIZE (b, 0); - SET_BYTE_BUF_GPT (b, 1); + SET_BOTH_BUF_GPT (b, 1, 1); SET_BOTH_BUF_Z (b, 1, 1); SET_GAP_SENTINEL (b); SET_END_SENTINEL (b); + #ifdef MULE - { - int i; + b->text->entirely_one_byte_p = 1; + +#ifdef OLD_BYTE_CHAR + b->text->mule_bufmin = b->text->mule_bufmax = 1; + b->text->mule_bytmin = b->text->mule_bytmax = 1; +#endif + + b->text->cached_charpos = 1; + b->text->cached_bytepos = 1; - b->text->mule_bufmin = b->text->mule_bufmax = 1; - b->text->mule_bytmin = b->text->mule_bytmax = 1; - b->text->entirely_one_byte_p = 1; - - for (i = 0; i < 16; i++) - { - b->text->mule_charbpos_cache[i] = 1; - b->text->mule_bytebpos_cache[i] = 1; - } - } /* &&#### Set to FORMAT_8_BIT_FIXED when that code is working */ BUF_FORMAT (b) = FORMAT_DEFAULT; #endif /* MULE */ diff --text -u 'xemacs-21.5.18/src/intl-auto-encap-win32.c' 'xemacs-21.5.19/src/intl-auto-encap-win32.c' Index: ./src/intl-auto-encap-win32.c --- ./src/intl-auto-encap-win32.c Tue Sep 16 05:21:46 2003 +++ ./src/intl-auto-encap-win32.c Tue Jan 25 08:34:00 2005 @@ -13,60 +13,281 @@ /*----------------------------------------------------------------------*/ -/* Processing file WINNLS.H */ +/* Processing file WINCON.H */ /*----------------------------------------------------------------------*/ -/* Error if GetCPInfoEx used: not used, not examined yet */ +BOOL +qxePeekConsoleInput (HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead) +{ + if (XEUNICODE_P) + return PeekConsoleInputW (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); + else + return PeekConsoleInputA (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); +} -/* Error if CompareString used: not used, not examined yet */ +BOOL +qxeReadConsoleInput (HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead) +{ + if (XEUNICODE_P) + return ReadConsoleInputW (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); + else + return ReadConsoleInputA (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); +} -/* Error if LCMapString used: not used, not examined yet */ +BOOL +qxeWriteConsoleInput (HANDLE hConsoleInput, CONST INPUT_RECORD * lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten) +{ + if (XEUNICODE_P) + return WriteConsoleInputW (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsWritten); + else + return WriteConsoleInputA (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsWritten); +} + +BOOL +qxeReadConsoleOutput (HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion) +{ + if (XEUNICODE_P) + return ReadConsoleOutputW (hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpReadRegion); + else + return ReadConsoleOutputA (hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpReadRegion); +} + +BOOL +qxeWriteConsoleOutput (HANDLE hConsoleOutput, CONST CHAR_INFO * lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion) +{ + if (XEUNICODE_P) + return WriteConsoleOutputW (hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpWriteRegion); + else + return WriteConsoleOutputA (hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpWriteRegion); +} + +BOOL +qxeReadConsoleOutputCharacter (HANDLE hConsoleOutput, Extbyte * lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead) +{ + if (XEUNICODE_P) + return ReadConsoleOutputCharacterW (hConsoleOutput, (LPWSTR) lpCharacter, nLength, dwReadCoord, lpNumberOfCharsRead); + else + return ReadConsoleOutputCharacterA (hConsoleOutput, (LPSTR) lpCharacter, nLength, dwReadCoord, lpNumberOfCharsRead); +} +BOOL +qxeWriteConsoleOutputCharacter (HANDLE hConsoleOutput, const Extbyte * lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten) +{ + if (XEUNICODE_P) + return WriteConsoleOutputCharacterW (hConsoleOutput, (LPCWSTR) lpCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten); + else + return WriteConsoleOutputCharacterA (hConsoleOutput, (LPCSTR) lpCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten); +} + +/* Error if FillConsoleOutputCharacter used: split CHAR */ + +BOOL +qxeScrollConsoleScreenBuffer (HANDLE hConsoleOutput, CONST SMALL_RECT * lpScrollRectangle, CONST SMALL_RECT * lpClipRectangle, COORD dwDestinationOrigin, CONST CHAR_INFO * lpFill) +{ + if (XEUNICODE_P) + return ScrollConsoleScreenBufferW (hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill); + else + return ScrollConsoleScreenBufferA (hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill); +} + +DWORD +qxeGetConsoleTitle (Extbyte * lpConsoleTitle, DWORD nSize) +{ + if (XEUNICODE_P) + return GetConsoleTitleW ((LPWSTR) lpConsoleTitle, nSize); + else + return GetConsoleTitleA ((LPSTR) lpConsoleTitle, nSize); +} + +BOOL +qxeSetConsoleTitle (const Extbyte * lpConsoleTitle) +{ + if (XEUNICODE_P) + return SetConsoleTitleW ((LPCWSTR) lpConsoleTitle); + else + return SetConsoleTitleA ((LPCSTR) lpConsoleTitle); +} + +BOOL +qxeReadConsole (HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved) +{ + if (XEUNICODE_P) + return ReadConsoleW (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved); + else + return ReadConsoleA (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved); +} + +BOOL +qxeWriteConsole (HANDLE hConsoleOutput, CONST VOID * lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved) +{ + if (XEUNICODE_P) + return WriteConsoleW (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved); + else + return WriteConsoleA (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved); +} + + +/*----------------------------------------------------------------------*/ +/* Processing file SHELLAPI.H */ +/*----------------------------------------------------------------------*/ + +UINT +qxeDragQueryFile (HDROP arg1, UINT arg2, Extbyte * arg3, UINT arg4) +{ + if (XEUNICODE_P) + return DragQueryFileW (arg1, arg2, (LPWSTR) arg3, arg4); + else + return DragQueryFileA (arg1, arg2, (LPSTR) arg3, arg4); +} + +HINSTANCE +qxeShellExecute (HWND hwnd, const Extbyte * lpOperation, const Extbyte * lpFile, const Extbyte * lpParameters, const Extbyte * lpDirectory, INT nShowCmd) +{ + if (XEUNICODE_P) + return ShellExecuteW (hwnd, (LPCWSTR) lpOperation, (LPCWSTR) lpFile, (LPCWSTR) lpParameters, (LPCWSTR) lpDirectory, nShowCmd); + else + return ShellExecuteA (hwnd, (LPCSTR) lpOperation, (LPCSTR) lpFile, (LPCSTR) lpParameters, (LPCSTR) lpDirectory, nShowCmd); +} + +HINSTANCE +qxeFindExecutable (const Extbyte * lpFile, const Extbyte * lpDirectory, Extbyte * lpResult) +{ + if (XEUNICODE_P) + return FindExecutableW ((LPCWSTR) lpFile, (LPCWSTR) lpDirectory, (LPWSTR) lpResult); + else + return FindExecutableA ((LPCSTR) lpFile, (LPCSTR) lpDirectory, (LPSTR) lpResult); +} + +/* Error if CommandLineToArgv used: Unicode-only */ + +INT +qxeShellAbout (HWND hWnd, const Extbyte * szApp, const Extbyte * szOtherStuff, HICON hIcon) +{ + if (XEUNICODE_P) + return ShellAboutW (hWnd, (LPCWSTR) szApp, (LPCWSTR) szOtherStuff, hIcon); + else + return ShellAboutA (hWnd, (LPCSTR) szApp, (LPCSTR) szOtherStuff, hIcon); +} + +HICON +qxeExtractAssociatedIcon (HINSTANCE hInst, Extbyte * lpIconPath, LPWORD lpiIcon) +{ + if (XEUNICODE_P) + return ExtractAssociatedIconW (hInst, (LPWSTR) lpIconPath, lpiIcon); + else + return ExtractAssociatedIconA (hInst, (LPSTR) lpIconPath, lpiIcon); +} + +HICON +qxeExtractIcon (HINSTANCE hInst, const Extbyte * lpszExeFileName, UINT nIconIndex) +{ + if (XEUNICODE_P) + return ExtractIconW (hInst, (LPCWSTR) lpszExeFileName, nIconIndex); + else + return ExtractIconA (hInst, (LPCSTR) lpszExeFileName, nIconIndex); +} + +#if !defined (CYGWIN_HEADERS) + +/* NOTE: NT 4.0+ only */ +DWORD +qxeDoEnvironmentSubst (Extbyte * szString, UINT cbString) +{ + if (XEUNICODE_P) + return DoEnvironmentSubstW ((LPWSTR) szString, cbString); + else + return DoEnvironmentSubstA ((LPSTR) szString, cbString); +} + +#endif /* !defined (CYGWIN_HEADERS) */ + +/* Error if FindEnvironmentString used: causes link error; NT 4.0+ only */ + +/* Skipping ExtractIconEx because NT 4.0+ only, error in Cygwin prototype */ + +/* NOTE: NT 4.0+ only */ int -qxeGetLocaleInfo (LCID Locale, LCTYPE LCType, Extbyte * lpLCData, int cchData) +qxeSHFileOperation (LPSHFILEOPSTRUCTW lpFileOp) { if (XEUNICODE_P) - return GetLocaleInfoW (Locale, LCType, (LPWSTR) lpLCData, cchData); + return SHFileOperationW (lpFileOp); else - return GetLocaleInfoA (Locale, LCType, (LPSTR) lpLCData, cchData); + return SHFileOperationA ((LPSHFILEOPSTRUCTA) lpFileOp); } +/* NOTE: NT 4.0+ only */ BOOL -qxeSetLocaleInfo (LCID Locale, LCTYPE LCType, const Extbyte * lpLCData) +qxeShellExecuteEx (LPSHELLEXECUTEINFOW lpExecInfo) { if (XEUNICODE_P) - return SetLocaleInfoW (Locale, LCType, (LPCWSTR) lpLCData); + return ShellExecuteExW (lpExecInfo); else - return SetLocaleInfoA (Locale, LCType, (LPCSTR) lpLCData); + return ShellExecuteExA ((LPSHELLEXECUTEINFOA) lpExecInfo); } -/* Error if GetTimeFormat used: not used, not examined yet */ +/* Error if WinExecError used: causes link error; NT 4.0+ only */ -/* Error if GetDateFormat used: not used, not examined yet */ +#if !defined (CYGWIN_HEADERS) -/* Error if GetNumberFormat used: not used, not examined yet */ +/* NOTE: NT 4.0+ only */ +HRESULT +qxeSHQueryRecycleBin (const Extbyte * pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo) +{ + if (XEUNICODE_P) + return SHQueryRecycleBinW ((LPCWSTR) pszRootPath, pSHQueryRBInfo); + else + return SHQueryRecycleBinA ((LPCSTR) pszRootPath, pSHQueryRBInfo); +} -/* Error if GetCurrencyFormat used: not used, not examined yet */ +#endif /* !defined (CYGWIN_HEADERS) */ -/* Error if EnumCalendarInfo used: not used, not examined yet */ +#if !defined (CYGWIN_HEADERS) -/* Error if EnumCalendarInfoEx used: not used, not examined yet */ +/* NOTE: NT 4.0+ only */ +HRESULT +qxeSHEmptyRecycleBin (HWND hwnd, const Extbyte * pszRootPath, DWORD dwFlags) +{ + if (XEUNICODE_P) + return SHEmptyRecycleBinW (hwnd, (LPCWSTR) pszRootPath, dwFlags); + else + return SHEmptyRecycleBinA (hwnd, (LPCSTR) pszRootPath, dwFlags); +} -/* Error if EnumTimeFormats used: not used, not examined yet */ +#endif /* !defined (CYGWIN_HEADERS) */ -/* Error if EnumDateFormats used: not used, not examined yet */ +/* Error if Shell_NotifyIcon used: split-sized NOTIFYICONDATA, NT 4.0+ only */ -/* Error if EnumDateFormatsEx used: not used, not examined yet */ +/* Skipping SHGetFileInfo because split-sized SHFILEINFO, NT 4.0+ only */ -/* Error if GetStringTypeEx used: not used, not examined yet */ +/* Error if SHGetDiskFreeSpace used: causes link error; NT 4.0+ only */ -/* Error if GetStringType used: no such fun; A and W versions have different nos. of args */ +#if !defined (CYGWIN_HEADERS) -/* Error if FoldString used: not used, not examined yet */ +/* NOTE: NT 4.0+ only */ +BOOL +qxeSHGetNewLinkInfo (const Extbyte * pszLinkTo, const Extbyte * pszDir, Extbyte * pszName, BOOL * pfMustCopy, UINT uFlags) +{ + if (XEUNICODE_P) + return SHGetNewLinkInfoW ((LPCWSTR) pszLinkTo, (LPCWSTR) pszDir, (LPWSTR) pszName, pfMustCopy, uFlags); + else + return SHGetNewLinkInfoA ((LPCSTR) pszLinkTo, (LPCSTR) pszDir, (LPSTR) pszName, pfMustCopy, uFlags); +} -/* Error if EnumSystemLocales used: not used, not examined yet */ +#endif /* !defined (CYGWIN_HEADERS) */ -/* Error if EnumSystemCodePages used: not used, not examined yet */ +#if !defined (CYGWIN_HEADERS) + +/* NOTE: NT 4.0+ only */ +BOOL +qxeSHInvokePrinterCommand (HWND hwnd, UINT uAction, const Extbyte * lpBuf1, const Extbyte * lpBuf2, BOOL fModal) +{ + if (XEUNICODE_P) + return SHInvokePrinterCommandW (hwnd, uAction, (LPCWSTR) lpBuf1, (LPCWSTR) lpBuf2, fModal); + else + return SHInvokePrinterCommandA (hwnd, uAction, (LPCSTR) lpBuf1, (LPCSTR) lpBuf2, fModal); +} + +#endif /* !defined (CYGWIN_HEADERS) */ /*----------------------------------------------------------------------*/ @@ -664,1890 +885,1904 @@ /*----------------------------------------------------------------------*/ -/* Processing file WINREG.H */ +/* Processing file WINUSER.H */ /*----------------------------------------------------------------------*/ -/* Skipping RegConnectRegistry because error in Cygwin prototype */ - -LONG - -qxeRegCreateKey (HKEY hKey, const Extbyte * lpSubKey, PHKEY phkResult) -{ - if (XEUNICODE_P) - return RegCreateKeyW (hKey, (LPCWSTR) lpSubKey, phkResult); - else - return RegCreateKeyA (hKey, (LPCSTR) lpSubKey, phkResult); -} - -LONG - -qxeRegCreateKeyEx (HKEY hKey, const Extbyte * lpSubKey, DWORD Reserved, Extbyte * lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition) -{ - if (XEUNICODE_P) - return RegCreateKeyExW (hKey, (LPCWSTR) lpSubKey, Reserved, (LPWSTR) lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); - else - return RegCreateKeyExA (hKey, (LPCSTR) lpSubKey, Reserved, (LPSTR) lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); -} - -LONG - -qxeRegDeleteKey (HKEY hKey, const Extbyte * lpSubKey) -{ - if (XEUNICODE_P) - return RegDeleteKeyW (hKey, (LPCWSTR) lpSubKey); - else - return RegDeleteKeyA (hKey, (LPCSTR) lpSubKey); -} - -LONG - -qxeRegDeleteValue (HKEY hKey, const Extbyte * lpValueName) -{ - if (XEUNICODE_P) - return RegDeleteValueW (hKey, (LPCWSTR) lpValueName); - else - return RegDeleteValueA (hKey, (LPCSTR) lpValueName); -} - -LONG - -qxeRegEnumKey (HKEY hKey, DWORD dwIndex, Extbyte * lpName, DWORD cbName) -{ - if (XEUNICODE_P) - return RegEnumKeyW (hKey, dwIndex, (LPWSTR) lpName, cbName); - else - return RegEnumKeyA (hKey, dwIndex, (LPSTR) lpName, cbName); -} - -LONG - -qxeRegEnumKeyEx (HKEY hKey, DWORD dwIndex, Extbyte * lpName, LPDWORD lpcbName, LPDWORD lpReserved, Extbyte * lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime) +int +qxewvsprintf (Extbyte * arg1, const Extbyte * arg2, va_list arglist) { if (XEUNICODE_P) - return RegEnumKeyExW (hKey, dwIndex, (LPWSTR) lpName, lpcbName, lpReserved, (LPWSTR) lpClass, lpcbClass, lpftLastWriteTime); + return wvsprintfW ((LPWSTR) arg1, (LPCWSTR) arg2, arglist); else - return RegEnumKeyExA (hKey, dwIndex, (LPSTR) lpName, lpcbName, lpReserved, (LPSTR) lpClass, lpcbClass, lpftLastWriteTime); + return wvsprintfA ((LPSTR) arg1, (LPCSTR) arg2, arglist); } -LONG - -qxeRegEnumValue (HKEY hKey, DWORD dwIndex, Extbyte * lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) +HKL +qxeLoadKeyboardLayout (const Extbyte * pwszKLID, UINT Flags) { if (XEUNICODE_P) - return RegEnumValueW (hKey, dwIndex, (LPWSTR) lpValueName, lpcbValueName, lpReserved, lpType, lpData, lpcbData); + return LoadKeyboardLayoutW ((LPCWSTR) pwszKLID, Flags); else - return RegEnumValueA (hKey, dwIndex, (LPSTR) lpValueName, lpcbValueName, lpReserved, lpType, lpData, lpcbData); + return LoadKeyboardLayoutA ((LPCSTR) pwszKLID, Flags); } -LONG - -qxeRegLoadKey (HKEY hKey, const Extbyte * lpSubKey, const Extbyte * lpFile) +BOOL +qxeGetKeyboardLayoutName (Extbyte * pwszKLID) { if (XEUNICODE_P) - return RegLoadKeyW (hKey, (LPCWSTR) lpSubKey, (LPCWSTR) lpFile); + return GetKeyboardLayoutNameW ((LPWSTR) pwszKLID); else - return RegLoadKeyA (hKey, (LPCSTR) lpSubKey, (LPCSTR) lpFile); + return GetKeyboardLayoutNameA ((LPSTR) pwszKLID); } -LONG +/* Error if CreateDesktop used: split-sized LPDEVMODE */ -qxeRegOpenKey (HKEY hKey, const Extbyte * lpSubKey, PHKEY phkResult) +HDESK +qxeOpenDesktop (Extbyte * lpszDesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess) { if (XEUNICODE_P) - return RegOpenKeyW (hKey, (LPCWSTR) lpSubKey, phkResult); + return OpenDesktopW ((LPWSTR) lpszDesktop, dwFlags, fInherit, dwDesiredAccess); else - return RegOpenKeyA (hKey, (LPCSTR) lpSubKey, phkResult); + return OpenDesktopA ((LPSTR) lpszDesktop, dwFlags, fInherit, dwDesiredAccess); } -LONG - -qxeRegOpenKeyEx (HKEY hKey, const Extbyte * lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) +/* NOTE: // callback fun differs only in string pointer type */ +BOOL +qxeEnumDesktops (HWINSTA hwinsta, DESKTOPENUMPROCW lpEnumFunc, LPARAM lParam) { if (XEUNICODE_P) - return RegOpenKeyExW (hKey, (LPCWSTR) lpSubKey, ulOptions, samDesired, phkResult); + return EnumDesktopsW (hwinsta, lpEnumFunc, lParam); else - return RegOpenKeyExA (hKey, (LPCSTR) lpSubKey, ulOptions, samDesired, phkResult); + return EnumDesktopsA (hwinsta, (DESKTOPENUMPROCA) lpEnumFunc, lParam); } -LONG - -qxeRegQueryInfoKey (HKEY hKey, Extbyte * lpClass, LPDWORD lpcbClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen, LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime) +HWINSTA +qxeCreateWindowStation (Extbyte * lpwinsta, DWORD dwReserved, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa) { if (XEUNICODE_P) - return RegQueryInfoKeyW (hKey, (LPWSTR) lpClass, lpcbClass, lpReserved, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime); + return CreateWindowStationW ((LPWSTR) lpwinsta, dwReserved, dwDesiredAccess, lpsa); else - return RegQueryInfoKeyA (hKey, (LPSTR) lpClass, lpcbClass, lpReserved, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime); + return CreateWindowStationA ((LPSTR) lpwinsta, dwReserved, dwDesiredAccess, lpsa); } -LONG - -qxeRegQueryValue (HKEY hKey, const Extbyte * lpSubKey, Extbyte * lpValue, PLONG lpcbValue) +HWINSTA +qxeOpenWindowStation (Extbyte * lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess) { if (XEUNICODE_P) - return RegQueryValueW (hKey, (LPCWSTR) lpSubKey, (LPWSTR) lpValue, lpcbValue); + return OpenWindowStationW ((LPWSTR) lpszWinSta, fInherit, dwDesiredAccess); else - return RegQueryValueA (hKey, (LPCSTR) lpSubKey, (LPSTR) lpValue, lpcbValue); -} - -LONG + return OpenWindowStationA ((LPSTR) lpszWinSta, fInherit, dwDesiredAccess); +} -qxeRegQueryMultipleValues (HKEY hKey, PVALENTW val_list, DWORD num_vals, Extbyte * lpValueBuf, LPDWORD ldwTotsize) +/* NOTE: // callback fun differs only in string pointer type */ +BOOL +qxeEnumWindowStations (WINSTAENUMPROCW lpEnumFunc, LPARAM lParam) { if (XEUNICODE_P) - return RegQueryMultipleValuesW (hKey, val_list, num_vals, (LPWSTR) lpValueBuf, ldwTotsize); + return EnumWindowStationsW (lpEnumFunc, lParam); else - return RegQueryMultipleValuesA (hKey, (PVALENTA) val_list, num_vals, (LPSTR) lpValueBuf, ldwTotsize); + return EnumWindowStationsA ((WINSTAENUMPROCA) lpEnumFunc, lParam); } -LONG - -qxeRegQueryValueEx (HKEY hKey, const Extbyte * lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) +BOOL +qxeGetUserObjectInformation (HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded) { if (XEUNICODE_P) - return RegQueryValueExW (hKey, (LPCWSTR) lpValueName, lpReserved, lpType, lpData, lpcbData); + return GetUserObjectInformationW (hObj, nIndex, pvInfo, nLength, lpnLengthNeeded); else - return RegQueryValueExA (hKey, (LPCSTR) lpValueName, lpReserved, lpType, lpData, lpcbData); + return GetUserObjectInformationA (hObj, nIndex, pvInfo, nLength, lpnLengthNeeded); } -LONG - -qxeRegReplaceKey (HKEY hKey, const Extbyte * lpSubKey, const Extbyte * lpNewFile, const Extbyte * lpOldFile) +BOOL +qxeSetUserObjectInformation (HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength) { if (XEUNICODE_P) - return RegReplaceKeyW (hKey, (LPCWSTR) lpSubKey, (LPCWSTR) lpNewFile, (LPCWSTR) lpOldFile); + return SetUserObjectInformationW (hObj, nIndex, pvInfo, nLength); else - return RegReplaceKeyA (hKey, (LPCSTR) lpSubKey, (LPCSTR) lpNewFile, (LPCSTR) lpOldFile); + return SetUserObjectInformationA (hObj, nIndex, pvInfo, nLength); } -LONG - -qxeRegRestoreKey (HKEY hKey, const Extbyte * lpFile, DWORD dwFlags) +UINT +qxeRegisterWindowMessage (const Extbyte * lpString) { if (XEUNICODE_P) - return RegRestoreKeyW (hKey, (LPCWSTR) lpFile, dwFlags); + return RegisterWindowMessageW ((LPCWSTR) lpString); else - return RegRestoreKeyA (hKey, (LPCSTR) lpFile, dwFlags); + return RegisterWindowMessageA ((LPCSTR) lpString); } -LONG - -qxeRegSaveKey (HKEY hKey, const Extbyte * lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes) +BOOL +qxeGetMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) { if (XEUNICODE_P) - return RegSaveKeyW (hKey, (LPCWSTR) lpFile, lpSecurityAttributes); + return GetMessageW (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); else - return RegSaveKeyA (hKey, (LPCSTR) lpFile, lpSecurityAttributes); + return GetMessageA (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); } LONG - -qxeRegSetValue (HKEY hKey, const Extbyte * lpSubKey, DWORD dwType, const Extbyte * lpData, DWORD cbData) +qxeDispatchMessage (CONST MSG * lpMsg) { if (XEUNICODE_P) - return RegSetValueW (hKey, (LPCWSTR) lpSubKey, dwType, (LPCWSTR) lpData, cbData); + return DispatchMessageW (lpMsg); else - return RegSetValueA (hKey, (LPCSTR) lpSubKey, dwType, (LPCSTR) lpData, cbData); + return DispatchMessageA (lpMsg); } -LONG - -qxeRegSetValueEx (HKEY hKey, const Extbyte * lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData) +BOOL +qxePeekMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { if (XEUNICODE_P) - return RegSetValueExW (hKey, (LPCWSTR) lpValueName, Reserved, dwType, lpData, cbData); + return PeekMessageW (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); else - return RegSetValueExA (hKey, (LPCSTR) lpValueName, Reserved, dwType, lpData, cbData); + return PeekMessageA (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } -LONG +/* Skipping SendMessage because split messages and structures */ -qxeRegUnLoadKey (HKEY hKey, const Extbyte * lpSubKey) +LRESULT +qxeSendMessageTimeout (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, LPDWORD lpdwResult) { if (XEUNICODE_P) - return RegUnLoadKeyW (hKey, (LPCWSTR) lpSubKey); + return SendMessageTimeoutW (hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult); else - return RegUnLoadKeyA (hKey, (LPCSTR) lpSubKey); + return SendMessageTimeoutA (hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult); } BOOL - -qxeInitiateSystemShutdown (Extbyte * lpMachineName, Extbyte * lpMessage, DWORD dwTimeout, BOOL bForceAppsClosed, BOOL bRebootAfterShutdown) +qxeSendNotifyMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { if (XEUNICODE_P) - return InitiateSystemShutdownW ((LPWSTR) lpMachineName, (LPWSTR) lpMessage, dwTimeout, bForceAppsClosed, bRebootAfterShutdown); + return SendNotifyMessageW (hWnd, Msg, wParam, lParam); else - return InitiateSystemShutdownA ((LPSTR) lpMachineName, (LPSTR) lpMessage, dwTimeout, bForceAppsClosed, bRebootAfterShutdown); + return SendNotifyMessageA (hWnd, Msg, wParam, lParam); } BOOL - -qxeAbortSystemShutdown (Extbyte * lpMachineName) +qxeSendMessageCallback (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, SENDASYNCPROC lpResultCallBack, DWORD dwData) { if (XEUNICODE_P) - return AbortSystemShutdownW ((LPWSTR) lpMachineName); + return SendMessageCallbackW (hWnd, Msg, wParam, lParam, lpResultCallBack, dwData); else - return AbortSystemShutdownA ((LPSTR) lpMachineName); + return SendMessageCallbackA (hWnd, Msg, wParam, lParam, lpResultCallBack, dwData); } +/* Error if BroadcastSystemMessage used: win95 version not split; NT 4.0+ only */ -/*----------------------------------------------------------------------*/ -/* Processing file SHELLAPI.H */ -/*----------------------------------------------------------------------*/ +/* Error if RegisterDeviceNotification used: NT 5.0+ only */ -UINT -qxeDragQueryFile (HDROP arg1, UINT arg2, Extbyte * arg3, UINT arg4) +BOOL +qxePostMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { if (XEUNICODE_P) - return DragQueryFileW (arg1, arg2, (LPWSTR) arg3, arg4); + return PostMessageW (hWnd, Msg, wParam, lParam); else - return DragQueryFileA (arg1, arg2, (LPSTR) arg3, arg4); + return PostMessageA (hWnd, Msg, wParam, lParam); } -HINSTANCE -qxeShellExecute (HWND hwnd, const Extbyte * lpOperation, const Extbyte * lpFile, const Extbyte * lpParameters, const Extbyte * lpDirectory, INT nShowCmd) +BOOL +qxePostThreadMessage (DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam) { if (XEUNICODE_P) - return ShellExecuteW (hwnd, (LPCWSTR) lpOperation, (LPCWSTR) lpFile, (LPCWSTR) lpParameters, (LPCWSTR) lpDirectory, nShowCmd); + return PostThreadMessageW (idThread, Msg, wParam, lParam); else - return ShellExecuteA (hwnd, (LPCSTR) lpOperation, (LPCSTR) lpFile, (LPCSTR) lpParameters, (LPCSTR) lpDirectory, nShowCmd); + return PostThreadMessageA (idThread, Msg, wParam, lParam); } -HINSTANCE -qxeFindExecutable (const Extbyte * lpFile, const Extbyte * lpDirectory, Extbyte * lpResult) +/* Skipping DefWindowProc because return value is conditionalized on _MAC, messes up parser */ + +/* Error if CallWindowProc used: two versions, STRICT and non-STRICT */ + +/* Error if CallWindowProc used: two versions, STRICT and non-STRICT */ + +/* Skipping RegisterClass because need to intercept so we can provide our own window procedure and handle split notify messages; split-simple WNDCLASS */ + +/* Skipping UnregisterClass because need to intercept for reasons related to RegisterClass */ + +BOOL +qxeGetClassInfo (HINSTANCE hInstance, const Extbyte * lpClassName, LPWNDCLASSW lpWndClass) { if (XEUNICODE_P) - return FindExecutableW ((LPCWSTR) lpFile, (LPCWSTR) lpDirectory, (LPWSTR) lpResult); + return GetClassInfoW (hInstance, (LPCWSTR) lpClassName, lpWndClass); else - return FindExecutableA ((LPCSTR) lpFile, (LPCSTR) lpDirectory, (LPSTR) lpResult); + return GetClassInfoA (hInstance, (LPCSTR) lpClassName, (LPWNDCLASSA) lpWndClass); } -/* Error if CommandLineToArgv used: Unicode-only */ +/* Skipping RegisterClassEx because need to intercept so we can provide our own window procedure and handle split notify messages; split-simple WNDCLASSEX; NT 4.0+ only */ -INT -qxeShellAbout (HWND hWnd, const Extbyte * szApp, const Extbyte * szOtherStuff, HICON hIcon) +/* NOTE: NT 4.0+ only */ +BOOL +qxeGetClassInfoEx (HINSTANCE arg1, const Extbyte * arg2, LPWNDCLASSEXW arg3) { if (XEUNICODE_P) - return ShellAboutW (hWnd, (LPCWSTR) szApp, (LPCWSTR) szOtherStuff, hIcon); + return GetClassInfoExW (arg1, (LPCWSTR) arg2, arg3); else - return ShellAboutA (hWnd, (LPCSTR) szApp, (LPCSTR) szOtherStuff, hIcon); + return GetClassInfoExA (arg1, (LPCSTR) arg2, (LPWNDCLASSEXA) arg3); } -HICON -qxeExtractAssociatedIcon (HINSTANCE hInst, Extbyte * lpIconPath, LPWORD lpiIcon) +HWND +qxeCreateWindowEx (DWORD dwExStyle, const Extbyte * lpClassName, const Extbyte * lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { if (XEUNICODE_P) - return ExtractAssociatedIconW (hInst, (LPWSTR) lpIconPath, lpiIcon); + return CreateWindowExW (dwExStyle, (LPCWSTR) lpClassName, (LPCWSTR) lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); else - return ExtractAssociatedIconA (hInst, (LPSTR) lpIconPath, lpiIcon); + return CreateWindowExA (dwExStyle, (LPCSTR) lpClassName, (LPCSTR) lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); } -HICON -qxeExtractIcon (HINSTANCE hInst, const Extbyte * lpszExeFileName, UINT nIconIndex) +HWND +qxeCreateDialogParam (HINSTANCE hInstance, const Extbyte * lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { if (XEUNICODE_P) - return ExtractIconW (hInst, (LPCWSTR) lpszExeFileName, nIconIndex); + return CreateDialogParamW (hInstance, (LPCWSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); else - return ExtractIconA (hInst, (LPCSTR) lpszExeFileName, nIconIndex); + return CreateDialogParamA (hInstance, (LPCSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); } -#if !defined (CYGWIN_HEADERS) - -/* NOTE: NT 4.0+ only */ -DWORD -qxeDoEnvironmentSubst (Extbyte * szString, UINT cbString) +/* NOTE: error in Cygwin prototype (no split) but fixable with typedef */ +HWND +qxeCreateDialogIndirectParam (HINSTANCE hInstance, LPCDLGTEMPLATEW lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { if (XEUNICODE_P) - return DoEnvironmentSubstW ((LPWSTR) szString, cbString); + return CreateDialogIndirectParamW (hInstance, lpTemplate, hWndParent, lpDialogFunc, dwInitParam); else - return DoEnvironmentSubstA ((LPSTR) szString, cbString); + return CreateDialogIndirectParamA (hInstance, (LPCDLGTEMPLATEA) lpTemplate, hWndParent, lpDialogFunc, dwInitParam); } -#endif /* !defined (CYGWIN_HEADERS) */ - -/* Error if FindEnvironmentString used: causes link error; NT 4.0+ only */ - -/* Skipping ExtractIconEx because NT 4.0+ only, error in Cygwin prototype */ - -/* NOTE: NT 4.0+ only */ int -qxeSHFileOperation (LPSHFILEOPSTRUCTW lpFileOp) +qxeDialogBoxParam (HINSTANCE hInstance, const Extbyte * lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { if (XEUNICODE_P) - return SHFileOperationW (lpFileOp); + return DialogBoxParamW (hInstance, (LPCWSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); else - return SHFileOperationA ((LPSHFILEOPSTRUCTA) lpFileOp); + return DialogBoxParamA (hInstance, (LPCSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); } -/* NOTE: NT 4.0+ only */ -BOOL -qxeShellExecuteEx (LPSHELLEXECUTEINFOW lpExecInfo) +/* NOTE: error in Cygwin prototype (no split) but fixable with typedef */ +int +qxeDialogBoxIndirectParam (HINSTANCE hInstance, LPCDLGTEMPLATEW hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { if (XEUNICODE_P) - return ShellExecuteExW (lpExecInfo); + return DialogBoxIndirectParamW (hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam); else - return ShellExecuteExA ((LPSHELLEXECUTEINFOA) lpExecInfo); + return DialogBoxIndirectParamA (hInstance, (LPCDLGTEMPLATEA) hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam); } -/* Error if WinExecError used: causes link error; NT 4.0+ only */ - -#if !defined (CYGWIN_HEADERS) - -/* NOTE: NT 4.0+ only */ -HRESULT -qxeSHQueryRecycleBin (const Extbyte * pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo) +BOOL +qxeSetDlgItemText (HWND hDlg, int nIDDlgItem, const Extbyte * lpString) { if (XEUNICODE_P) - return SHQueryRecycleBinW ((LPCWSTR) pszRootPath, pSHQueryRBInfo); + return SetDlgItemTextW (hDlg, nIDDlgItem, (LPCWSTR) lpString); else - return SHQueryRecycleBinA ((LPCSTR) pszRootPath, pSHQueryRBInfo); + return SetDlgItemTextA (hDlg, nIDDlgItem, (LPCSTR) lpString); } -#endif /* !defined (CYGWIN_HEADERS) */ - -#if !defined (CYGWIN_HEADERS) - -/* NOTE: NT 4.0+ only */ -HRESULT -qxeSHEmptyRecycleBin (HWND hwnd, const Extbyte * pszRootPath, DWORD dwFlags) +UINT +qxeGetDlgItemText (HWND hDlg, int nIDDlgItem, Extbyte * lpString, int nMaxCount) { if (XEUNICODE_P) - return SHEmptyRecycleBinW (hwnd, (LPCWSTR) pszRootPath, dwFlags); + return GetDlgItemTextW (hDlg, nIDDlgItem, (LPWSTR) lpString, nMaxCount); else - return SHEmptyRecycleBinA (hwnd, (LPCSTR) pszRootPath, dwFlags); + return GetDlgItemTextA (hDlg, nIDDlgItem, (LPSTR) lpString, nMaxCount); } -#endif /* !defined (CYGWIN_HEADERS) */ - -/* Error if Shell_NotifyIcon used: split-sized NOTIFYICONDATA, NT 4.0+ only */ - -/* Skipping SHGetFileInfo because split-sized SHFILEINFO, NT 4.0+ only */ - -/* Error if SHGetDiskFreeSpace used: causes link error; NT 4.0+ only */ - -#if !defined (CYGWIN_HEADERS) - -/* NOTE: NT 4.0+ only */ -BOOL -qxeSHGetNewLinkInfo (const Extbyte * pszLinkTo, const Extbyte * pszDir, Extbyte * pszName, BOOL * pfMustCopy, UINT uFlags) +LONG +qxeSendDlgItemMessage (HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) { if (XEUNICODE_P) - return SHGetNewLinkInfoW ((LPCWSTR) pszLinkTo, (LPCWSTR) pszDir, (LPWSTR) pszName, pfMustCopy, uFlags); + return SendDlgItemMessageW (hDlg, nIDDlgItem, Msg, wParam, lParam); else - return SHGetNewLinkInfoA ((LPCSTR) pszLinkTo, (LPCSTR) pszDir, (LPSTR) pszName, pfMustCopy, uFlags); + return SendDlgItemMessageA (hDlg, nIDDlgItem, Msg, wParam, lParam); } -#endif /* !defined (CYGWIN_HEADERS) */ +/* Error if DefDlgProc used: return value is conditionalized on _MAC, messes up parser */ #if !defined (CYGWIN_HEADERS) -/* NOTE: NT 4.0+ only */ BOOL -qxeSHInvokePrinterCommand (HWND hwnd, UINT uAction, const Extbyte * lpBuf1, const Extbyte * lpBuf2, BOOL fModal) +qxeCallMsgFilter (LPMSG lpMsg, int nCode) { if (XEUNICODE_P) - return SHInvokePrinterCommandW (hwnd, uAction, (LPCWSTR) lpBuf1, (LPCWSTR) lpBuf2, fModal); + return CallMsgFilterW (lpMsg, nCode); else - return SHInvokePrinterCommandA (hwnd, uAction, (LPCSTR) lpBuf1, (LPCSTR) lpBuf2, fModal); + return CallMsgFilterA (lpMsg, nCode); } #endif /* !defined (CYGWIN_HEADERS) */ - -/*----------------------------------------------------------------------*/ -/* Processing file WINCON.H */ -/*----------------------------------------------------------------------*/ - -BOOL -qxePeekConsoleInput (HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead) +UINT +qxeRegisterClipboardFormat (const Extbyte * lpszFormat) { if (XEUNICODE_P) - return PeekConsoleInputW (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); + return RegisterClipboardFormatW ((LPCWSTR) lpszFormat); else - return PeekConsoleInputA (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); + return RegisterClipboardFormatA ((LPCSTR) lpszFormat); } -BOOL -qxeReadConsoleInput (HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead) +int +qxeGetClipboardFormatName (UINT format, Extbyte * lpszFormatName, int cchMaxCount) { if (XEUNICODE_P) - return ReadConsoleInputW (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); + return GetClipboardFormatNameW (format, (LPWSTR) lpszFormatName, cchMaxCount); else - return ReadConsoleInputA (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); + return GetClipboardFormatNameA (format, (LPSTR) lpszFormatName, cchMaxCount); } BOOL -qxeWriteConsoleInput (HANDLE hConsoleInput, CONST INPUT_RECORD * lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten) +qxeCharToOem (const Extbyte * lpszSrc, LPSTR lpszDst) { if (XEUNICODE_P) - return WriteConsoleInputW (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsWritten); + return CharToOemW ((LPCWSTR) lpszSrc, lpszDst); else - return WriteConsoleInputA (hConsoleInput, lpBuffer, nLength, lpNumberOfEventsWritten); + return CharToOemA ((LPCSTR) lpszSrc, lpszDst); } BOOL -qxeReadConsoleOutput (HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion) +qxeOemToChar (LPCSTR lpszSrc, Extbyte * lpszDst) { if (XEUNICODE_P) - return ReadConsoleOutputW (hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpReadRegion); + return OemToCharW (lpszSrc, (LPWSTR) lpszDst); else - return ReadConsoleOutputA (hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpReadRegion); + return OemToCharA (lpszSrc, (LPSTR) lpszDst); } BOOL -qxeWriteConsoleOutput (HANDLE hConsoleOutput, CONST CHAR_INFO * lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion) +qxeCharToOemBuff (const Extbyte * lpszSrc, LPSTR lpszDst, DWORD cchDstLength) { if (XEUNICODE_P) - return WriteConsoleOutputW (hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpWriteRegion); + return CharToOemBuffW ((LPCWSTR) lpszSrc, lpszDst, cchDstLength); else - return WriteConsoleOutputA (hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpWriteRegion); + return CharToOemBuffA ((LPCSTR) lpszSrc, lpszDst, cchDstLength); } BOOL -qxeReadConsoleOutputCharacter (HANDLE hConsoleOutput, Extbyte * lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead) +qxeOemToCharBuff (LPCSTR lpszSrc, Extbyte * lpszDst, DWORD cchDstLength) { if (XEUNICODE_P) - return ReadConsoleOutputCharacterW (hConsoleOutput, (LPWSTR) lpCharacter, nLength, dwReadCoord, lpNumberOfCharsRead); + return OemToCharBuffW (lpszSrc, (LPWSTR) lpszDst, cchDstLength); else - return ReadConsoleOutputCharacterA (hConsoleOutput, (LPSTR) lpCharacter, nLength, dwReadCoord, lpNumberOfCharsRead); + return OemToCharBuffA (lpszSrc, (LPSTR) lpszDst, cchDstLength); } -BOOL -qxeWriteConsoleOutputCharacter (HANDLE hConsoleOutput, const Extbyte * lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten) +Extbyte * +qxeCharUpper (Extbyte * lpsz) { if (XEUNICODE_P) - return WriteConsoleOutputCharacterW (hConsoleOutput, (LPCWSTR) lpCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten); + return (Extbyte *) CharUpperW ((LPWSTR) lpsz); else - return WriteConsoleOutputCharacterA (hConsoleOutput, (LPCSTR) lpCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten); + return (Extbyte *) CharUpperA ((LPSTR) lpsz); } -/* Error if FillConsoleOutputCharacter used: split CHAR */ - -BOOL -qxeScrollConsoleScreenBuffer (HANDLE hConsoleOutput, CONST SMALL_RECT * lpScrollRectangle, CONST SMALL_RECT * lpClipRectangle, COORD dwDestinationOrigin, CONST CHAR_INFO * lpFill) +DWORD +qxeCharUpperBuff (Extbyte * lpsz, DWORD cchLength) { if (XEUNICODE_P) - return ScrollConsoleScreenBufferW (hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill); + return CharUpperBuffW ((LPWSTR) lpsz, cchLength); else - return ScrollConsoleScreenBufferA (hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill); + return CharUpperBuffA ((LPSTR) lpsz, cchLength); } -DWORD -qxeGetConsoleTitle (Extbyte * lpConsoleTitle, DWORD nSize) +Extbyte * +qxeCharLower (Extbyte * lpsz) { if (XEUNICODE_P) - return GetConsoleTitleW ((LPWSTR) lpConsoleTitle, nSize); + return (Extbyte *) CharLowerW ((LPWSTR) lpsz); else - return GetConsoleTitleA ((LPSTR) lpConsoleTitle, nSize); + return (Extbyte *) CharLowerA ((LPSTR) lpsz); } -BOOL -qxeSetConsoleTitle (const Extbyte * lpConsoleTitle) +DWORD +qxeCharLowerBuff (Extbyte * lpsz, DWORD cchLength) { if (XEUNICODE_P) - return SetConsoleTitleW ((LPCWSTR) lpConsoleTitle); + return CharLowerBuffW ((LPWSTR) lpsz, cchLength); else - return SetConsoleTitleA ((LPCSTR) lpConsoleTitle); + return CharLowerBuffA ((LPSTR) lpsz, cchLength); } -BOOL -qxeReadConsole (HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved) +Extbyte * +qxeCharNext (const Extbyte * lpsz) { if (XEUNICODE_P) - return ReadConsoleW (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved); + return (Extbyte *) CharNextW ((LPCWSTR) lpsz); else - return ReadConsoleA (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved); + return (Extbyte *) CharNextA ((LPCSTR) lpsz); } -BOOL -qxeWriteConsole (HANDLE hConsoleOutput, CONST VOID * lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved) +Extbyte * +qxeCharPrev (const Extbyte * lpszStart, const Extbyte * lpszCurrent) { if (XEUNICODE_P) - return WriteConsoleW (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved); + return (Extbyte *) CharPrevW ((LPCWSTR) lpszStart, (LPCWSTR) lpszCurrent); else - return WriteConsoleA (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved); + return (Extbyte *) CharPrevA ((LPCSTR) lpszStart, (LPCSTR) lpszCurrent); } +/* Error if IsCharAlpha used: split CHAR */ -/*----------------------------------------------------------------------*/ -/* Processing file IMM.H */ -/*----------------------------------------------------------------------*/ +/* Error if IsCharAlphaNumeric used: split CHAR */ -#if defined (HAVE_MS_WINDOWS) +/* Error if IsCharUpper used: split CHAR */ -HKL -qxeImmInstallIME (const Extbyte * lpszIMEFileName, const Extbyte * lpszLayoutText) +/* Error if IsCharLower used: split CHAR */ + +int +qxeGetKeyNameText (LONG lParam, Extbyte * lpString, int nSize) { if (XEUNICODE_P) - return ImmInstallIMEW ((LPCWSTR) lpszIMEFileName, (LPCWSTR) lpszLayoutText); + return GetKeyNameTextW (lParam, (LPWSTR) lpString, nSize); else - return ImmInstallIMEA ((LPCSTR) lpszIMEFileName, (LPCSTR) lpszLayoutText); + return GetKeyNameTextA (lParam, (LPSTR) lpString, nSize); } -#endif /* defined (HAVE_MS_WINDOWS) */ +/* Skipping VkKeyScan because split CHAR */ -#if defined (HAVE_MS_WINDOWS) +/* Error if VkKeyScanEx used: split CHAR; NT 4.0+ only */ UINT -qxeImmGetDescription (HKL arg1, Extbyte * arg2, UINT uBufLen) +qxeMapVirtualKey (UINT uCode, UINT uMapType) { if (XEUNICODE_P) - return ImmGetDescriptionW (arg1, (LPWSTR) arg2, uBufLen); + return MapVirtualKeyW (uCode, uMapType); else - return ImmGetDescriptionA (arg1, (LPSTR) arg2, uBufLen); + return MapVirtualKeyA (uCode, uMapType); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - +/* NOTE: NT 4.0+ only */ UINT -qxeImmGetIMEFileName (HKL arg1, Extbyte * arg2, UINT uBufLen) +qxeMapVirtualKeyEx (UINT uCode, UINT uMapType, HKL dwhkl) { if (XEUNICODE_P) - return ImmGetIMEFileNameW (arg1, (LPWSTR) arg2, uBufLen); + return MapVirtualKeyExW (uCode, uMapType, dwhkl); else - return ImmGetIMEFileNameA (arg1, (LPSTR) arg2, uBufLen); + return MapVirtualKeyExA (uCode, uMapType, dwhkl); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -LONG -qxeImmGetCompositionString (HIMC arg1, DWORD arg2, LPVOID arg3, DWORD arg4) +HACCEL +qxeLoadAccelerators (HINSTANCE hInstance, const Extbyte * lpTableName) { if (XEUNICODE_P) - return ImmGetCompositionStringW (arg1, arg2, arg3, arg4); + return LoadAcceleratorsW (hInstance, (LPCWSTR) lpTableName); else - return ImmGetCompositionStringA (arg1, arg2, arg3, arg4); + return LoadAcceleratorsA (hInstance, (LPCSTR) lpTableName); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -BOOL -qxeImmSetCompositionString (HIMC arg1, DWORD dwIndex, LPCVOID lpComp, DWORD arg4, LPCVOID lpRead, DWORD arg6) +HACCEL +qxeCreateAcceleratorTable (LPACCEL arg1, int arg2) { if (XEUNICODE_P) - return ImmSetCompositionStringW (arg1, dwIndex, lpComp, arg4, lpRead, arg6); + return CreateAcceleratorTableW (arg1, arg2); else - return ImmSetCompositionStringA (arg1, dwIndex, lpComp, arg4, lpRead, arg6); + return CreateAcceleratorTableA (arg1, arg2); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -DWORD -qxeImmGetCandidateListCount (HIMC arg1, LPDWORD lpdwListCount) +int +qxeCopyAcceleratorTable (HACCEL hAccelSrc, LPACCEL lpAccelDst, int cAccelEntries) { if (XEUNICODE_P) - return ImmGetCandidateListCountW (arg1, lpdwListCount); + return CopyAcceleratorTableW (hAccelSrc, lpAccelDst, cAccelEntries); else - return ImmGetCandidateListCountA (arg1, lpdwListCount); + return CopyAcceleratorTableA (hAccelSrc, lpAccelDst, cAccelEntries); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -DWORD -qxeImmGetCandidateList (HIMC arg1, DWORD deIndex, LPCANDIDATELIST arg3, DWORD dwBufLen) +int +qxeTranslateAccelerator (HWND hWnd, HACCEL hAccTable, LPMSG lpMsg) { if (XEUNICODE_P) - return ImmGetCandidateListW (arg1, deIndex, arg3, dwBufLen); + return TranslateAcceleratorW (hWnd, hAccTable, lpMsg); else - return ImmGetCandidateListA (arg1, deIndex, arg3, dwBufLen); + return TranslateAcceleratorA (hWnd, hAccTable, lpMsg); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -DWORD -qxeImmGetGuideLine (HIMC arg1, DWORD dwIndex, Extbyte * arg3, DWORD dwBufLen) +HMENU +qxeLoadMenu (HINSTANCE hInstance, const Extbyte * lpMenuName) { if (XEUNICODE_P) - return ImmGetGuideLineW (arg1, dwIndex, (LPWSTR) arg3, dwBufLen); + return LoadMenuW (hInstance, (LPCWSTR) lpMenuName); else - return ImmGetGuideLineA (arg1, dwIndex, (LPSTR) arg3, dwBufLen); + return LoadMenuA (hInstance, (LPCSTR) lpMenuName); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -/* Skipping ImmGetCompositionFont because split-sized LOGFONT */ - -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -/* Skipping ImmSetCompositionFont because split-sized LOGFONT */ - -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) +HMENU +qxeLoadMenuIndirect (CONST MENUTEMPLATEW * lpMenuTemplate) +{ + if (XEUNICODE_P) + return LoadMenuIndirectW (lpMenuTemplate); + else + return LoadMenuIndirectA ((CONST MENUTEMPLATEA *) lpMenuTemplate); +} -/* NOTE: // split-simple REGISTERWORD */ BOOL -qxeImmConfigureIME (HKL arg1, HWND arg2, DWORD arg3, LPVOID arg4) +qxeChangeMenu (HMENU hMenu, UINT cmd, const Extbyte * lpszNewItem, UINT cmdInsert, UINT flags) { if (XEUNICODE_P) - return ImmConfigureIMEW (arg1, arg2, arg3, arg4); + return ChangeMenuW (hMenu, cmd, (LPCWSTR) lpszNewItem, cmdInsert, flags); else - return ImmConfigureIMEA (arg1, arg2, arg3, arg4); + return ChangeMenuA (hMenu, cmd, (LPCSTR) lpszNewItem, cmdInsert, flags); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -/* NOTE: // strings of various sorts */ -LRESULT -qxeImmEscape (HKL arg1, HIMC arg2, UINT arg3, LPVOID arg4) +int +qxeGetMenuString (HMENU hMenu, UINT uIDItem, Extbyte * lpString, int nMaxCount, UINT uFlag) { if (XEUNICODE_P) - return ImmEscapeW (arg1, arg2, arg3, arg4); + return GetMenuStringW (hMenu, uIDItem, (LPWSTR) lpString, nMaxCount, uFlag); else - return ImmEscapeA (arg1, arg2, arg3, arg4); + return GetMenuStringA (hMenu, uIDItem, (LPSTR) lpString, nMaxCount, uFlag); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -DWORD -qxeImmGetConversionList (HKL arg1, HIMC arg2, const Extbyte * arg3, LPCANDIDATELIST arg4, DWORD dwBufLen, UINT uFlag) +BOOL +qxeInsertMenu (HMENU hMenu, UINT uPosition, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem) { if (XEUNICODE_P) - return ImmGetConversionListW (arg1, arg2, (LPCWSTR) arg3, arg4, dwBufLen, uFlag); + return InsertMenuW (hMenu, uPosition, uFlags, uIDNewItem, (LPCWSTR) lpNewItem); else - return ImmGetConversionListA (arg1, arg2, (LPCSTR) arg3, arg4, dwBufLen, uFlag); + return InsertMenuA (hMenu, uPosition, uFlags, uIDNewItem, (LPCSTR) lpNewItem); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - BOOL -qxeImmIsUIMessage (HWND arg1, UINT arg2, WPARAM arg3, LPARAM arg4) +qxeAppendMenu (HMENU hMenu, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem) { if (XEUNICODE_P) - return ImmIsUIMessageW (arg1, arg2, arg3, arg4); + return AppendMenuW (hMenu, uFlags, uIDNewItem, (LPCWSTR) lpNewItem); else - return ImmIsUIMessageA (arg1, arg2, arg3, arg4); + return AppendMenuA (hMenu, uFlags, uIDNewItem, (LPCSTR) lpNewItem); } -#endif /* defined (HAVE_MS_WINDOWS) */ +BOOL +qxeModifyMenu (HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem) +{ + if (XEUNICODE_P) + return ModifyMenuW (hMnu, uPosition, uFlags, uIDNewItem, (LPCWSTR) lpNewItem); + else + return ModifyMenuA (hMnu, uPosition, uFlags, uIDNewItem, (LPCSTR) lpNewItem); +} -#if defined (HAVE_MS_WINDOWS) +/* NOTE: NT 4.0+ only */ +BOOL +qxeInsertMenuItem (HMENU arg1, UINT arg2, BOOL arg3, LPCMENUITEMINFOW arg4) +{ + if (XEUNICODE_P) + return InsertMenuItemW (arg1, arg2, arg3, arg4); + else + return InsertMenuItemA (arg1, arg2, arg3, (LPCMENUITEMINFOA) arg4); +} +/* NOTE: NT 4.0+ only */ BOOL -qxeImmRegisterWord (HKL arg1, const Extbyte * lpszReading, DWORD arg3, const Extbyte * lpszRegister) +qxeGetMenuItemInfo (HMENU arg1, UINT arg2, BOOL arg3, LPMENUITEMINFOW arg4) { if (XEUNICODE_P) - return ImmRegisterWordW (arg1, (LPCWSTR) lpszReading, arg3, (LPCWSTR) lpszRegister); + return GetMenuItemInfoW (arg1, arg2, arg3, arg4); else - return ImmRegisterWordA (arg1, (LPCSTR) lpszReading, arg3, (LPCSTR) lpszRegister); + return GetMenuItemInfoA (arg1, arg2, arg3, (LPMENUITEMINFOA) arg4); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - +/* NOTE: NT 4.0+ only */ BOOL -qxeImmUnregisterWord (HKL arg1, const Extbyte * lpszReading, DWORD arg3, const Extbyte * lpszUnregister) +qxeSetMenuItemInfo (HMENU arg1, UINT arg2, BOOL arg3, LPCMENUITEMINFOW arg4) { if (XEUNICODE_P) - return ImmUnregisterWordW (arg1, (LPCWSTR) lpszReading, arg3, (LPCWSTR) lpszUnregister); + return SetMenuItemInfoW (arg1, arg2, arg3, arg4); else - return ImmUnregisterWordA (arg1, (LPCSTR) lpszReading, arg3, (LPCSTR) lpszUnregister); + return SetMenuItemInfoA (arg1, arg2, arg3, (LPCMENUITEMINFOA) arg4); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -/* Error if ImmGetRegisterWordStyle used: split-sized STYLEBUF */ - -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -UINT -qxeImmEnumRegisterWord (HKL arg1, REGISTERWORDENUMPROCW arg2, const Extbyte * lpszReading, DWORD arg4, const Extbyte * lpszRegister, LPVOID arg6) +int +qxeDrawText (HDC hDC, const Extbyte * lpString, int nCount, LPRECT lpRect, UINT uFormat) { if (XEUNICODE_P) - return ImmEnumRegisterWordW (arg1, arg2, (LPCWSTR) lpszReading, arg4, (LPCWSTR) lpszRegister, arg6); + return DrawTextW (hDC, (LPCWSTR) lpString, nCount, lpRect, uFormat); else - return ImmEnumRegisterWordA (arg1, (REGISTERWORDENUMPROCA) arg2, (LPCSTR) lpszReading, arg4, (LPCSTR) lpszRegister, arg6); + return DrawTextA (hDC, (LPCSTR) lpString, nCount, lpRect, uFormat); } -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) - -/* Error if ImmGetImeMenuItems used: split-sized IMEMENUITEMINFO */ - -#endif /* defined (HAVE_MS_WINDOWS) */ - - -/*----------------------------------------------------------------------*/ -/* Processing file DDEML.H */ -/*----------------------------------------------------------------------*/ - -UINT -qxeDdeInitialize (LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes) +/* NOTE: NT 4.0+ only */ +int +qxeDrawTextEx (HDC arg1, Extbyte * arg2, int arg3, LPRECT arg4, UINT arg5, LPDRAWTEXTPARAMS arg6) { if (XEUNICODE_P) - return DdeInitializeW (pidInst, pfnCallback, afCmd, ulRes); + return DrawTextExW (arg1, (LPWSTR) arg2, arg3, arg4, arg5, arg6); else - return DdeInitializeA (pidInst, pfnCallback, afCmd, ulRes); + return DrawTextExA (arg1, (LPSTR) arg2, arg3, arg4, arg5, arg6); } -/* Skipping DdeCreateStringHandle because error in Cygwin prototype */ - -DWORD -qxeDdeQueryString (DWORD idInst, HSZ hsz, Extbyte * psz, DWORD cchMax, int iCodePage) +BOOL +qxeGrayString (HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int X, int Y, int nWidth, int nHeight) { if (XEUNICODE_P) - return DdeQueryStringW (idInst, hsz, (LPWSTR) psz, cchMax, iCodePage); + return GrayStringW (hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight); else - return DdeQueryStringA (idInst, hsz, (LPSTR) psz, cchMax, iCodePage); + return GrayStringA (hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight); } - -/*----------------------------------------------------------------------*/ -/* Processing file WINUSER.H */ -/*----------------------------------------------------------------------*/ - -int -qxewvsprintf (Extbyte * arg1, const Extbyte * arg2, va_list arglist) +/* NOTE: NT 4.0+ only */ +BOOL +qxeDrawState (HDC arg1, HBRUSH arg2, DRAWSTATEPROC arg3, LPARAM arg4, WPARAM arg5, int arg6, int arg7, int arg8, int arg9, UINT arg10) { if (XEUNICODE_P) - return wvsprintfW ((LPWSTR) arg1, (LPCWSTR) arg2, arglist); + return DrawStateW (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); else - return wvsprintfA ((LPSTR) arg1, (LPCSTR) arg2, arglist); + return DrawStateA (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } -HKL -qxeLoadKeyboardLayout (const Extbyte * pwszKLID, UINT Flags) +LONG +qxeTabbedTextOut (HDC hDC, int X, int Y, const Extbyte * lpString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin) { if (XEUNICODE_P) - return LoadKeyboardLayoutW ((LPCWSTR) pwszKLID, Flags); + return TabbedTextOutW (hDC, X, Y, (LPCWSTR) lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); else - return LoadKeyboardLayoutA ((LPCSTR) pwszKLID, Flags); + return TabbedTextOutA (hDC, X, Y, (LPCSTR) lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); } -BOOL -qxeGetKeyboardLayoutName (Extbyte * pwszKLID) +DWORD +qxeGetTabbedTextExtent (HDC hDC, const Extbyte * lpString, int nCount, int nTabPositions, LPINT lpnTabStopPositions) { if (XEUNICODE_P) - return GetKeyboardLayoutNameW ((LPWSTR) pwszKLID); + return GetTabbedTextExtentW (hDC, (LPCWSTR) lpString, nCount, nTabPositions, lpnTabStopPositions); else - return GetKeyboardLayoutNameA ((LPSTR) pwszKLID); + return GetTabbedTextExtentA (hDC, (LPCSTR) lpString, nCount, nTabPositions, lpnTabStopPositions); } -/* Error if CreateDesktop used: split-sized LPDEVMODE */ - -HDESK -qxeOpenDesktop (Extbyte * lpszDesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess) +BOOL +qxeSetProp (HWND hWnd, const Extbyte * lpString, HANDLE hData) { if (XEUNICODE_P) - return OpenDesktopW ((LPWSTR) lpszDesktop, dwFlags, fInherit, dwDesiredAccess); + return SetPropW (hWnd, (LPCWSTR) lpString, hData); else - return OpenDesktopA ((LPSTR) lpszDesktop, dwFlags, fInherit, dwDesiredAccess); + return SetPropA (hWnd, (LPCSTR) lpString, hData); } -/* NOTE: // callback fun differs only in string pointer type */ -BOOL -qxeEnumDesktops (HWINSTA hwinsta, DESKTOPENUMPROCW lpEnumFunc, LPARAM lParam) +HANDLE +qxeGetProp (HWND hWnd, const Extbyte * lpString) { if (XEUNICODE_P) - return EnumDesktopsW (hwinsta, lpEnumFunc, lParam); + return GetPropW (hWnd, (LPCWSTR) lpString); else - return EnumDesktopsA (hwinsta, (DESKTOPENUMPROCA) lpEnumFunc, lParam); + return GetPropA (hWnd, (LPCSTR) lpString); } -HWINSTA -qxeCreateWindowStation (Extbyte * lpwinsta, DWORD dwReserved, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa) +HANDLE +qxeRemoveProp (HWND hWnd, const Extbyte * lpString) { if (XEUNICODE_P) - return CreateWindowStationW ((LPWSTR) lpwinsta, dwReserved, dwDesiredAccess, lpsa); + return RemovePropW (hWnd, (LPCWSTR) lpString); else - return CreateWindowStationA ((LPSTR) lpwinsta, dwReserved, dwDesiredAccess, lpsa); + return RemovePropA (hWnd, (LPCSTR) lpString); } -HWINSTA -qxeOpenWindowStation (Extbyte * lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess) +/* NOTE: // callback fun differs only in string pointer type */ +int +qxeEnumPropsEx (HWND hWnd, PROPENUMPROCEXW lpEnumFunc, LPARAM lParam) { if (XEUNICODE_P) - return OpenWindowStationW ((LPWSTR) lpszWinSta, fInherit, dwDesiredAccess); + return EnumPropsExW (hWnd, lpEnumFunc, lParam); else - return OpenWindowStationA ((LPSTR) lpszWinSta, fInherit, dwDesiredAccess); + return EnumPropsExA (hWnd, (PROPENUMPROCEXA) lpEnumFunc, lParam); } /* NOTE: // callback fun differs only in string pointer type */ -BOOL -qxeEnumWindowStations (WINSTAENUMPROCW lpEnumFunc, LPARAM lParam) +int +qxeEnumProps (HWND hWnd, PROPENUMPROCW lpEnumFunc) { if (XEUNICODE_P) - return EnumWindowStationsW (lpEnumFunc, lParam); + return EnumPropsW (hWnd, lpEnumFunc); else - return EnumWindowStationsA ((WINSTAENUMPROCA) lpEnumFunc, lParam); + return EnumPropsA (hWnd, (PROPENUMPROCA) lpEnumFunc); } BOOL -qxeGetUserObjectInformation (HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded) +qxeSetWindowText (HWND hWnd, const Extbyte * lpString) { if (XEUNICODE_P) - return GetUserObjectInformationW (hObj, nIndex, pvInfo, nLength, lpnLengthNeeded); + return SetWindowTextW (hWnd, (LPCWSTR) lpString); else - return GetUserObjectInformationA (hObj, nIndex, pvInfo, nLength, lpnLengthNeeded); + return SetWindowTextA (hWnd, (LPCSTR) lpString); } -BOOL -qxeSetUserObjectInformation (HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength) +int +qxeGetWindowText (HWND hWnd, Extbyte * lpString, int nMaxCount) { if (XEUNICODE_P) - return SetUserObjectInformationW (hObj, nIndex, pvInfo, nLength); + return GetWindowTextW (hWnd, (LPWSTR) lpString, nMaxCount); else - return SetUserObjectInformationA (hObj, nIndex, pvInfo, nLength); + return GetWindowTextA (hWnd, (LPSTR) lpString, nMaxCount); } -UINT -qxeRegisterWindowMessage (const Extbyte * lpString) +int +qxeGetWindowTextLength (HWND hWnd) { if (XEUNICODE_P) - return RegisterWindowMessageW ((LPCWSTR) lpString); + return GetWindowTextLengthW (hWnd); else - return RegisterWindowMessageA ((LPCSTR) lpString); + return GetWindowTextLengthA (hWnd); } -BOOL -qxeGetMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) +int +qxeMessageBox (HWND hWnd, const Extbyte * lpText, const Extbyte * lpCaption, UINT uType) { if (XEUNICODE_P) - return GetMessageW (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); + return MessageBoxW (hWnd, (LPCWSTR) lpText, (LPCWSTR) lpCaption, uType); else - return GetMessageA (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); + return MessageBoxA (hWnd, (LPCSTR) lpText, (LPCSTR) lpCaption, uType); } -LONG -qxeDispatchMessage (CONST MSG * lpMsg) +int +qxeMessageBoxEx (HWND hWnd, const Extbyte * lpText, const Extbyte * lpCaption, UINT uType, WORD wLanguageId) { if (XEUNICODE_P) - return DispatchMessageW (lpMsg); + return MessageBoxExW (hWnd, (LPCWSTR) lpText, (LPCWSTR) lpCaption, uType, wLanguageId); else - return DispatchMessageA (lpMsg); + return MessageBoxExA (hWnd, (LPCSTR) lpText, (LPCSTR) lpCaption, uType, wLanguageId); } -BOOL -qxePeekMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) +/* NOTE: NT 4.0+ only */ +int +qxeMessageBoxIndirect (LPMSGBOXPARAMSW arg1) { if (XEUNICODE_P) - return PeekMessageW (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + return MessageBoxIndirectW (arg1); else - return PeekMessageA (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); + return MessageBoxIndirectA ((LPMSGBOXPARAMSA) arg1); } -/* Skipping SendMessage because split messages and structures */ - -LRESULT -qxeSendMessageTimeout (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, LPDWORD lpdwResult) +LONG +qxeGetWindowLong (HWND hWnd, int nIndex) { if (XEUNICODE_P) - return SendMessageTimeoutW (hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult); + return GetWindowLongW (hWnd, nIndex); else - return SendMessageTimeoutA (hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult); + return GetWindowLongA (hWnd, nIndex); } -BOOL -qxeSendNotifyMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +LONG +qxeSetWindowLong (HWND hWnd, int nIndex, LONG dwNewLong) { if (XEUNICODE_P) - return SendNotifyMessageW (hWnd, Msg, wParam, lParam); + return SetWindowLongW (hWnd, nIndex, dwNewLong); else - return SendNotifyMessageA (hWnd, Msg, wParam, lParam); + return SetWindowLongA (hWnd, nIndex, dwNewLong); } -BOOL -qxeSendMessageCallback (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, SENDASYNCPROC lpResultCallBack, DWORD dwData) +DWORD +qxeGetClassLong (HWND hWnd, int nIndex) { if (XEUNICODE_P) - return SendMessageCallbackW (hWnd, Msg, wParam, lParam, lpResultCallBack, dwData); + return GetClassLongW (hWnd, nIndex); else - return SendMessageCallbackA (hWnd, Msg, wParam, lParam, lpResultCallBack, dwData); + return GetClassLongA (hWnd, nIndex); } -/* Error if BroadcastSystemMessage used: win95 version not split; NT 4.0+ only */ - -/* Error if RegisterDeviceNotification used: NT 5.0+ only */ - -BOOL -qxePostMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +DWORD +qxeSetClassLong (HWND hWnd, int nIndex, LONG dwNewLong) { if (XEUNICODE_P) - return PostMessageW (hWnd, Msg, wParam, lParam); + return SetClassLongW (hWnd, nIndex, dwNewLong); else - return PostMessageA (hWnd, Msg, wParam, lParam); + return SetClassLongA (hWnd, nIndex, dwNewLong); } -BOOL -qxePostThreadMessage (DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam) +HWND +qxeFindWindow (const Extbyte * lpClassName, const Extbyte * lpWindowName) { if (XEUNICODE_P) - return PostThreadMessageW (idThread, Msg, wParam, lParam); + return FindWindowW ((LPCWSTR) lpClassName, (LPCWSTR) lpWindowName); else - return PostThreadMessageA (idThread, Msg, wParam, lParam); + return FindWindowA ((LPCSTR) lpClassName, (LPCSTR) lpWindowName); } -/* Skipping DefWindowProc because return value is conditionalized on _MAC, messes up parser */ - -/* Error if CallWindowProc used: two versions, STRICT and non-STRICT */ - -/* Error if CallWindowProc used: two versions, STRICT and non-STRICT */ - -/* Skipping RegisterClass because need to intercept so we can provide our own window procedure and handle split notify messages; split-simple WNDCLASS */ - -/* Skipping UnregisterClass because need to intercept for reasons related to RegisterClass */ +/* NOTE: NT 4.0+ only */ +HWND +qxeFindWindowEx (HWND arg1, HWND arg2, const Extbyte * arg3, const Extbyte * arg4) +{ + if (XEUNICODE_P) + return FindWindowExW (arg1, arg2, (LPCWSTR) arg3, (LPCWSTR) arg4); + else + return FindWindowExA (arg1, arg2, (LPCSTR) arg3, (LPCSTR) arg4); +} -BOOL -qxeGetClassInfo (HINSTANCE hInstance, const Extbyte * lpClassName, LPWNDCLASSW lpWndClass) +int +qxeGetClassName (HWND hWnd, Extbyte * lpClassName, int nMaxCount) { if (XEUNICODE_P) - return GetClassInfoW (hInstance, (LPCWSTR) lpClassName, lpWndClass); + return GetClassNameW (hWnd, (LPWSTR) lpClassName, nMaxCount); else - return GetClassInfoA (hInstance, (LPCSTR) lpClassName, (LPWNDCLASSA) lpWndClass); + return GetClassNameA (hWnd, (LPSTR) lpClassName, nMaxCount); } -/* Skipping RegisterClassEx because need to intercept so we can provide our own window procedure and handle split notify messages; split-simple WNDCLASSEX; NT 4.0+ only */ +/* Error if SetWindowsHook used: obsolete; two versions, STRICT and non-STRICT */ -/* NOTE: NT 4.0+ only */ -BOOL -qxeGetClassInfoEx (HINSTANCE arg1, const Extbyte * arg2, LPWNDCLASSEXW arg3) +/* Error if SetWindowsHook used: obsolete; two versions, STRICT and non-STRICT */ + +HHOOK +qxeSetWindowsHookEx (int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId) { if (XEUNICODE_P) - return GetClassInfoExW (arg1, (LPCWSTR) arg2, arg3); + return SetWindowsHookExW (idHook, lpfn, hmod, dwThreadId); else - return GetClassInfoExA (arg1, (LPCSTR) arg2, (LPWNDCLASSEXA) arg3); + return SetWindowsHookExA (idHook, lpfn, hmod, dwThreadId); } -HWND -qxeCreateWindowEx (DWORD dwExStyle, const Extbyte * lpClassName, const Extbyte * lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) +HBITMAP +qxeLoadBitmap (HINSTANCE hInstance, const Extbyte * lpBitmapName) { if (XEUNICODE_P) - return CreateWindowExW (dwExStyle, (LPCWSTR) lpClassName, (LPCWSTR) lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + return LoadBitmapW (hInstance, (LPCWSTR) lpBitmapName); else - return CreateWindowExA (dwExStyle, (LPCSTR) lpClassName, (LPCSTR) lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + return LoadBitmapA (hInstance, (LPCSTR) lpBitmapName); } -HWND -qxeCreateDialogParam (HINSTANCE hInstance, const Extbyte * lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +HCURSOR +qxeLoadCursor (HINSTANCE hInstance, const Extbyte * lpCursorName) { if (XEUNICODE_P) - return CreateDialogParamW (hInstance, (LPCWSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); + return LoadCursorW (hInstance, (LPCWSTR) lpCursorName); else - return CreateDialogParamA (hInstance, (LPCSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); + return LoadCursorA (hInstance, (LPCSTR) lpCursorName); } -/* NOTE: error in Cygwin prototype (no split) but fixable with typedef */ -HWND -qxeCreateDialogIndirectParam (HINSTANCE hInstance, LPCDLGTEMPLATEW lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +HCURSOR +qxeLoadCursorFromFile (const Extbyte * lpFileName) { if (XEUNICODE_P) - return CreateDialogIndirectParamW (hInstance, lpTemplate, hWndParent, lpDialogFunc, dwInitParam); + return LoadCursorFromFileW ((LPCWSTR) lpFileName); else - return CreateDialogIndirectParamA (hInstance, (LPCDLGTEMPLATEA) lpTemplate, hWndParent, lpDialogFunc, dwInitParam); + return LoadCursorFromFileA ((LPCSTR) lpFileName); } -int -qxeDialogBoxParam (HINSTANCE hInstance, const Extbyte * lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +HICON +qxeLoadIcon (HINSTANCE hInstance, const Extbyte * lpIconName) { if (XEUNICODE_P) - return DialogBoxParamW (hInstance, (LPCWSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); + return LoadIconW (hInstance, (LPCWSTR) lpIconName); else - return DialogBoxParamA (hInstance, (LPCSTR) lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); + return LoadIconA (hInstance, (LPCSTR) lpIconName); } -/* NOTE: error in Cygwin prototype (no split) but fixable with typedef */ -int -qxeDialogBoxIndirectParam (HINSTANCE hInstance, LPCDLGTEMPLATEW hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +/* NOTE: NT 4.0+ only */ +HANDLE +qxeLoadImage (HINSTANCE arg1, const Extbyte * arg2, UINT arg3, int arg4, int arg5, UINT arg6) { if (XEUNICODE_P) - return DialogBoxIndirectParamW (hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam); + return LoadImageW (arg1, (LPCWSTR) arg2, arg3, arg4, arg5, arg6); else - return DialogBoxIndirectParamA (hInstance, (LPCDLGTEMPLATEA) hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam); + return LoadImageA (arg1, (LPCSTR) arg2, arg3, arg4, arg5, arg6); } -BOOL -qxeSetDlgItemText (HWND hDlg, int nIDDlgItem, const Extbyte * lpString) +int +qxeLoadString (HINSTANCE hInstance, UINT uID, Extbyte * lpBuffer, int nBufferMax) { if (XEUNICODE_P) - return SetDlgItemTextW (hDlg, nIDDlgItem, (LPCWSTR) lpString); + return LoadStringW (hInstance, uID, (LPWSTR) lpBuffer, nBufferMax); else - return SetDlgItemTextA (hDlg, nIDDlgItem, (LPCSTR) lpString); + return LoadStringA (hInstance, uID, (LPSTR) lpBuffer, nBufferMax); } -UINT -qxeGetDlgItemText (HWND hDlg, int nIDDlgItem, Extbyte * lpString, int nMaxCount) +BOOL +qxeIsDialogMessage (HWND hDlg, LPMSG lpMsg) { if (XEUNICODE_P) - return GetDlgItemTextW (hDlg, nIDDlgItem, (LPWSTR) lpString, nMaxCount); + return IsDialogMessageW (hDlg, lpMsg); else - return GetDlgItemTextA (hDlg, nIDDlgItem, (LPSTR) lpString, nMaxCount); + return IsDialogMessageA (hDlg, lpMsg); } -LONG -qxeSendDlgItemMessage (HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) +int +qxeDlgDirList (HWND hDlg, Extbyte * lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType) { if (XEUNICODE_P) - return SendDlgItemMessageW (hDlg, nIDDlgItem, Msg, wParam, lParam); + return DlgDirListW (hDlg, (LPWSTR) lpPathSpec, nIDListBox, nIDStaticPath, uFileType); else - return SendDlgItemMessageA (hDlg, nIDDlgItem, Msg, wParam, lParam); + return DlgDirListA (hDlg, (LPSTR) lpPathSpec, nIDListBox, nIDStaticPath, uFileType); } -/* Error if DefDlgProc used: return value is conditionalized on _MAC, messes up parser */ - -#if !defined (CYGWIN_HEADERS) - BOOL -qxeCallMsgFilter (LPMSG lpMsg, int nCode) +qxeDlgDirSelectEx (HWND hDlg, Extbyte * lpString, int nCount, int nIDListBox) { if (XEUNICODE_P) - return CallMsgFilterW (lpMsg, nCode); + return DlgDirSelectExW (hDlg, (LPWSTR) lpString, nCount, nIDListBox); else - return CallMsgFilterA (lpMsg, nCode); + return DlgDirSelectExA (hDlg, (LPSTR) lpString, nCount, nIDListBox); } -#endif /* !defined (CYGWIN_HEADERS) */ - -UINT -qxeRegisterClipboardFormat (const Extbyte * lpszFormat) +int +qxeDlgDirListComboBox (HWND hDlg, Extbyte * lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype) { if (XEUNICODE_P) - return RegisterClipboardFormatW ((LPCWSTR) lpszFormat); + return DlgDirListComboBoxW (hDlg, (LPWSTR) lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype); else - return RegisterClipboardFormatA ((LPCSTR) lpszFormat); + return DlgDirListComboBoxA (hDlg, (LPSTR) lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype); } -int -qxeGetClipboardFormatName (UINT format, Extbyte * lpszFormatName, int cchMaxCount) +BOOL +qxeDlgDirSelectComboBoxEx (HWND hDlg, Extbyte * lpString, int nCount, int nIDComboBox) { if (XEUNICODE_P) - return GetClipboardFormatNameW (format, (LPWSTR) lpszFormatName, cchMaxCount); + return DlgDirSelectComboBoxExW (hDlg, (LPWSTR) lpString, nCount, nIDComboBox); else - return GetClipboardFormatNameA (format, (LPSTR) lpszFormatName, cchMaxCount); + return DlgDirSelectComboBoxExA (hDlg, (LPSTR) lpString, nCount, nIDComboBox); } -BOOL -qxeCharToOem (const Extbyte * lpszSrc, LPSTR lpszDst) +LRESULT +qxeDefFrameProc (HWND hWnd, HWND hWndMDIClient, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (XEUNICODE_P) - return CharToOemW ((LPCWSTR) lpszSrc, lpszDst); + return DefFrameProcW (hWnd, hWndMDIClient, uMsg, wParam, lParam); else - return CharToOemA ((LPCSTR) lpszSrc, lpszDst); + return DefFrameProcA (hWnd, hWndMDIClient, uMsg, wParam, lParam); } -BOOL -qxeOemToChar (LPCSTR lpszSrc, Extbyte * lpszDst) +/* Error if DefMDIChildProc used: return value is conditionalized on _MAC, messes up parser */ + +HWND +qxeCreateMDIWindow (Extbyte * lpClassName, Extbyte * lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HINSTANCE hInstance, LPARAM lParam) { if (XEUNICODE_P) - return OemToCharW (lpszSrc, (LPWSTR) lpszDst); + return CreateMDIWindowW ((LPWSTR) lpClassName, (LPWSTR) lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hInstance, lParam); else - return OemToCharA (lpszSrc, (LPSTR) lpszDst); + return CreateMDIWindowA ((LPSTR) lpClassName, (LPSTR) lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hInstance, lParam); } BOOL -qxeCharToOemBuff (const Extbyte * lpszSrc, LPSTR lpszDst, DWORD cchDstLength) +qxeWinHelp (HWND hWndMain, const Extbyte * lpszHelp, UINT uCommand, DWORD dwData) { if (XEUNICODE_P) - return CharToOemBuffW ((LPCWSTR) lpszSrc, lpszDst, cchDstLength); + return WinHelpW (hWndMain, (LPCWSTR) lpszHelp, uCommand, dwData); else - return CharToOemBuffA ((LPCSTR) lpszSrc, lpszDst, cchDstLength); + return WinHelpA (hWndMain, (LPCSTR) lpszHelp, uCommand, dwData); } +/* Error if ChangeDisplaySettings used: split-sized LPDEVMODE */ + +/* Error if ChangeDisplaySettingsEx used: split-sized LPDEVMODE; NT 5.0/Win98+ only */ + +/* Error if EnumDisplaySettings used: split-sized LPDEVMODE */ + +/* Error if EnumDisplayDevices used: split-sized PDISPLAY_DEVICE; NT 5.0+ only, no Win98 */ + +/* NOTE: probs w/ICONMETRICS, NONCLIENTMETRICS */ BOOL -qxeOemToCharBuff (LPCSTR lpszSrc, Extbyte * lpszDst, DWORD cchDstLength) +qxeSystemParametersInfo (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni) { if (XEUNICODE_P) - return OemToCharBuffW (lpszSrc, (LPWSTR) lpszDst, cchDstLength); + return SystemParametersInfoW (uiAction, uiParam, pvParam, fWinIni); else - return OemToCharBuffA (lpszSrc, (LPSTR) lpszDst, cchDstLength); + return SystemParametersInfoA (uiAction, uiParam, pvParam, fWinIni); } -Extbyte * -qxeCharUpper (Extbyte * lpsz) +/* Error if GetMonitorInfo used: NT 5.0/Win98+ only */ + +/* Error if GetWindowModuleFileName used: NT 5.0+ only */ + +/* Error if RealGetWindowClass used: NT 5.0+ only */ + +/* Error if GetAltTabInfo used: NT 5.0+ only */ + + +/*----------------------------------------------------------------------*/ +/* Processing file DDEML.H */ +/*----------------------------------------------------------------------*/ + +UINT +qxeDdeInitialize (LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes) { if (XEUNICODE_P) - return (Extbyte *) CharUpperW ((LPWSTR) lpsz); + return DdeInitializeW (pidInst, pfnCallback, afCmd, ulRes); else - return (Extbyte *) CharUpperA ((LPSTR) lpsz); + return DdeInitializeA (pidInst, pfnCallback, afCmd, ulRes); } +/* Skipping DdeCreateStringHandle because error in Cygwin prototype */ + DWORD -qxeCharUpperBuff (Extbyte * lpsz, DWORD cchLength) +qxeDdeQueryString (DWORD idInst, HSZ hsz, Extbyte * psz, DWORD cchMax, int iCodePage) { if (XEUNICODE_P) - return CharUpperBuffW ((LPWSTR) lpsz, cchLength); + return DdeQueryStringW (idInst, hsz, (LPWSTR) psz, cchMax, iCodePage); else - return CharUpperBuffA ((LPSTR) lpsz, cchLength); + return DdeQueryStringA (idInst, hsz, (LPSTR) psz, cchMax, iCodePage); } -Extbyte * -qxeCharLower (Extbyte * lpsz) + +/*----------------------------------------------------------------------*/ +/* Processing file WINREG.H */ +/*----------------------------------------------------------------------*/ + +/* Skipping RegConnectRegistry because error in Cygwin prototype */ + +LONG + +qxeRegCreateKey (HKEY hKey, const Extbyte * lpSubKey, PHKEY phkResult) { if (XEUNICODE_P) - return (Extbyte *) CharLowerW ((LPWSTR) lpsz); + return RegCreateKeyW (hKey, (LPCWSTR) lpSubKey, phkResult); else - return (Extbyte *) CharLowerA ((LPSTR) lpsz); + return RegCreateKeyA (hKey, (LPCSTR) lpSubKey, phkResult); } -DWORD -qxeCharLowerBuff (Extbyte * lpsz, DWORD cchLength) +LONG + +qxeRegCreateKeyEx (HKEY hKey, const Extbyte * lpSubKey, DWORD Reserved, Extbyte * lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition) { if (XEUNICODE_P) - return CharLowerBuffW ((LPWSTR) lpsz, cchLength); + return RegCreateKeyExW (hKey, (LPCWSTR) lpSubKey, Reserved, (LPWSTR) lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); else - return CharLowerBuffA ((LPSTR) lpsz, cchLength); + return RegCreateKeyExA (hKey, (LPCSTR) lpSubKey, Reserved, (LPSTR) lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); } -Extbyte * -qxeCharNext (const Extbyte * lpsz) +LONG + +qxeRegDeleteKey (HKEY hKey, const Extbyte * lpSubKey) { if (XEUNICODE_P) - return (Extbyte *) CharNextW ((LPCWSTR) lpsz); + return RegDeleteKeyW (hKey, (LPCWSTR) lpSubKey); else - return (Extbyte *) CharNextA ((LPCSTR) lpsz); + return RegDeleteKeyA (hKey, (LPCSTR) lpSubKey); } -Extbyte * -qxeCharPrev (const Extbyte * lpszStart, const Extbyte * lpszCurrent) +LONG + +qxeRegDeleteValue (HKEY hKey, const Extbyte * lpValueName) { if (XEUNICODE_P) - return (Extbyte *) CharPrevW ((LPCWSTR) lpszStart, (LPCWSTR) lpszCurrent); + return RegDeleteValueW (hKey, (LPCWSTR) lpValueName); else - return (Extbyte *) CharPrevA ((LPCSTR) lpszStart, (LPCSTR) lpszCurrent); + return RegDeleteValueA (hKey, (LPCSTR) lpValueName); } -/* Error if IsCharAlpha used: split CHAR */ - -/* Error if IsCharAlphaNumeric used: split CHAR */ +LONG -/* Error if IsCharUpper used: split CHAR */ +qxeRegEnumKey (HKEY hKey, DWORD dwIndex, Extbyte * lpName, DWORD cbName) +{ + if (XEUNICODE_P) + return RegEnumKeyW (hKey, dwIndex, (LPWSTR) lpName, cbName); + else + return RegEnumKeyA (hKey, dwIndex, (LPSTR) lpName, cbName); +} -/* Error if IsCharLower used: split CHAR */ +LONG -int -qxeGetKeyNameText (LONG lParam, Extbyte * lpString, int nSize) +qxeRegEnumKeyEx (HKEY hKey, DWORD dwIndex, Extbyte * lpName, LPDWORD lpcbName, LPDWORD lpReserved, Extbyte * lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime) { if (XEUNICODE_P) - return GetKeyNameTextW (lParam, (LPWSTR) lpString, nSize); + return RegEnumKeyExW (hKey, dwIndex, (LPWSTR) lpName, lpcbName, lpReserved, (LPWSTR) lpClass, lpcbClass, lpftLastWriteTime); else - return GetKeyNameTextA (lParam, (LPSTR) lpString, nSize); + return RegEnumKeyExA (hKey, dwIndex, (LPSTR) lpName, lpcbName, lpReserved, (LPSTR) lpClass, lpcbClass, lpftLastWriteTime); } -/* Skipping VkKeyScan because split CHAR */ - -/* Error if VkKeyScanEx used: split CHAR; NT 4.0+ only */ +LONG -UINT -qxeMapVirtualKey (UINT uCode, UINT uMapType) +qxeRegEnumValue (HKEY hKey, DWORD dwIndex, Extbyte * lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) { if (XEUNICODE_P) - return MapVirtualKeyW (uCode, uMapType); + return RegEnumValueW (hKey, dwIndex, (LPWSTR) lpValueName, lpcbValueName, lpReserved, lpType, lpData, lpcbData); else - return MapVirtualKeyA (uCode, uMapType); + return RegEnumValueA (hKey, dwIndex, (LPSTR) lpValueName, lpcbValueName, lpReserved, lpType, lpData, lpcbData); } -/* NOTE: NT 4.0+ only */ -UINT -qxeMapVirtualKeyEx (UINT uCode, UINT uMapType, HKL dwhkl) +LONG + +qxeRegLoadKey (HKEY hKey, const Extbyte * lpSubKey, const Extbyte * lpFile) { if (XEUNICODE_P) - return MapVirtualKeyExW (uCode, uMapType, dwhkl); + return RegLoadKeyW (hKey, (LPCWSTR) lpSubKey, (LPCWSTR) lpFile); else - return MapVirtualKeyExA (uCode, uMapType, dwhkl); + return RegLoadKeyA (hKey, (LPCSTR) lpSubKey, (LPCSTR) lpFile); } -HACCEL -qxeLoadAccelerators (HINSTANCE hInstance, const Extbyte * lpTableName) +LONG + +qxeRegOpenKey (HKEY hKey, const Extbyte * lpSubKey, PHKEY phkResult) { if (XEUNICODE_P) - return LoadAcceleratorsW (hInstance, (LPCWSTR) lpTableName); + return RegOpenKeyW (hKey, (LPCWSTR) lpSubKey, phkResult); else - return LoadAcceleratorsA (hInstance, (LPCSTR) lpTableName); + return RegOpenKeyA (hKey, (LPCSTR) lpSubKey, phkResult); } -HACCEL -qxeCreateAcceleratorTable (LPACCEL arg1, int arg2) +LONG + +qxeRegOpenKeyEx (HKEY hKey, const Extbyte * lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) { if (XEUNICODE_P) - return CreateAcceleratorTableW (arg1, arg2); + return RegOpenKeyExW (hKey, (LPCWSTR) lpSubKey, ulOptions, samDesired, phkResult); else - return CreateAcceleratorTableA (arg1, arg2); + return RegOpenKeyExA (hKey, (LPCSTR) lpSubKey, ulOptions, samDesired, phkResult); } -int -qxeCopyAcceleratorTable (HACCEL hAccelSrc, LPACCEL lpAccelDst, int cAccelEntries) +LONG + +qxeRegQueryInfoKey (HKEY hKey, Extbyte * lpClass, LPDWORD lpcbClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen, LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime) { if (XEUNICODE_P) - return CopyAcceleratorTableW (hAccelSrc, lpAccelDst, cAccelEntries); + return RegQueryInfoKeyW (hKey, (LPWSTR) lpClass, lpcbClass, lpReserved, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime); else - return CopyAcceleratorTableA (hAccelSrc, lpAccelDst, cAccelEntries); + return RegQueryInfoKeyA (hKey, (LPSTR) lpClass, lpcbClass, lpReserved, lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime); } -int -qxeTranslateAccelerator (HWND hWnd, HACCEL hAccTable, LPMSG lpMsg) +LONG + +qxeRegQueryValue (HKEY hKey, const Extbyte * lpSubKey, Extbyte * lpValue, PLONG lpcbValue) { if (XEUNICODE_P) - return TranslateAcceleratorW (hWnd, hAccTable, lpMsg); + return RegQueryValueW (hKey, (LPCWSTR) lpSubKey, (LPWSTR) lpValue, lpcbValue); else - return TranslateAcceleratorA (hWnd, hAccTable, lpMsg); + return RegQueryValueA (hKey, (LPCSTR) lpSubKey, (LPSTR) lpValue, lpcbValue); } -HMENU -qxeLoadMenu (HINSTANCE hInstance, const Extbyte * lpMenuName) +LONG + +qxeRegQueryMultipleValues (HKEY hKey, PVALENTW val_list, DWORD num_vals, Extbyte * lpValueBuf, LPDWORD ldwTotsize) { if (XEUNICODE_P) - return LoadMenuW (hInstance, (LPCWSTR) lpMenuName); + return RegQueryMultipleValuesW (hKey, val_list, num_vals, (LPWSTR) lpValueBuf, ldwTotsize); else - return LoadMenuA (hInstance, (LPCSTR) lpMenuName); + return RegQueryMultipleValuesA (hKey, (PVALENTA) val_list, num_vals, (LPSTR) lpValueBuf, ldwTotsize); } -HMENU -qxeLoadMenuIndirect (CONST MENUTEMPLATEW * lpMenuTemplate) +LONG + +qxeRegQueryValueEx (HKEY hKey, const Extbyte * lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) { if (XEUNICODE_P) - return LoadMenuIndirectW (lpMenuTemplate); + return RegQueryValueExW (hKey, (LPCWSTR) lpValueName, lpReserved, lpType, lpData, lpcbData); else - return LoadMenuIndirectA ((CONST MENUTEMPLATEA *) lpMenuTemplate); + return RegQueryValueExA (hKey, (LPCSTR) lpValueName, lpReserved, lpType, lpData, lpcbData); } -BOOL -qxeChangeMenu (HMENU hMenu, UINT cmd, const Extbyte * lpszNewItem, UINT cmdInsert, UINT flags) +LONG + +qxeRegReplaceKey (HKEY hKey, const Extbyte * lpSubKey, const Extbyte * lpNewFile, const Extbyte * lpOldFile) { if (XEUNICODE_P) - return ChangeMenuW (hMenu, cmd, (LPCWSTR) lpszNewItem, cmdInsert, flags); + return RegReplaceKeyW (hKey, (LPCWSTR) lpSubKey, (LPCWSTR) lpNewFile, (LPCWSTR) lpOldFile); else - return ChangeMenuA (hMenu, cmd, (LPCSTR) lpszNewItem, cmdInsert, flags); + return RegReplaceKeyA (hKey, (LPCSTR) lpSubKey, (LPCSTR) lpNewFile, (LPCSTR) lpOldFile); } -int -qxeGetMenuString (HMENU hMenu, UINT uIDItem, Extbyte * lpString, int nMaxCount, UINT uFlag) +LONG + +qxeRegRestoreKey (HKEY hKey, const Extbyte * lpFile, DWORD dwFlags) { if (XEUNICODE_P) - return GetMenuStringW (hMenu, uIDItem, (LPWSTR) lpString, nMaxCount, uFlag); + return RegRestoreKeyW (hKey, (LPCWSTR) lpFile, dwFlags); else - return GetMenuStringA (hMenu, uIDItem, (LPSTR) lpString, nMaxCount, uFlag); + return RegRestoreKeyA (hKey, (LPCSTR) lpFile, dwFlags); } -BOOL -qxeInsertMenu (HMENU hMenu, UINT uPosition, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem) +LONG + +qxeRegSaveKey (HKEY hKey, const Extbyte * lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { if (XEUNICODE_P) - return InsertMenuW (hMenu, uPosition, uFlags, uIDNewItem, (LPCWSTR) lpNewItem); + return RegSaveKeyW (hKey, (LPCWSTR) lpFile, lpSecurityAttributes); else - return InsertMenuA (hMenu, uPosition, uFlags, uIDNewItem, (LPCSTR) lpNewItem); + return RegSaveKeyA (hKey, (LPCSTR) lpFile, lpSecurityAttributes); } -BOOL -qxeAppendMenu (HMENU hMenu, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem) +LONG + +qxeRegSetValue (HKEY hKey, const Extbyte * lpSubKey, DWORD dwType, const Extbyte * lpData, DWORD cbData) { if (XEUNICODE_P) - return AppendMenuW (hMenu, uFlags, uIDNewItem, (LPCWSTR) lpNewItem); + return RegSetValueW (hKey, (LPCWSTR) lpSubKey, dwType, (LPCWSTR) lpData, cbData); else - return AppendMenuA (hMenu, uFlags, uIDNewItem, (LPCSTR) lpNewItem); + return RegSetValueA (hKey, (LPCSTR) lpSubKey, dwType, (LPCSTR) lpData, cbData); } -BOOL -qxeModifyMenu (HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem) +LONG + +qxeRegSetValueEx (HKEY hKey, const Extbyte * lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData) { if (XEUNICODE_P) - return ModifyMenuW (hMnu, uPosition, uFlags, uIDNewItem, (LPCWSTR) lpNewItem); + return RegSetValueExW (hKey, (LPCWSTR) lpValueName, Reserved, dwType, lpData, cbData); else - return ModifyMenuA (hMnu, uPosition, uFlags, uIDNewItem, (LPCSTR) lpNewItem); + return RegSetValueExA (hKey, (LPCSTR) lpValueName, Reserved, dwType, lpData, cbData); } -/* NOTE: NT 4.0+ only */ -BOOL -qxeInsertMenuItem (HMENU arg1, UINT arg2, BOOL arg3, LPCMENUITEMINFOW arg4) +LONG + +qxeRegUnLoadKey (HKEY hKey, const Extbyte * lpSubKey) { if (XEUNICODE_P) - return InsertMenuItemW (arg1, arg2, arg3, arg4); + return RegUnLoadKeyW (hKey, (LPCWSTR) lpSubKey); else - return InsertMenuItemA (arg1, arg2, arg3, (LPCMENUITEMINFOA) arg4); + return RegUnLoadKeyA (hKey, (LPCSTR) lpSubKey); } -/* NOTE: NT 4.0+ only */ BOOL -qxeGetMenuItemInfo (HMENU arg1, UINT arg2, BOOL arg3, LPMENUITEMINFOW arg4) + +qxeInitiateSystemShutdown (Extbyte * lpMachineName, Extbyte * lpMessage, DWORD dwTimeout, BOOL bForceAppsClosed, BOOL bRebootAfterShutdown) { if (XEUNICODE_P) - return GetMenuItemInfoW (arg1, arg2, arg3, arg4); + return InitiateSystemShutdownW ((LPWSTR) lpMachineName, (LPWSTR) lpMessage, dwTimeout, bForceAppsClosed, bRebootAfterShutdown); else - return GetMenuItemInfoA (arg1, arg2, arg3, (LPMENUITEMINFOA) arg4); + return InitiateSystemShutdownA ((LPSTR) lpMachineName, (LPSTR) lpMessage, dwTimeout, bForceAppsClosed, bRebootAfterShutdown); } -/* NOTE: NT 4.0+ only */ BOOL -qxeSetMenuItemInfo (HMENU arg1, UINT arg2, BOOL arg3, LPCMENUITEMINFOW arg4) + +qxeAbortSystemShutdown (Extbyte * lpMachineName) { if (XEUNICODE_P) - return SetMenuItemInfoW (arg1, arg2, arg3, arg4); + return AbortSystemShutdownW ((LPWSTR) lpMachineName); else - return SetMenuItemInfoA (arg1, arg2, arg3, (LPCMENUITEMINFOA) arg4); + return AbortSystemShutdownA ((LPSTR) lpMachineName); } + +/*----------------------------------------------------------------------*/ +/* Processing file WINNLS.H */ +/*----------------------------------------------------------------------*/ + +/* Error if GetCPInfoEx used: not used, not examined yet */ + +/* Error if CompareString used: not used, not examined yet */ + +/* Error if LCMapString used: not used, not examined yet */ + int -qxeDrawText (HDC hDC, const Extbyte * lpString, int nCount, LPRECT lpRect, UINT uFormat) +qxeGetLocaleInfo (LCID Locale, LCTYPE LCType, Extbyte * lpLCData, int cchData) { if (XEUNICODE_P) - return DrawTextW (hDC, (LPCWSTR) lpString, nCount, lpRect, uFormat); + return GetLocaleInfoW (Locale, LCType, (LPWSTR) lpLCData, cchData); else - return DrawTextA (hDC, (LPCSTR) lpString, nCount, lpRect, uFormat); + return GetLocaleInfoA (Locale, LCType, (LPSTR) lpLCData, cchData); } -/* NOTE: NT 4.0+ only */ -int -qxeDrawTextEx (HDC arg1, Extbyte * arg2, int arg3, LPRECT arg4, UINT arg5, LPDRAWTEXTPARAMS arg6) +BOOL +qxeSetLocaleInfo (LCID Locale, LCTYPE LCType, const Extbyte * lpLCData) { if (XEUNICODE_P) - return DrawTextExW (arg1, (LPWSTR) arg2, arg3, arg4, arg5, arg6); + return SetLocaleInfoW (Locale, LCType, (LPCWSTR) lpLCData); else - return DrawTextExA (arg1, (LPSTR) arg2, arg3, arg4, arg5, arg6); + return SetLocaleInfoA (Locale, LCType, (LPCSTR) lpLCData); } -BOOL -qxeGrayString (HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int X, int Y, int nWidth, int nHeight) +/* Error if GetTimeFormat used: not used, not examined yet */ + +/* Error if GetDateFormat used: not used, not examined yet */ + +/* Error if GetNumberFormat used: not used, not examined yet */ + +/* Error if GetCurrencyFormat used: not used, not examined yet */ + +/* Error if EnumCalendarInfo used: not used, not examined yet */ + +/* Error if EnumCalendarInfoEx used: not used, not examined yet */ + +/* Error if EnumTimeFormats used: not used, not examined yet */ + +/* Error if EnumDateFormats used: not used, not examined yet */ + +/* Error if EnumDateFormatsEx used: not used, not examined yet */ + +/* Error if GetStringTypeEx used: not used, not examined yet */ + +/* Error if GetStringType used: no such fun; A and W versions have different nos. of args */ + +/* Error if FoldString used: not used, not examined yet */ + +/* Error if EnumSystemLocales used: not used, not examined yet */ + +/* Error if EnumSystemCodePages used: not used, not examined yet */ + + +/*----------------------------------------------------------------------*/ +/* Processing file IME.H */ +/*----------------------------------------------------------------------*/ + +/* Error if SendIMEMessageEx used: obsolete, no docs available */ + + +/*----------------------------------------------------------------------*/ +/* Processing file WINGDI.H */ +/*----------------------------------------------------------------------*/ + +int +qxeAddFontResource (const Extbyte * arg1) { if (XEUNICODE_P) - return GrayStringW (hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight); + return AddFontResourceW ((LPCWSTR) arg1); else - return GrayStringA (hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight); + return AddFontResourceA ((LPCSTR) arg1); } -/* NOTE: NT 4.0+ only */ -BOOL -qxeDrawState (HDC arg1, HBRUSH arg2, DRAWSTATEPROC arg3, LPARAM arg4, WPARAM arg5, int arg6, int arg7, int arg8, int arg9, UINT arg10) +HMETAFILE +qxeCopyMetaFile (HMETAFILE arg1, const Extbyte * arg2) { if (XEUNICODE_P) - return DrawStateW (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + return CopyMetaFileW (arg1, (LPCWSTR) arg2); else - return DrawStateA (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + return CopyMetaFileA (arg1, (LPCSTR) arg2); } -LONG -qxeTabbedTextOut (HDC hDC, int X, int Y, const Extbyte * lpString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin) +/* Skipping CreateDC because split-sized DEVMODE */ + +/* Skipping CreateFontIndirect because split-sized LOGFONT */ + +HFONT +qxeCreateFont (int arg1, int arg2, int arg3, int arg4, int arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD arg10, DWORD arg11, DWORD arg12, DWORD arg13, const Extbyte * arg14) { if (XEUNICODE_P) - return TabbedTextOutW (hDC, X, Y, (LPCWSTR) lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); + return CreateFontW (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, (LPCWSTR) arg14); else - return TabbedTextOutA (hDC, X, Y, (LPCSTR) lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); + return CreateFontA (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, (LPCSTR) arg14); } -DWORD -qxeGetTabbedTextExtent (HDC hDC, const Extbyte * lpString, int nCount, int nTabPositions, LPINT lpnTabStopPositions) +/* Skipping CreateIC because split-sized DEVMODE */ + +HDC +qxeCreateMetaFile (const Extbyte * arg1) { if (XEUNICODE_P) - return GetTabbedTextExtentW (hDC, (LPCWSTR) lpString, nCount, nTabPositions, lpnTabStopPositions); + return CreateMetaFileW ((LPCWSTR) arg1); else - return GetTabbedTextExtentA (hDC, (LPCSTR) lpString, nCount, nTabPositions, lpnTabStopPositions); + return CreateMetaFileA ((LPCSTR) arg1); } BOOL -qxeSetProp (HWND hWnd, const Extbyte * lpString, HANDLE hData) +qxeCreateScalableFontResource (DWORD arg1, const Extbyte * arg2, const Extbyte * arg3, const Extbyte * arg4) { if (XEUNICODE_P) - return SetPropW (hWnd, (LPCWSTR) lpString, hData); + return CreateScalableFontResourceW (arg1, (LPCWSTR) arg2, (LPCWSTR) arg3, (LPCWSTR) arg4); else - return SetPropA (hWnd, (LPCSTR) lpString, hData); + return CreateScalableFontResourceA (arg1, (LPCSTR) arg2, (LPCSTR) arg3, (LPCSTR) arg4); } -HANDLE -qxeGetProp (HWND hWnd, const Extbyte * lpString) +/* Skipping DeviceCapabilities because split-sized DEVMODE */ + +/* Skipping EnumFontFamiliesEx because split-complex FONTENUMPROC; NT 4.0+ only */ + +/* Error if EnumFontFamilies used: split-complex FONTENUMPROC */ + +/* Error if EnumFonts used: split-complex FONTENUMPROC */ + +BOOL +qxeGetCharWidth (HDC arg1, UINT arg2, UINT arg3, LPINT arg4) { if (XEUNICODE_P) - return GetPropW (hWnd, (LPCWSTR) lpString); + return GetCharWidthW (arg1, arg2, arg3, arg4); else - return GetPropA (hWnd, (LPCSTR) lpString); + return GetCharWidthA (arg1, arg2, arg3, arg4); } -HANDLE -qxeRemoveProp (HWND hWnd, const Extbyte * lpString) +BOOL +qxeGetCharWidth32 (HDC arg1, UINT arg2, UINT arg3, LPINT arg4) { if (XEUNICODE_P) - return RemovePropW (hWnd, (LPCWSTR) lpString); + return GetCharWidth32W (arg1, arg2, arg3, arg4); else - return RemovePropA (hWnd, (LPCSTR) lpString); + return GetCharWidth32A (arg1, arg2, arg3, arg4); } -/* NOTE: // callback fun differs only in string pointer type */ -int -qxeEnumPropsEx (HWND hWnd, PROPENUMPROCEXW lpEnumFunc, LPARAM lParam) +BOOL +qxeGetCharWidthFloat (HDC arg1, UINT arg2, UINT arg3, PFLOAT arg4) { if (XEUNICODE_P) - return EnumPropsExW (hWnd, lpEnumFunc, lParam); + return GetCharWidthFloatW (arg1, arg2, arg3, arg4); else - return EnumPropsExA (hWnd, (PROPENUMPROCEXA) lpEnumFunc, lParam); + return GetCharWidthFloatA (arg1, arg2, arg3, arg4); } -/* NOTE: // callback fun differs only in string pointer type */ -int -qxeEnumProps (HWND hWnd, PROPENUMPROCW lpEnumFunc) +BOOL +qxeGetCharABCWidths (HDC arg1, UINT arg2, UINT arg3, LPABC arg4) { if (XEUNICODE_P) - return EnumPropsW (hWnd, lpEnumFunc); + return GetCharABCWidthsW (arg1, arg2, arg3, arg4); else - return EnumPropsA (hWnd, (PROPENUMPROCA) lpEnumFunc); + return GetCharABCWidthsA (arg1, arg2, arg3, arg4); } -BOOL -qxeSetWindowText (HWND hWnd, const Extbyte * lpString) +BOOL +qxeGetCharABCWidthsFloat (HDC arg1, UINT arg2, UINT arg3, LPABCFLOAT arg4) { if (XEUNICODE_P) - return SetWindowTextW (hWnd, (LPCWSTR) lpString); + return GetCharABCWidthsFloatW (arg1, arg2, arg3, arg4); else - return SetWindowTextA (hWnd, (LPCSTR) lpString); + return GetCharABCWidthsFloatA (arg1, arg2, arg3, arg4); } -int -qxeGetWindowText (HWND hWnd, Extbyte * lpString, int nMaxCount) +DWORD +qxeGetGlyphOutline (HDC arg1, UINT arg2, UINT arg3, LPGLYPHMETRICS arg4, DWORD arg5, LPVOID arg6, CONST MAT2 * arg7) { if (XEUNICODE_P) - return GetWindowTextW (hWnd, (LPWSTR) lpString, nMaxCount); + return GetGlyphOutlineW (arg1, arg2, arg3, arg4, arg5, arg6, arg7); else - return GetWindowTextA (hWnd, (LPSTR) lpString, nMaxCount); + return GetGlyphOutlineA (arg1, arg2, arg3, arg4, arg5, arg6, arg7); } -int -qxeGetWindowTextLength (HWND hWnd) +HMETAFILE +qxeGetMetaFile (const Extbyte * arg1) { if (XEUNICODE_P) - return GetWindowTextLengthW (hWnd); + return GetMetaFileW ((LPCWSTR) arg1); else - return GetWindowTextLengthA (hWnd); + return GetMetaFileA ((LPCSTR) arg1); } -int -qxeMessageBox (HWND hWnd, const Extbyte * lpText, const Extbyte * lpCaption, UINT uType) +/* Error if GetOutlineTextMetrics used: split-sized LPOUTLINETEXTMETRIC */ + +BOOL +qxeGetTextExtentPoint (HDC arg1, const Extbyte * arg2, int arg3, LPSIZE arg4) { if (XEUNICODE_P) - return MessageBoxW (hWnd, (LPCWSTR) lpText, (LPCWSTR) lpCaption, uType); + return GetTextExtentPointW (arg1, (LPCWSTR) arg2, arg3, arg4); else - return MessageBoxA (hWnd, (LPCSTR) lpText, (LPCSTR) lpCaption, uType); + return GetTextExtentPointA (arg1, (LPCSTR) arg2, arg3, arg4); } -int -qxeMessageBoxEx (HWND hWnd, const Extbyte * lpText, const Extbyte * lpCaption, UINT uType, WORD wLanguageId) +BOOL +qxeGetTextExtentPoint32 (HDC arg1, const Extbyte * arg2, int arg3, LPSIZE arg4) { if (XEUNICODE_P) - return MessageBoxExW (hWnd, (LPCWSTR) lpText, (LPCWSTR) lpCaption, uType, wLanguageId); + return GetTextExtentPoint32W (arg1, (LPCWSTR) arg2, arg3, arg4); else - return MessageBoxExA (hWnd, (LPCSTR) lpText, (LPCSTR) lpCaption, uType, wLanguageId); + return GetTextExtentPoint32A (arg1, (LPCSTR) arg2, arg3, arg4); } -/* NOTE: NT 4.0+ only */ -int -qxeMessageBoxIndirect (LPMSGBOXPARAMSW arg1) +BOOL +qxeGetTextExtentExPoint (HDC arg1, const Extbyte * arg2, int arg3, int arg4, LPINT arg5, LPINT arg6, LPSIZE arg7) { if (XEUNICODE_P) - return MessageBoxIndirectW (arg1); + return GetTextExtentExPointW (arg1, (LPCWSTR) arg2, arg3, arg4, arg5, arg6, arg7); else - return MessageBoxIndirectA ((LPMSGBOXPARAMSA) arg1); + return GetTextExtentExPointA (arg1, (LPCSTR) arg2, arg3, arg4, arg5, arg6, arg7); } -LONG -qxeGetWindowLong (HWND hWnd, int nIndex) +/* NOTE: NT 4.0+ only */ +DWORD +qxeGetCharacterPlacement (HDC arg1, const Extbyte * arg2, int arg3, int arg4, LPGCP_RESULTSW arg5, DWORD arg6) { if (XEUNICODE_P) - return GetWindowLongW (hWnd, nIndex); + return GetCharacterPlacementW (arg1, (LPCWSTR) arg2, arg3, arg4, arg5, arg6); else - return GetWindowLongA (hWnd, nIndex); + return GetCharacterPlacementA (arg1, (LPCSTR) arg2, arg3, arg4, (LPGCP_RESULTSA) arg5, arg6); } -LONG -qxeSetWindowLong (HWND hWnd, int nIndex, LONG dwNewLong) +/* Error if GetGlyphIndices used: NT 5.0+ only */ + +/* Error if AddFontResourceEx used: NT 5.0+ only */ + +/* Error if RemoveFontResourceEx used: NT 5.0+ only */ + +/* Error if CreateFontIndirectEx used: split-sized ENUMLOGFONTEXDV; NT 5.0+ only */ + +/* Skipping ResetDC because split-sized DEVMODE */ + +BOOL +qxeRemoveFontResource (const Extbyte * arg1) { if (XEUNICODE_P) - return SetWindowLongW (hWnd, nIndex, dwNewLong); + return RemoveFontResourceW ((LPCWSTR) arg1); else - return SetWindowLongA (hWnd, nIndex, dwNewLong); + return RemoveFontResourceA ((LPCSTR) arg1); } -DWORD -qxeGetClassLong (HWND hWnd, int nIndex) +HENHMETAFILE +qxeCopyEnhMetaFile (HENHMETAFILE arg1, const Extbyte * arg2) { if (XEUNICODE_P) - return GetClassLongW (hWnd, nIndex); + return CopyEnhMetaFileW (arg1, (LPCWSTR) arg2); else - return GetClassLongA (hWnd, nIndex); + return CopyEnhMetaFileA (arg1, (LPCSTR) arg2); } -DWORD -qxeSetClassLong (HWND hWnd, int nIndex, LONG dwNewLong) +HDC +qxeCreateEnhMetaFile (HDC arg1, const Extbyte * arg2, CONST RECT * arg3, const Extbyte * arg4) { if (XEUNICODE_P) - return SetClassLongW (hWnd, nIndex, dwNewLong); + return CreateEnhMetaFileW (arg1, (LPCWSTR) arg2, arg3, (LPCWSTR) arg4); else - return SetClassLongA (hWnd, nIndex, dwNewLong); + return CreateEnhMetaFileA (arg1, (LPCSTR) arg2, arg3, (LPCSTR) arg4); } -HWND -qxeFindWindow (const Extbyte * lpClassName, const Extbyte * lpWindowName) +HENHMETAFILE +qxeGetEnhMetaFile (const Extbyte * arg1) { if (XEUNICODE_P) - return FindWindowW ((LPCWSTR) lpClassName, (LPCWSTR) lpWindowName); + return GetEnhMetaFileW ((LPCWSTR) arg1); else - return FindWindowA ((LPCSTR) lpClassName, (LPCSTR) lpWindowName); + return GetEnhMetaFileA ((LPCSTR) arg1); } -/* NOTE: NT 4.0+ only */ -HWND -qxeFindWindowEx (HWND arg1, HWND arg2, const Extbyte * arg3, const Extbyte * arg4) +UINT +qxeGetEnhMetaFileDescription (HENHMETAFILE arg1, UINT arg2, Extbyte * arg3) { if (XEUNICODE_P) - return FindWindowExW (arg1, arg2, (LPCWSTR) arg3, (LPCWSTR) arg4); + return GetEnhMetaFileDescriptionW (arg1, arg2, (LPWSTR) arg3); else - return FindWindowExA (arg1, arg2, (LPCSTR) arg3, (LPCSTR) arg4); + return GetEnhMetaFileDescriptionA (arg1, arg2, (LPSTR) arg3); } +/* Skipping GetTextMetrics because split-sized LPTEXTMETRIC */ + int -qxeGetClassName (HWND hWnd, Extbyte * lpClassName, int nMaxCount) +qxeStartDoc (HDC arg1, CONST DOCINFOW * arg2) { if (XEUNICODE_P) - return GetClassNameW (hWnd, (LPWSTR) lpClassName, nMaxCount); + return StartDocW (arg1, arg2); else - return GetClassNameA (hWnd, (LPSTR) lpClassName, nMaxCount); + return StartDocA (arg1, (CONST DOCINFOA *) arg2); } -/* Error if SetWindowsHook used: obsolete; two versions, STRICT and non-STRICT */ - -/* Error if SetWindowsHook used: obsolete; two versions, STRICT and non-STRICT */ +/* Skipping GetObject because split-sized LOGFONT */ -HHOOK -qxeSetWindowsHookEx (int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId) +BOOL +qxeTextOut (HDC arg1, int arg2, int arg3, const Extbyte * arg4, int arg5) { if (XEUNICODE_P) - return SetWindowsHookExW (idHook, lpfn, hmod, dwThreadId); + return TextOutW (arg1, arg2, arg3, (LPCWSTR) arg4, arg5); else - return SetWindowsHookExA (idHook, lpfn, hmod, dwThreadId); + return TextOutA (arg1, arg2, arg3, (LPCSTR) arg4, arg5); } -HBITMAP -qxeLoadBitmap (HINSTANCE hInstance, const Extbyte * lpBitmapName) +BOOL +qxeExtTextOut (HDC arg1, int arg2, int arg3, UINT arg4, CONST RECT * arg5, const Extbyte * arg6, UINT arg7, CONST INT * arg8) { if (XEUNICODE_P) - return LoadBitmapW (hInstance, (LPCWSTR) lpBitmapName); + return ExtTextOutW (arg1, arg2, arg3, arg4, arg5, (LPCWSTR) arg6, arg7, arg8); else - return LoadBitmapA (hInstance, (LPCSTR) lpBitmapName); + return ExtTextOutA (arg1, arg2, arg3, arg4, arg5, (LPCSTR) arg6, arg7, arg8); } -HCURSOR -qxeLoadCursor (HINSTANCE hInstance, const Extbyte * lpCursorName) +BOOL +qxePolyTextOut (HDC arg1, CONST POLYTEXTW * arg2, int arg3) { if (XEUNICODE_P) - return LoadCursorW (hInstance, (LPCWSTR) lpCursorName); + return PolyTextOutW (arg1, arg2, arg3); else - return LoadCursorA (hInstance, (LPCSTR) lpCursorName); + return PolyTextOutA (arg1, (CONST POLYTEXTA *) arg2, arg3); } -HCURSOR -qxeLoadCursorFromFile (const Extbyte * lpFileName) +int +qxeGetTextFace (HDC arg1, int arg2, Extbyte * arg3) { if (XEUNICODE_P) - return LoadCursorFromFileW ((LPCWSTR) lpFileName); + return GetTextFaceW (arg1, arg2, (LPWSTR) arg3); else - return LoadCursorFromFileA ((LPCSTR) lpFileName); + return GetTextFaceA (arg1, arg2, (LPSTR) arg3); } -HICON -qxeLoadIcon (HINSTANCE hInstance, const Extbyte * lpIconName) +DWORD +qxeGetKerningPairs (HDC arg1, DWORD arg2, LPKERNINGPAIR arg3) { if (XEUNICODE_P) - return LoadIconW (hInstance, (LPCWSTR) lpIconName); + return GetKerningPairsW (arg1, arg2, arg3); else - return LoadIconA (hInstance, (LPCSTR) lpIconName); + return GetKerningPairsA (arg1, arg2, arg3); } +/* Error if GetLogColorSpace used: split-sized LPLOGCOLORSPACE; NT 4.0+ only */ + +/* Error if CreateColorSpace used: split-sized LPLOGCOLORSPACE; NT 4.0+ only */ + +/* Skipping GetICMProfile because NT 4.0+ only, error in Cygwin prototype */ + /* NOTE: NT 4.0+ only */ -HANDLE -qxeLoadImage (HINSTANCE arg1, const Extbyte * arg2, UINT arg3, int arg4, int arg5, UINT arg6) +BOOL +qxeSetICMProfile (HDC arg1, Extbyte * arg2) { if (XEUNICODE_P) - return LoadImageW (arg1, (LPCWSTR) arg2, arg3, arg4, arg5, arg6); + return SetICMProfileW (arg1, (LPWSTR) arg2); else - return LoadImageA (arg1, (LPCSTR) arg2, arg3, arg4, arg5, arg6); + return SetICMProfileA (arg1, (LPSTR) arg2); } +/* NOTE: NT 4.0+ only */ int -qxeLoadString (HINSTANCE hInstance, UINT uID, Extbyte * lpBuffer, int nBufferMax) +qxeEnumICMProfiles (HDC arg1, ICMENUMPROCW arg2, LPARAM arg3) { if (XEUNICODE_P) - return LoadStringW (hInstance, uID, (LPWSTR) lpBuffer, nBufferMax); + return EnumICMProfilesW (arg1, arg2, arg3); else - return LoadStringA (hInstance, uID, (LPSTR) lpBuffer, nBufferMax); + return EnumICMProfilesA (arg1, (ICMENUMPROCA) arg2, arg3); } +/* Skipping UpdateICMRegKey because NT 4.0+ only, error in Cygwin prototype */ + +/* Error if wglUseFontBitmaps used: causes link error */ + +/* Error if wglUseFontOutlines used: causes link error */ + + +/*----------------------------------------------------------------------*/ +/* Processing file SHLOBJ.H */ +/*----------------------------------------------------------------------*/ + BOOL -qxeIsDialogMessage (HWND hDlg, LPMSG lpMsg) +qxeSHGetPathFromIDList (LPCITEMIDLIST pidl, Extbyte * pszPath) { if (XEUNICODE_P) - return IsDialogMessageW (hDlg, lpMsg); + return SHGetPathFromIDListW (pidl, (LPWSTR) pszPath); else - return IsDialogMessageA (hDlg, lpMsg); + return SHGetPathFromIDListA (pidl, (LPSTR) pszPath); } -int -qxeDlgDirList (HWND hDlg, Extbyte * lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType) -{ - if (XEUNICODE_P) - return DlgDirListW (hDlg, (LPWSTR) lpPathSpec, nIDListBox, nIDStaticPath, uFileType); - else - return DlgDirListA (hDlg, (LPSTR) lpPathSpec, nIDListBox, nIDStaticPath, uFileType); -} +/* Skipping SHGetSpecialFolderPath because error in Cygwin prototype, missing from Cygwin libraries */ -BOOL -qxeDlgDirSelectEx (HWND hDlg, Extbyte * lpString, int nCount, int nIDListBox) +/* Skipping SHBrowseForFolder because need to intercept callback for SendMessage */ + +/* Skipping SHGetDataFromIDList because split-sized WIN32_FIND_DATA or split-simple NETRESOURCE, missing from Cygwin libraries */ + + +/*----------------------------------------------------------------------*/ +/* Processing file COMMDLG.H */ +/*----------------------------------------------------------------------*/ + +BOOL +qxeGetOpenFileName (LPOPENFILENAMEW arg1) { if (XEUNICODE_P) - return DlgDirSelectExW (hDlg, (LPWSTR) lpString, nCount, nIDListBox); + return GetOpenFileNameW (arg1); else - return DlgDirSelectExA (hDlg, (LPSTR) lpString, nCount, nIDListBox); + return GetOpenFileNameA ((LPOPENFILENAMEA) arg1); } -int -qxeDlgDirListComboBox (HWND hDlg, Extbyte * lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype) +BOOL +qxeGetSaveFileName (LPOPENFILENAMEW arg1) { if (XEUNICODE_P) - return DlgDirListComboBoxW (hDlg, (LPWSTR) lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype); + return GetSaveFileNameW (arg1); else - return DlgDirListComboBoxA (hDlg, (LPSTR) lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype); + return GetSaveFileNameA ((LPOPENFILENAMEA) arg1); } -BOOL -qxeDlgDirSelectComboBoxEx (HWND hDlg, Extbyte * lpString, int nCount, int nIDComboBox) +short +qxeGetFileTitle (const Extbyte * arg1, Extbyte * arg2, WORD arg3) { if (XEUNICODE_P) - return DlgDirSelectComboBoxExW (hDlg, (LPWSTR) lpString, nCount, nIDComboBox); + return GetFileTitleW ((LPCWSTR) arg1, (LPWSTR) arg2, arg3); else - return DlgDirSelectComboBoxExA (hDlg, (LPSTR) lpString, nCount, nIDComboBox); + return GetFileTitleA ((LPCSTR) arg1, (LPSTR) arg2, arg3); } -LRESULT -qxeDefFrameProc (HWND hWnd, HWND hWndMDIClient, UINT uMsg, WPARAM wParam, LPARAM lParam) +BOOL +qxeChooseColor (LPCHOOSECOLORW arg1) { if (XEUNICODE_P) - return DefFrameProcW (hWnd, hWndMDIClient, uMsg, wParam, lParam); + return ChooseColorW (arg1); else - return DefFrameProcA (hWnd, hWndMDIClient, uMsg, wParam, lParam); + return ChooseColorA ((LPCHOOSECOLORA) arg1); } -/* Error if DefMDIChildProc used: return value is conditionalized on _MAC, messes up parser */ - -HWND -qxeCreateMDIWindow (Extbyte * lpClassName, Extbyte * lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HINSTANCE hInstance, LPARAM lParam) +HWND +qxeFindText (LPFINDREPLACEW arg1) { if (XEUNICODE_P) - return CreateMDIWindowW ((LPWSTR) lpClassName, (LPWSTR) lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hInstance, lParam); + return FindTextW (arg1); else - return CreateMDIWindowA ((LPSTR) lpClassName, (LPSTR) lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hInstance, lParam); + return FindTextA ((LPFINDREPLACEA) arg1); } -BOOL -qxeWinHelp (HWND hWndMain, const Extbyte * lpszHelp, UINT uCommand, DWORD dwData) +HWND +qxeReplaceText (LPFINDREPLACEW arg1) { if (XEUNICODE_P) - return WinHelpW (hWndMain, (LPCWSTR) lpszHelp, uCommand, dwData); + return ReplaceTextW (arg1); else - return WinHelpA (hWndMain, (LPCSTR) lpszHelp, uCommand, dwData); + return ReplaceTextA ((LPFINDREPLACEA) arg1); } -/* Error if ChangeDisplaySettings used: split-sized LPDEVMODE */ +/* Error if AfxReplaceText used: mac only */ -/* Error if ChangeDisplaySettingsEx used: split-sized LPDEVMODE; NT 5.0/Win98+ only */ +/* Error if ChooseFont used: split-sized LPLOGFONT in LPCHOOSEFONT */ -/* Error if EnumDisplaySettings used: split-sized LPDEVMODE */ +/* Skipping PrintDlg because LPPRINTDLG with split-sized DEVMODE handle */ -/* Error if EnumDisplayDevices used: split-sized PDISPLAY_DEVICE; NT 5.0+ only, no Win98 */ +/* Skipping PageSetupDlg because LPPAGESETUPDLG with split-sized DEVMODE handle */ -/* NOTE: probs w/ICONMETRICS, NONCLIENTMETRICS */ -BOOL -qxeSystemParametersInfo (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni) + +/*----------------------------------------------------------------------*/ +/* Processing file IMM.H */ +/*----------------------------------------------------------------------*/ + +#if defined (HAVE_MS_WINDOWS) + +HKL +qxeImmInstallIME (const Extbyte * lpszIMEFileName, const Extbyte * lpszLayoutText) { if (XEUNICODE_P) - return SystemParametersInfoW (uiAction, uiParam, pvParam, fWinIni); + return ImmInstallIMEW ((LPCWSTR) lpszIMEFileName, (LPCWSTR) lpszLayoutText); else - return SystemParametersInfoA (uiAction, uiParam, pvParam, fWinIni); + return ImmInstallIMEA ((LPCSTR) lpszIMEFileName, (LPCSTR) lpszLayoutText); } -/* Error if GetMonitorInfo used: NT 5.0/Win98+ only */ - -/* Error if GetWindowModuleFileName used: NT 5.0+ only */ - -/* Error if RealGetWindowClass used: NT 5.0+ only */ - -/* Error if GetAltTabInfo used: NT 5.0+ only */ - +#endif /* defined (HAVE_MS_WINDOWS) */ -/*----------------------------------------------------------------------*/ -/* Processing file MMSYSTEM.H */ -/*----------------------------------------------------------------------*/ +#if defined (HAVE_MS_WINDOWS) -BOOL -qxesndPlaySound (const Extbyte * pszSound, UINT fuSound) +UINT +qxeImmGetDescription (HKL arg1, Extbyte * arg2, UINT uBufLen) { if (XEUNICODE_P) - return sndPlaySoundW ((LPCWSTR) pszSound, fuSound); + return ImmGetDescriptionW (arg1, (LPWSTR) arg2, uBufLen); else - return sndPlaySoundA ((LPCSTR) pszSound, fuSound); + return ImmGetDescriptionA (arg1, (LPSTR) arg2, uBufLen); } -BOOL -qxePlaySound (const Extbyte * pszSound, HMODULE hmod, DWORD fdwSound) +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) + +UINT +qxeImmGetIMEFileName (HKL arg1, Extbyte * arg2, UINT uBufLen) { if (XEUNICODE_P) - return PlaySoundW ((LPCWSTR) pszSound, hmod, fdwSound); + return ImmGetIMEFileNameW (arg1, (LPWSTR) arg2, uBufLen); else - return PlaySoundA ((LPCSTR) pszSound, hmod, fdwSound); + return ImmGetIMEFileNameA (arg1, (LPSTR) arg2, uBufLen); } -/* Error if waveOutGetDevCaps used: split-sized LPWAVEOUTCAPS */ +#endif /* defined (HAVE_MS_WINDOWS) */ -MMRESULT -qxewaveOutGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText) +#if defined (HAVE_MS_WINDOWS) + +LONG +qxeImmGetCompositionString (HIMC arg1, DWORD arg2, LPVOID arg3, DWORD arg4) { if (XEUNICODE_P) - return waveOutGetErrorTextW (mmrError, (LPWSTR) pszText, cchText); + return ImmGetCompositionStringW (arg1, arg2, arg3, arg4); else - return waveOutGetErrorTextA (mmrError, (LPSTR) pszText, cchText); + return ImmGetCompositionStringA (arg1, arg2, arg3, arg4); } -/* Error if waveInGetDevCaps used: split-sized LPWAVEINCAPS */ +#endif /* defined (HAVE_MS_WINDOWS) */ -MMRESULT -qxewaveInGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText) +#if defined (HAVE_MS_WINDOWS) + +DWORD +qxeImmGetCandidateListCount (HIMC arg1, LPDWORD lpdwListCount) { if (XEUNICODE_P) - return waveInGetErrorTextW (mmrError, (LPWSTR) pszText, cchText); + return ImmGetCandidateListCountW (arg1, lpdwListCount); else - return waveInGetErrorTextA (mmrError, (LPSTR) pszText, cchText); + return ImmGetCandidateListCountA (arg1, lpdwListCount); } -/* Error if midiOutGetDevCaps used: split-sized LPMIDIOUTCAPS */ +#endif /* defined (HAVE_MS_WINDOWS) */ -MMRESULT -qxemidiOutGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText) +#if defined (HAVE_MS_WINDOWS) + +DWORD +qxeImmGetCandidateList (HIMC arg1, DWORD deIndex, LPCANDIDATELIST arg3, DWORD dwBufLen) { if (XEUNICODE_P) - return midiOutGetErrorTextW (mmrError, (LPWSTR) pszText, cchText); + return ImmGetCandidateListW (arg1, deIndex, arg3, dwBufLen); else - return midiOutGetErrorTextA (mmrError, (LPSTR) pszText, cchText); + return ImmGetCandidateListA (arg1, deIndex, arg3, dwBufLen); } -/* Error if midiInGetDevCaps used: split-sized LPMIDIOUTCAPS */ +#endif /* defined (HAVE_MS_WINDOWS) */ -MMRESULT -qxemidiInGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText) +#if defined (HAVE_MS_WINDOWS) + +DWORD +qxeImmGetGuideLine (HIMC arg1, DWORD dwIndex, Extbyte * arg3, DWORD dwBufLen) { if (XEUNICODE_P) - return midiInGetErrorTextW (mmrError, (LPWSTR) pszText, cchText); + return ImmGetGuideLineW (arg1, dwIndex, (LPWSTR) arg3, dwBufLen); else - return midiInGetErrorTextA (mmrError, (LPSTR) pszText, cchText); + return ImmGetGuideLineA (arg1, dwIndex, (LPSTR) arg3, dwBufLen); } -/* Error if auxGetDevCaps used: split-sized LPAUXCAPS */ +#endif /* defined (HAVE_MS_WINDOWS) */ -/* Error if mixerGetDevCaps used: split-sized LPMIXERCAPS */ +#if defined (HAVE_MS_WINDOWS) -/* Error if mixerGetLineInfo used: split-sized LPMIXERLINE */ +/* Skipping ImmGetCompositionFont because split-sized LOGFONT */ -/* Error if mixerGetLineControls used: split-sized LPMIXERCONTROL */ +#endif /* defined (HAVE_MS_WINDOWS) */ -/* Error if mixerGetControlDetails used: split-sized LPMIXERCONTROL in LPMIXERLINECONTROLS in LPMIXERCONTROLDETAILS */ +#if defined (HAVE_MS_WINDOWS) -/* Error if joyGetDevCaps used: split-sized LPJOYCAPS */ +/* Skipping ImmSetCompositionFont because split-sized LOGFONT */ -FOURCC -qxemmioStringToFOURCC (const Extbyte * sz, UINT uFlags) -{ - if (XEUNICODE_P) - return mmioStringToFOURCCW ((LPCWSTR) sz, uFlags); - else - return mmioStringToFOURCCA ((LPCSTR) sz, uFlags); -} +#endif /* defined (HAVE_MS_WINDOWS) */ -LPMMIOPROC -qxemmioInstallIOProc (FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags) +#if defined (HAVE_MS_WINDOWS) + +/* NOTE: // split-simple REGISTERWORD */ +BOOL +qxeImmConfigureIME (HKL arg1, HWND arg2, DWORD arg3, LPVOID arg4) { if (XEUNICODE_P) - return mmioInstallIOProcW (fccIOProc, pIOProc, dwFlags); + return ImmConfigureIMEW (arg1, arg2, arg3, arg4); else - return mmioInstallIOProcA (fccIOProc, pIOProc, dwFlags); + return ImmConfigureIMEA (arg1, arg2, arg3, arg4); } -HMMIO -qxemmioOpen (Extbyte * pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen) +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) + +/* NOTE: // strings of various sorts */ +LRESULT +qxeImmEscape (HKL arg1, HIMC arg2, UINT arg3, LPVOID arg4) { if (XEUNICODE_P) - return mmioOpenW ((LPWSTR) pszFileName, pmmioinfo, fdwOpen); + return ImmEscapeW (arg1, arg2, arg3, arg4); else - return mmioOpenA ((LPSTR) pszFileName, pmmioinfo, fdwOpen); + return ImmEscapeA (arg1, arg2, arg3, arg4); } -MMRESULT -qxemmioRename (const Extbyte * pszFileName, const Extbyte * pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename) +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) + +DWORD +qxeImmGetConversionList (HKL arg1, HIMC arg2, const Extbyte * arg3, LPCANDIDATELIST arg4, DWORD dwBufLen, UINT uFlag) { if (XEUNICODE_P) - return mmioRenameW ((LPCWSTR) pszFileName, (LPCWSTR) pszNewFileName, pmmioinfo, fdwRename); + return ImmGetConversionListW (arg1, arg2, (LPCWSTR) arg3, arg4, dwBufLen, uFlag); else - return mmioRenameA ((LPCSTR) pszFileName, (LPCSTR) pszNewFileName, pmmioinfo, fdwRename); + return ImmGetConversionListA (arg1, arg2, (LPCSTR) arg3, arg4, dwBufLen, uFlag); } -MCIERROR -qxemciSendCommand (MCIDEVICEID mciId, UINT uMsg, DWORD dwParam1, DWORD dwParam2) +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) + +BOOL +qxeImmIsUIMessage (HWND arg1, UINT arg2, WPARAM arg3, LPARAM arg4) { if (XEUNICODE_P) - return mciSendCommandW (mciId, uMsg, dwParam1, dwParam2); + return ImmIsUIMessageW (arg1, arg2, arg3, arg4); else - return mciSendCommandA (mciId, uMsg, dwParam1, dwParam2); + return ImmIsUIMessageA (arg1, arg2, arg3, arg4); } -MCIERROR -qxemciSendString (const Extbyte * lpstrCommand, Extbyte * lpstrReturnString, UINT uReturnLength, HWND hwndCallback) +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) + +BOOL +qxeImmRegisterWord (HKL arg1, const Extbyte * lpszReading, DWORD arg3, const Extbyte * lpszRegister) { if (XEUNICODE_P) - return mciSendStringW ((LPCWSTR) lpstrCommand, (LPWSTR) lpstrReturnString, uReturnLength, hwndCallback); + return ImmRegisterWordW (arg1, (LPCWSTR) lpszReading, arg3, (LPCWSTR) lpszRegister); else - return mciSendStringA ((LPCSTR) lpstrCommand, (LPSTR) lpstrReturnString, uReturnLength, hwndCallback); + return ImmRegisterWordA (arg1, (LPCSTR) lpszReading, arg3, (LPCSTR) lpszRegister); } -MCIDEVICEID -qxemciGetDeviceID (const Extbyte * pszDevice) +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) + +BOOL +qxeImmUnregisterWord (HKL arg1, const Extbyte * lpszReading, DWORD arg3, const Extbyte * lpszUnregister) { if (XEUNICODE_P) - return mciGetDeviceIDW ((LPCWSTR) pszDevice); + return ImmUnregisterWordW (arg1, (LPCWSTR) lpszReading, arg3, (LPCWSTR) lpszUnregister); else - return mciGetDeviceIDA ((LPCSTR) pszDevice); + return ImmUnregisterWordA (arg1, (LPCSTR) lpszReading, arg3, (LPCSTR) lpszUnregister); } -#if !defined (MINGW) +#endif /* defined (HAVE_MS_WINDOWS) */ -/* Error if mciGetDeviceIDFromElementID used: missing from Win98se version of ADVAPI32.dll */ +#if defined (HAVE_MS_WINDOWS) -#endif /* !defined (MINGW) */ +/* Error if ImmGetRegisterWordStyle used: split-sized STYLEBUF */ -BOOL -qxemciGetErrorString (MCIERROR mcierr, Extbyte * pszText, UINT cchText) +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) + +UINT +qxeImmEnumRegisterWord (HKL arg1, REGISTERWORDENUMPROCW arg2, const Extbyte * lpszReading, DWORD arg4, const Extbyte * lpszRegister, LPVOID arg6) { if (XEUNICODE_P) - return mciGetErrorStringW (mcierr, (LPWSTR) pszText, cchText); + return ImmEnumRegisterWordW (arg1, arg2, (LPCWSTR) lpszReading, arg4, (LPCWSTR) lpszRegister, arg6); else - return mciGetErrorStringA (mcierr, (LPSTR) pszText, cchText); + return ImmEnumRegisterWordA (arg1, (REGISTERWORDENUMPROCA) arg2, (LPCSTR) lpszReading, arg4, (LPCSTR) lpszRegister, arg6); } +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) + +/* Error if ImmGetImeMenuItems used: split-sized IMEMENUITEMINFO */ + +#endif /* defined (HAVE_MS_WINDOWS) */ + /*----------------------------------------------------------------------*/ /* Processing file WINBASE.H */ @@ -2897,33 +3132,6 @@ return FindResourceExA (hModule, (LPCSTR) lpType, (LPCSTR) lpName, wLanguage); } -BOOL -qxeEnumResourceTypes (HMODULE hModule, ENUMRESTYPEPROC lpEnumFunc, LONG lParam) -{ - if (XEUNICODE_P) - return EnumResourceTypesW (hModule, lpEnumFunc, lParam); - else - return EnumResourceTypesA (hModule, lpEnumFunc, lParam); -} - -BOOL -qxeEnumResourceNames (HMODULE hModule, const Extbyte * lpType, ENUMRESNAMEPROC lpEnumFunc, LONG lParam) -{ - if (XEUNICODE_P) - return EnumResourceNamesW (hModule, (LPCWSTR) lpType, lpEnumFunc, lParam); - else - return EnumResourceNamesA (hModule, (LPCSTR) lpType, lpEnumFunc, lParam); -} - -BOOL -qxeEnumResourceLanguages (HMODULE hModule, const Extbyte * lpType, const Extbyte * lpName, ENUMRESLANGPROC lpEnumFunc, LONG lParam) -{ - if (XEUNICODE_P) - return EnumResourceLanguagesW (hModule, (LPCWSTR) lpType, (LPCWSTR) lpName, lpEnumFunc, lParam); - else - return EnumResourceLanguagesA (hModule, (LPCSTR) lpType, (LPCSTR) lpName, lpEnumFunc, lParam); -} - HANDLE qxeBeginUpdateResource (const Extbyte * pFileName, BOOL bDeleteExistingResources) { @@ -3346,785 +3554,537 @@ } BOOL -qxeMoveFile (const Extbyte * lpExistingFileName, const Extbyte * lpNewFileName) -{ - if (XEUNICODE_P) - return MoveFileW ((LPCWSTR) lpExistingFileName, (LPCWSTR) lpNewFileName); - else - return MoveFileA ((LPCSTR) lpExistingFileName, (LPCSTR) lpNewFileName); -} - -BOOL -qxeMoveFileEx (const Extbyte * lpExistingFileName, const Extbyte * lpNewFileName, DWORD dwFlags) -{ - if (XEUNICODE_P) - return MoveFileExW ((LPCWSTR) lpExistingFileName, (LPCWSTR) lpNewFileName, dwFlags); - else - return MoveFileExA ((LPCSTR) lpExistingFileName, (LPCSTR) lpNewFileName, dwFlags); -} - -/* Error if MoveFileWithProgress used: NT 5.0+ only */ - -/* Error if CreateHardLink used: NT 5.0+ only */ - -HANDLE -qxeCreateNamedPipe (const Extbyte * lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes) -{ - if (XEUNICODE_P) - return CreateNamedPipeW ((LPCWSTR) lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes); - else - return CreateNamedPipeA ((LPCSTR) lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes); -} - -BOOL -qxeGetNamedPipeHandleState (HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout, Extbyte * lpUserName, DWORD nMaxUserNameSize) -{ - if (XEUNICODE_P) - return GetNamedPipeHandleStateW (hNamedPipe, lpState, lpCurInstances, lpMaxCollectionCount, lpCollectDataTimeout, (LPWSTR) lpUserName, nMaxUserNameSize); - else - return GetNamedPipeHandleStateA (hNamedPipe, lpState, lpCurInstances, lpMaxCollectionCount, lpCollectDataTimeout, (LPSTR) lpUserName, nMaxUserNameSize); -} - -BOOL -qxeCallNamedPipe (const Extbyte * lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, DWORD nTimeOut) -{ - if (XEUNICODE_P) - return CallNamedPipeW ((LPCWSTR) lpNamedPipeName, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, nTimeOut); - else - return CallNamedPipeA ((LPCSTR) lpNamedPipeName, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, nTimeOut); -} - -BOOL -qxeWaitNamedPipe (const Extbyte * lpNamedPipeName, DWORD nTimeOut) -{ - if (XEUNICODE_P) - return WaitNamedPipeW ((LPCWSTR) lpNamedPipeName, nTimeOut); - else - return WaitNamedPipeA ((LPCSTR) lpNamedPipeName, nTimeOut); -} - -BOOL -qxeSetVolumeLabel (const Extbyte * lpRootPathName, const Extbyte * lpVolumeName) -{ - if (XEUNICODE_P) - return SetVolumeLabelW ((LPCWSTR) lpRootPathName, (LPCWSTR) lpVolumeName); - else - return SetVolumeLabelA ((LPCSTR) lpRootPathName, (LPCSTR) lpVolumeName); -} - -BOOL -qxeGetVolumeInformation (const Extbyte * lpRootPathName, Extbyte * lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, Extbyte * lpFileSystemNameBuffer, DWORD nFileSystemNameSize) -{ - if (XEUNICODE_P) - return GetVolumeInformationW ((LPCWSTR) lpRootPathName, (LPWSTR) lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, (LPWSTR) lpFileSystemNameBuffer, nFileSystemNameSize); - else - return GetVolumeInformationA ((LPCSTR) lpRootPathName, (LPSTR) lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, (LPSTR) lpFileSystemNameBuffer, nFileSystemNameSize); -} - -BOOL -qxeClearEventLog (HANDLE hEventLog, const Extbyte * lpBackupFileName) -{ - if (XEUNICODE_P) - return ClearEventLogW (hEventLog, (LPCWSTR) lpBackupFileName); - else - return ClearEventLogA (hEventLog, (LPCSTR) lpBackupFileName); -} - -BOOL -qxeBackupEventLog (HANDLE hEventLog, const Extbyte * lpBackupFileName) -{ - if (XEUNICODE_P) - return BackupEventLogW (hEventLog, (LPCWSTR) lpBackupFileName); - else - return BackupEventLogA (hEventLog, (LPCSTR) lpBackupFileName); -} - -HANDLE -qxeOpenEventLog (const Extbyte * lpUNCServerName, const Extbyte * lpSourceName) -{ - if (XEUNICODE_P) - return OpenEventLogW ((LPCWSTR) lpUNCServerName, (LPCWSTR) lpSourceName); - else - return OpenEventLogA ((LPCSTR) lpUNCServerName, (LPCSTR) lpSourceName); -} - -HANDLE -qxeRegisterEventSource (const Extbyte * lpUNCServerName, const Extbyte * lpSourceName) -{ - if (XEUNICODE_P) - return RegisterEventSourceW ((LPCWSTR) lpUNCServerName, (LPCWSTR) lpSourceName); - else - return RegisterEventSourceA ((LPCSTR) lpUNCServerName, (LPCSTR) lpSourceName); -} - -HANDLE -qxeOpenBackupEventLog (const Extbyte * lpUNCServerName, const Extbyte * lpFileName) -{ - if (XEUNICODE_P) - return OpenBackupEventLogW ((LPCWSTR) lpUNCServerName, (LPCWSTR) lpFileName); - else - return OpenBackupEventLogA ((LPCSTR) lpUNCServerName, (LPCSTR) lpFileName); -} - -BOOL -qxeReadEventLog (HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD * pnBytesRead, DWORD * pnMinNumberOfBytesNeeded) -{ - if (XEUNICODE_P) - return ReadEventLogW (hEventLog, dwReadFlags, dwRecordOffset, lpBuffer, nNumberOfBytesToRead, pnBytesRead, pnMinNumberOfBytesNeeded); - else - return ReadEventLogA (hEventLog, dwReadFlags, dwRecordOffset, lpBuffer, nNumberOfBytesToRead, pnBytesRead, pnMinNumberOfBytesNeeded); -} - -BOOL -qxeReportEvent (HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, const Extbyte * * lpStrings, LPVOID lpRawData) -{ - if (XEUNICODE_P) - return ReportEventW (hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, (LPCWSTR *) lpStrings, lpRawData); - else - return ReportEventA (hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, (LPCSTR *) lpStrings, lpRawData); -} - -BOOL -qxeAccessCheckAndAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, Extbyte * ObjectTypeName, Extbyte * ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose) -{ - if (XEUNICODE_P) - return AccessCheckAndAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, (LPWSTR) ObjectTypeName, (LPWSTR) ObjectName, SecurityDescriptor, DesiredAccess, GenericMapping, ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose); - else - return AccessCheckAndAuditAlarmA ((LPCSTR) SubsystemName, HandleId, (LPSTR) ObjectTypeName, (LPSTR) ObjectName, SecurityDescriptor, DesiredAccess, GenericMapping, ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose); -} - -/* Error if AccessCheckByTypeAndAuditAlarm used: NT 5.0+ only */ - -/* Error if AccessCheckByTypeResultListAndAuditAlarm used: NT 5.0+ only */ - -BOOL -qxeObjectOpenAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, Extbyte * ObjectTypeName, Extbyte * ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted, LPBOOL GenerateOnClose) -{ - if (XEUNICODE_P) - return ObjectOpenAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, (LPWSTR) ObjectTypeName, (LPWSTR) ObjectName, pSecurityDescriptor, ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted, GenerateOnClose); - else - return ObjectOpenAuditAlarmA ((LPCSTR) SubsystemName, HandleId, (LPSTR) ObjectTypeName, (LPSTR) ObjectName, pSecurityDescriptor, ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted, GenerateOnClose); -} - -BOOL -qxeObjectPrivilegeAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, HANDLE ClientToken, DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted) -{ - if (XEUNICODE_P) - return ObjectPrivilegeAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, ClientToken, DesiredAccess, Privileges, AccessGranted); - else - return ObjectPrivilegeAuditAlarmA ((LPCSTR) SubsystemName, HandleId, ClientToken, DesiredAccess, Privileges, AccessGranted); -} - -BOOL -qxeObjectCloseAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, BOOL GenerateOnClose) -{ - if (XEUNICODE_P) - return ObjectCloseAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, GenerateOnClose); - else - return ObjectCloseAuditAlarmA ((LPCSTR) SubsystemName, HandleId, GenerateOnClose); -} - -BOOL -qxeObjectDeleteAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, BOOL GenerateOnClose) -{ - if (XEUNICODE_P) - return ObjectDeleteAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, GenerateOnClose); - else - return ObjectDeleteAuditAlarmA ((LPCSTR) SubsystemName, HandleId, GenerateOnClose); -} - -BOOL -qxePrivilegedServiceAuditAlarm (const Extbyte * SubsystemName, const Extbyte * ServiceName, HANDLE ClientToken, PPRIVILEGE_SET Privileges, BOOL AccessGranted) -{ - if (XEUNICODE_P) - return PrivilegedServiceAuditAlarmW ((LPCWSTR) SubsystemName, (LPCWSTR) ServiceName, ClientToken, Privileges, AccessGranted); - else - return PrivilegedServiceAuditAlarmA ((LPCSTR) SubsystemName, (LPCSTR) ServiceName, ClientToken, Privileges, AccessGranted); -} - -BOOL -qxeSetFileSecurity (const Extbyte * lpFileName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) -{ - if (XEUNICODE_P) - return SetFileSecurityW ((LPCWSTR) lpFileName, SecurityInformation, pSecurityDescriptor); - else - return SetFileSecurityA ((LPCSTR) lpFileName, SecurityInformation, pSecurityDescriptor); -} - -BOOL -qxeGetFileSecurity (const Extbyte * lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) -{ - if (XEUNICODE_P) - return GetFileSecurityW ((LPCWSTR) lpFileName, RequestedInformation, pSecurityDescriptor, nLength, lpnLengthNeeded); - else - return GetFileSecurityA ((LPCSTR) lpFileName, RequestedInformation, pSecurityDescriptor, nLength, lpnLengthNeeded); -} - -HANDLE -qxeFindFirstChangeNotification (const Extbyte * lpPathName, BOOL bWatchSubtree, DWORD dwNotifyFilter) -{ - if (XEUNICODE_P) - return FindFirstChangeNotificationW ((LPCWSTR) lpPathName, bWatchSubtree, dwNotifyFilter); - else - return FindFirstChangeNotificationA ((LPCSTR) lpPathName, bWatchSubtree, dwNotifyFilter); -} - -/* Error if ReadDirectoryChanges used: Unicode-only */ - -BOOL -qxeIsBadStringPtr (const Extbyte * lpsz, UINT ucchMax) +qxeMoveFile (const Extbyte * lpExistingFileName, const Extbyte * lpNewFileName) { if (XEUNICODE_P) - return IsBadStringPtrW ((LPCWSTR) lpsz, ucchMax); + return MoveFileW ((LPCWSTR) lpExistingFileName, (LPCWSTR) lpNewFileName); else - return IsBadStringPtrA ((LPCSTR) lpsz, ucchMax); + return MoveFileA ((LPCSTR) lpExistingFileName, (LPCSTR) lpNewFileName); } BOOL -qxeLookupAccountSid (const Extbyte * lpSystemName, PSID Sid, Extbyte * Name, LPDWORD cbName, Extbyte * ReferencedDomainName, LPDWORD cbReferencedDomainName, PSID_NAME_USE peUse) +qxeMoveFileEx (const Extbyte * lpExistingFileName, const Extbyte * lpNewFileName, DWORD dwFlags) { if (XEUNICODE_P) - return LookupAccountSidW ((LPCWSTR) lpSystemName, Sid, (LPWSTR) Name, cbName, (LPWSTR) ReferencedDomainName, cbReferencedDomainName, peUse); + return MoveFileExW ((LPCWSTR) lpExistingFileName, (LPCWSTR) lpNewFileName, dwFlags); else - return LookupAccountSidA ((LPCSTR) lpSystemName, Sid, (LPSTR) Name, cbName, (LPSTR) ReferencedDomainName, cbReferencedDomainName, peUse); + return MoveFileExA ((LPCSTR) lpExistingFileName, (LPCSTR) lpNewFileName, dwFlags); } -BOOL -qxeLookupAccountName (const Extbyte * lpSystemName, const Extbyte * lpAccountName, PSID Sid, LPDWORD cbSid, Extbyte * ReferencedDomainName, LPDWORD cbReferencedDomainName, PSID_NAME_USE peUse) +/* Error if MoveFileWithProgress used: NT 5.0+ only */ + +/* Error if CreateHardLink used: NT 5.0+ only */ + +HANDLE +qxeCreateNamedPipe (const Extbyte * lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { if (XEUNICODE_P) - return LookupAccountNameW ((LPCWSTR) lpSystemName, (LPCWSTR) lpAccountName, Sid, cbSid, (LPWSTR) ReferencedDomainName, cbReferencedDomainName, peUse); + return CreateNamedPipeW ((LPCWSTR) lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes); else - return LookupAccountNameA ((LPCSTR) lpSystemName, (LPCSTR) lpAccountName, Sid, cbSid, (LPSTR) ReferencedDomainName, cbReferencedDomainName, peUse); + return CreateNamedPipeA ((LPCSTR) lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes); } BOOL -qxeLookupPrivilegeValue (const Extbyte * lpSystemName, const Extbyte * lpName, PLUID lpLuid) +qxeGetNamedPipeHandleState (HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout, Extbyte * lpUserName, DWORD nMaxUserNameSize) { if (XEUNICODE_P) - return LookupPrivilegeValueW ((LPCWSTR) lpSystemName, (LPCWSTR) lpName, lpLuid); + return GetNamedPipeHandleStateW (hNamedPipe, lpState, lpCurInstances, lpMaxCollectionCount, lpCollectDataTimeout, (LPWSTR) lpUserName, nMaxUserNameSize); else - return LookupPrivilegeValueA ((LPCSTR) lpSystemName, (LPCSTR) lpName, lpLuid); + return GetNamedPipeHandleStateA (hNamedPipe, lpState, lpCurInstances, lpMaxCollectionCount, lpCollectDataTimeout, (LPSTR) lpUserName, nMaxUserNameSize); } BOOL -qxeLookupPrivilegeName (const Extbyte * lpSystemName, PLUID lpLuid, Extbyte * lpName, LPDWORD cbName) +qxeCallNamedPipe (const Extbyte * lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, DWORD nTimeOut) { if (XEUNICODE_P) - return LookupPrivilegeNameW ((LPCWSTR) lpSystemName, lpLuid, (LPWSTR) lpName, cbName); + return CallNamedPipeW ((LPCWSTR) lpNamedPipeName, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, nTimeOut); else - return LookupPrivilegeNameA ((LPCSTR) lpSystemName, lpLuid, (LPSTR) lpName, cbName); + return CallNamedPipeA ((LPCSTR) lpNamedPipeName, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, nTimeOut); } BOOL -qxeLookupPrivilegeDisplayName (const Extbyte * lpSystemName, const Extbyte * lpName, Extbyte * lpDisplayName, LPDWORD cbDisplayName, LPDWORD lpLanguageId) +qxeWaitNamedPipe (const Extbyte * lpNamedPipeName, DWORD nTimeOut) { if (XEUNICODE_P) - return LookupPrivilegeDisplayNameW ((LPCWSTR) lpSystemName, (LPCWSTR) lpName, (LPWSTR) lpDisplayName, cbDisplayName, lpLanguageId); + return WaitNamedPipeW ((LPCWSTR) lpNamedPipeName, nTimeOut); else - return LookupPrivilegeDisplayNameA ((LPCSTR) lpSystemName, (LPCSTR) lpName, (LPSTR) lpDisplayName, cbDisplayName, lpLanguageId); + return WaitNamedPipeA ((LPCSTR) lpNamedPipeName, nTimeOut); } BOOL -qxeBuildCommDCB (const Extbyte * lpDef, LPDCB lpDCB) +qxeSetVolumeLabel (const Extbyte * lpRootPathName, const Extbyte * lpVolumeName) { if (XEUNICODE_P) - return BuildCommDCBW ((LPCWSTR) lpDef, lpDCB); + return SetVolumeLabelW ((LPCWSTR) lpRootPathName, (LPCWSTR) lpVolumeName); else - return BuildCommDCBA ((LPCSTR) lpDef, lpDCB); + return SetVolumeLabelA ((LPCSTR) lpRootPathName, (LPCSTR) lpVolumeName); } BOOL -qxeBuildCommDCBAndTimeouts (const Extbyte * lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts) +qxeGetVolumeInformation (const Extbyte * lpRootPathName, Extbyte * lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, Extbyte * lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { if (XEUNICODE_P) - return BuildCommDCBAndTimeoutsW ((LPCWSTR) lpDef, lpDCB, lpCommTimeouts); + return GetVolumeInformationW ((LPCWSTR) lpRootPathName, (LPWSTR) lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, (LPWSTR) lpFileSystemNameBuffer, nFileSystemNameSize); else - return BuildCommDCBAndTimeoutsA ((LPCSTR) lpDef, lpDCB, lpCommTimeouts); + return GetVolumeInformationA ((LPCSTR) lpRootPathName, (LPSTR) lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, (LPSTR) lpFileSystemNameBuffer, nFileSystemNameSize); } BOOL -qxeCommConfigDialog (const Extbyte * lpszName, HWND hWnd, LPCOMMCONFIG lpCC) +qxeClearEventLog (HANDLE hEventLog, const Extbyte * lpBackupFileName) { if (XEUNICODE_P) - return CommConfigDialogW ((LPCWSTR) lpszName, hWnd, lpCC); + return ClearEventLogW (hEventLog, (LPCWSTR) lpBackupFileName); else - return CommConfigDialogA ((LPCSTR) lpszName, hWnd, lpCC); + return ClearEventLogA (hEventLog, (LPCSTR) lpBackupFileName); } BOOL -qxeGetDefaultCommConfig (const Extbyte * lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize) +qxeBackupEventLog (HANDLE hEventLog, const Extbyte * lpBackupFileName) { if (XEUNICODE_P) - return GetDefaultCommConfigW ((LPCWSTR) lpszName, lpCC, lpdwSize); + return BackupEventLogW (hEventLog, (LPCWSTR) lpBackupFileName); else - return GetDefaultCommConfigA ((LPCSTR) lpszName, lpCC, lpdwSize); + return BackupEventLogA (hEventLog, (LPCSTR) lpBackupFileName); } -BOOL -qxeSetDefaultCommConfig (const Extbyte * lpszName, LPCOMMCONFIG lpCC, DWORD dwSize) +HANDLE +qxeOpenEventLog (const Extbyte * lpUNCServerName, const Extbyte * lpSourceName) { if (XEUNICODE_P) - return SetDefaultCommConfigW ((LPCWSTR) lpszName, lpCC, dwSize); + return OpenEventLogW ((LPCWSTR) lpUNCServerName, (LPCWSTR) lpSourceName); else - return SetDefaultCommConfigA ((LPCSTR) lpszName, lpCC, dwSize); + return OpenEventLogA ((LPCSTR) lpUNCServerName, (LPCSTR) lpSourceName); } -BOOL -qxeGetComputerName (Extbyte * lpBuffer, LPDWORD nSize) +HANDLE +qxeRegisterEventSource (const Extbyte * lpUNCServerName, const Extbyte * lpSourceName) { if (XEUNICODE_P) - return GetComputerNameW ((LPWSTR) lpBuffer, nSize); + return RegisterEventSourceW ((LPCWSTR) lpUNCServerName, (LPCWSTR) lpSourceName); else - return GetComputerNameA ((LPSTR) lpBuffer, nSize); + return RegisterEventSourceA ((LPCSTR) lpUNCServerName, (LPCSTR) lpSourceName); } -BOOL -qxeSetComputerName (const Extbyte * lpComputerName) +HANDLE +qxeOpenBackupEventLog (const Extbyte * lpUNCServerName, const Extbyte * lpFileName) { if (XEUNICODE_P) - return SetComputerNameW ((LPCWSTR) lpComputerName); + return OpenBackupEventLogW ((LPCWSTR) lpUNCServerName, (LPCWSTR) lpFileName); else - return SetComputerNameA ((LPCSTR) lpComputerName); + return OpenBackupEventLogA ((LPCSTR) lpUNCServerName, (LPCSTR) lpFileName); } BOOL -qxeGetUserName (Extbyte * lpBuffer, LPDWORD nSize) +qxeReadEventLog (HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD * pnBytesRead, DWORD * pnMinNumberOfBytesNeeded) { if (XEUNICODE_P) - return GetUserNameW ((LPWSTR) lpBuffer, nSize); + return ReadEventLogW (hEventLog, dwReadFlags, dwRecordOffset, lpBuffer, nNumberOfBytesToRead, pnBytesRead, pnMinNumberOfBytesNeeded); else - return GetUserNameA ((LPSTR) lpBuffer, nSize); + return ReadEventLogA (hEventLog, dwReadFlags, dwRecordOffset, lpBuffer, nNumberOfBytesToRead, pnBytesRead, pnMinNumberOfBytesNeeded); } BOOL -qxeLogonUser (Extbyte * lpszUsername, Extbyte * lpszDomain, Extbyte * lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken) +qxeReportEvent (HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, const Extbyte * * lpStrings, LPVOID lpRawData) { if (XEUNICODE_P) - return LogonUserW ((LPWSTR) lpszUsername, (LPWSTR) lpszDomain, (LPWSTR) lpszPassword, dwLogonType, dwLogonProvider, phToken); + return ReportEventW (hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, (LPCWSTR *) lpStrings, lpRawData); else - return LogonUserA ((LPSTR) lpszUsername, (LPSTR) lpszDomain, (LPSTR) lpszPassword, dwLogonType, dwLogonProvider, phToken); + return ReportEventA (hEventLog, wType, wCategory, dwEventID, lpUserSid, wNumStrings, dwDataSize, (LPCSTR *) lpStrings, lpRawData); } BOOL -qxeCreateProcessAsUser (HANDLE hToken, const Extbyte * lpApplicationName, Extbyte * lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, const Extbyte * lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) +qxeAccessCheckAndAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, Extbyte * ObjectTypeName, Extbyte * ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose) { if (XEUNICODE_P) - return CreateProcessAsUserW (hToken, (LPCWSTR) lpApplicationName, (LPWSTR) lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, (LPCWSTR) lpCurrentDirectory, lpStartupInfo, lpProcessInformation); + return AccessCheckAndAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, (LPWSTR) ObjectTypeName, (LPWSTR) ObjectName, SecurityDescriptor, DesiredAccess, GenericMapping, ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose); else - return CreateProcessAsUserA (hToken, (LPCSTR) lpApplicationName, (LPSTR) lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, (LPCSTR) lpCurrentDirectory, (LPSTARTUPINFOA) lpStartupInfo, lpProcessInformation); + return AccessCheckAndAuditAlarmA ((LPCSTR) SubsystemName, HandleId, (LPSTR) ObjectTypeName, (LPSTR) ObjectName, SecurityDescriptor, DesiredAccess, GenericMapping, ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose); } -/* Error if GetCurrentHwProfile used: split-sized LPHW_PROFILE_INFO; NT 4.0+ only */ - -/* Error if GetVersionEx used: split-sized LPOSVERSIONINFO */ - -/* Error if CreateJobObject used: NT 5.0+ only */ - -/* Error if OpenJobObject used: NT 5.0+ only */ - +/* Error if AccessCheckByTypeAndAuditAlarm used: NT 5.0+ only */ -/*----------------------------------------------------------------------*/ -/* Processing file COMMDLG.H */ -/*----------------------------------------------------------------------*/ +/* Error if AccessCheckByTypeResultListAndAuditAlarm used: NT 5.0+ only */ -BOOL -qxeGetOpenFileName (LPOPENFILENAMEW arg1) +BOOL +qxeObjectOpenAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, Extbyte * ObjectTypeName, Extbyte * ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted, LPBOOL GenerateOnClose) { if (XEUNICODE_P) - return GetOpenFileNameW (arg1); + return ObjectOpenAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, (LPWSTR) ObjectTypeName, (LPWSTR) ObjectName, pSecurityDescriptor, ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted, GenerateOnClose); else - return GetOpenFileNameA ((LPOPENFILENAMEA) arg1); + return ObjectOpenAuditAlarmA ((LPCSTR) SubsystemName, HandleId, (LPSTR) ObjectTypeName, (LPSTR) ObjectName, pSecurityDescriptor, ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted, GenerateOnClose); } -BOOL -qxeGetSaveFileName (LPOPENFILENAMEW arg1) +BOOL +qxeObjectPrivilegeAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, HANDLE ClientToken, DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted) { if (XEUNICODE_P) - return GetSaveFileNameW (arg1); + return ObjectPrivilegeAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, ClientToken, DesiredAccess, Privileges, AccessGranted); else - return GetSaveFileNameA ((LPOPENFILENAMEA) arg1); + return ObjectPrivilegeAuditAlarmA ((LPCSTR) SubsystemName, HandleId, ClientToken, DesiredAccess, Privileges, AccessGranted); } -short -qxeGetFileTitle (const Extbyte * arg1, Extbyte * arg2, WORD arg3) +BOOL +qxeObjectCloseAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, BOOL GenerateOnClose) { if (XEUNICODE_P) - return GetFileTitleW ((LPCWSTR) arg1, (LPWSTR) arg2, arg3); + return ObjectCloseAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, GenerateOnClose); else - return GetFileTitleA ((LPCSTR) arg1, (LPSTR) arg2, arg3); + return ObjectCloseAuditAlarmA ((LPCSTR) SubsystemName, HandleId, GenerateOnClose); } -BOOL -qxeChooseColor (LPCHOOSECOLORW arg1) +BOOL +qxeObjectDeleteAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, BOOL GenerateOnClose) { if (XEUNICODE_P) - return ChooseColorW (arg1); + return ObjectDeleteAuditAlarmW ((LPCWSTR) SubsystemName, HandleId, GenerateOnClose); else - return ChooseColorA ((LPCHOOSECOLORA) arg1); + return ObjectDeleteAuditAlarmA ((LPCSTR) SubsystemName, HandleId, GenerateOnClose); } -HWND -qxeFindText (LPFINDREPLACEW arg1) +BOOL +qxePrivilegedServiceAuditAlarm (const Extbyte * SubsystemName, const Extbyte * ServiceName, HANDLE ClientToken, PPRIVILEGE_SET Privileges, BOOL AccessGranted) { if (XEUNICODE_P) - return FindTextW (arg1); + return PrivilegedServiceAuditAlarmW ((LPCWSTR) SubsystemName, (LPCWSTR) ServiceName, ClientToken, Privileges, AccessGranted); else - return FindTextA ((LPFINDREPLACEA) arg1); + return PrivilegedServiceAuditAlarmA ((LPCSTR) SubsystemName, (LPCSTR) ServiceName, ClientToken, Privileges, AccessGranted); } -HWND -qxeReplaceText (LPFINDREPLACEW arg1) +BOOL +qxeSetFileSecurity (const Extbyte * lpFileName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { if (XEUNICODE_P) - return ReplaceTextW (arg1); + return SetFileSecurityW ((LPCWSTR) lpFileName, SecurityInformation, pSecurityDescriptor); else - return ReplaceTextA ((LPFINDREPLACEA) arg1); + return SetFileSecurityA ((LPCSTR) lpFileName, SecurityInformation, pSecurityDescriptor); } -/* Error if AfxReplaceText used: mac only */ - -/* Error if ChooseFont used: split-sized LPLOGFONT in LPCHOOSEFONT */ - -/* Skipping PrintDlg because LPPRINTDLG with split-sized DEVMODE handle */ - -/* Skipping PageSetupDlg because LPPAGESETUPDLG with split-sized DEVMODE handle */ - - -/*----------------------------------------------------------------------*/ -/* Processing file SHLOBJ.H */ -/*----------------------------------------------------------------------*/ - BOOL -qxeSHGetPathFromIDList (LPCITEMIDLIST pidl, Extbyte * pszPath) +qxeGetFileSecurity (const Extbyte * lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded) { if (XEUNICODE_P) - return SHGetPathFromIDListW (pidl, (LPWSTR) pszPath); + return GetFileSecurityW ((LPCWSTR) lpFileName, RequestedInformation, pSecurityDescriptor, nLength, lpnLengthNeeded); else - return SHGetPathFromIDListA (pidl, (LPSTR) pszPath); + return GetFileSecurityA ((LPCSTR) lpFileName, RequestedInformation, pSecurityDescriptor, nLength, lpnLengthNeeded); } -/* Skipping SHGetSpecialFolderPath because error in Cygwin prototype, missing from Cygwin libraries */ - -/* Skipping SHBrowseForFolder because need to intercept callback for SendMessage */ - -/* Skipping SHGetDataFromIDList because split-sized WIN32_FIND_DATA or split-simple NETRESOURCE, missing from Cygwin libraries */ - - -/*----------------------------------------------------------------------*/ -/* Processing file IME.H */ -/*----------------------------------------------------------------------*/ - -/* Error if SendIMEMessageEx used: obsolete, no docs available */ - +HANDLE +qxeFindFirstChangeNotification (const Extbyte * lpPathName, BOOL bWatchSubtree, DWORD dwNotifyFilter) +{ + if (XEUNICODE_P) + return FindFirstChangeNotificationW ((LPCWSTR) lpPathName, bWatchSubtree, dwNotifyFilter); + else + return FindFirstChangeNotificationA ((LPCSTR) lpPathName, bWatchSubtree, dwNotifyFilter); +} -/*----------------------------------------------------------------------*/ -/* Processing file WINGDI.H */ -/*----------------------------------------------------------------------*/ +/* Error if ReadDirectoryChanges used: Unicode-only */ -int -qxeAddFontResource (const Extbyte * arg1) +BOOL +qxeIsBadStringPtr (const Extbyte * lpsz, UINT ucchMax) { if (XEUNICODE_P) - return AddFontResourceW ((LPCWSTR) arg1); + return IsBadStringPtrW ((LPCWSTR) lpsz, ucchMax); else - return AddFontResourceA ((LPCSTR) arg1); + return IsBadStringPtrA ((LPCSTR) lpsz, ucchMax); } -HMETAFILE -qxeCopyMetaFile (HMETAFILE arg1, const Extbyte * arg2) +BOOL +qxeLookupAccountSid (const Extbyte * lpSystemName, PSID Sid, Extbyte * Name, LPDWORD cbName, Extbyte * ReferencedDomainName, LPDWORD cbReferencedDomainName, PSID_NAME_USE peUse) { if (XEUNICODE_P) - return CopyMetaFileW (arg1, (LPCWSTR) arg2); + return LookupAccountSidW ((LPCWSTR) lpSystemName, Sid, (LPWSTR) Name, cbName, (LPWSTR) ReferencedDomainName, cbReferencedDomainName, peUse); else - return CopyMetaFileA (arg1, (LPCSTR) arg2); + return LookupAccountSidA ((LPCSTR) lpSystemName, Sid, (LPSTR) Name, cbName, (LPSTR) ReferencedDomainName, cbReferencedDomainName, peUse); } -/* Skipping CreateDC because split-sized DEVMODE */ - -/* Skipping CreateFontIndirect because split-sized LOGFONT */ - -HFONT -qxeCreateFont (int arg1, int arg2, int arg3, int arg4, int arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD arg10, DWORD arg11, DWORD arg12, DWORD arg13, const Extbyte * arg14) +BOOL +qxeLookupAccountName (const Extbyte * lpSystemName, const Extbyte * lpAccountName, PSID Sid, LPDWORD cbSid, Extbyte * ReferencedDomainName, LPDWORD cbReferencedDomainName, PSID_NAME_USE peUse) { if (XEUNICODE_P) - return CreateFontW (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, (LPCWSTR) arg14); + return LookupAccountNameW ((LPCWSTR) lpSystemName, (LPCWSTR) lpAccountName, Sid, cbSid, (LPWSTR) ReferencedDomainName, cbReferencedDomainName, peUse); else - return CreateFontA (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, (LPCSTR) arg14); + return LookupAccountNameA ((LPCSTR) lpSystemName, (LPCSTR) lpAccountName, Sid, cbSid, (LPSTR) ReferencedDomainName, cbReferencedDomainName, peUse); } -/* Skipping CreateIC because split-sized DEVMODE */ - -HDC -qxeCreateMetaFile (const Extbyte * arg1) +BOOL +qxeLookupPrivilegeValue (const Extbyte * lpSystemName, const Extbyte * lpName, PLUID lpLuid) { if (XEUNICODE_P) - return CreateMetaFileW ((LPCWSTR) arg1); + return LookupPrivilegeValueW ((LPCWSTR) lpSystemName, (LPCWSTR) lpName, lpLuid); else - return CreateMetaFileA ((LPCSTR) arg1); + return LookupPrivilegeValueA ((LPCSTR) lpSystemName, (LPCSTR) lpName, lpLuid); } BOOL -qxeCreateScalableFontResource (DWORD arg1, const Extbyte * arg2, const Extbyte * arg3, const Extbyte * arg4) +qxeLookupPrivilegeName (const Extbyte * lpSystemName, PLUID lpLuid, Extbyte * lpName, LPDWORD cbName) { if (XEUNICODE_P) - return CreateScalableFontResourceW (arg1, (LPCWSTR) arg2, (LPCWSTR) arg3, (LPCWSTR) arg4); + return LookupPrivilegeNameW ((LPCWSTR) lpSystemName, lpLuid, (LPWSTR) lpName, cbName); else - return CreateScalableFontResourceA (arg1, (LPCSTR) arg2, (LPCSTR) arg3, (LPCSTR) arg4); + return LookupPrivilegeNameA ((LPCSTR) lpSystemName, lpLuid, (LPSTR) lpName, cbName); } -/* Skipping DeviceCapabilities because split-sized DEVMODE */ - -/* Skipping EnumFontFamiliesEx because split-complex FONTENUMPROC; NT 4.0+ only */ - -/* Error if EnumFontFamilies used: split-complex FONTENUMPROC */ - -/* Error if EnumFonts used: split-complex FONTENUMPROC */ - BOOL -qxeGetCharWidth (HDC arg1, UINT arg2, UINT arg3, LPINT arg4) +qxeLookupPrivilegeDisplayName (const Extbyte * lpSystemName, const Extbyte * lpName, Extbyte * lpDisplayName, LPDWORD cbDisplayName, LPDWORD lpLanguageId) { if (XEUNICODE_P) - return GetCharWidthW (arg1, arg2, arg3, arg4); + return LookupPrivilegeDisplayNameW ((LPCWSTR) lpSystemName, (LPCWSTR) lpName, (LPWSTR) lpDisplayName, cbDisplayName, lpLanguageId); else - return GetCharWidthA (arg1, arg2, arg3, arg4); + return LookupPrivilegeDisplayNameA ((LPCSTR) lpSystemName, (LPCSTR) lpName, (LPSTR) lpDisplayName, cbDisplayName, lpLanguageId); } BOOL -qxeGetCharWidth32 (HDC arg1, UINT arg2, UINT arg3, LPINT arg4) +qxeBuildCommDCB (const Extbyte * lpDef, LPDCB lpDCB) { if (XEUNICODE_P) - return GetCharWidth32W (arg1, arg2, arg3, arg4); + return BuildCommDCBW ((LPCWSTR) lpDef, lpDCB); else - return GetCharWidth32A (arg1, arg2, arg3, arg4); + return BuildCommDCBA ((LPCSTR) lpDef, lpDCB); } -BOOL -qxeGetCharWidthFloat (HDC arg1, UINT arg2, UINT arg3, PFLOAT arg4) +BOOL +qxeBuildCommDCBAndTimeouts (const Extbyte * lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts) { if (XEUNICODE_P) - return GetCharWidthFloatW (arg1, arg2, arg3, arg4); + return BuildCommDCBAndTimeoutsW ((LPCWSTR) lpDef, lpDCB, lpCommTimeouts); else - return GetCharWidthFloatA (arg1, arg2, arg3, arg4); + return BuildCommDCBAndTimeoutsA ((LPCSTR) lpDef, lpDCB, lpCommTimeouts); } -BOOL -qxeGetCharABCWidths (HDC arg1, UINT arg2, UINT arg3, LPABC arg4) +BOOL +qxeCommConfigDialog (const Extbyte * lpszName, HWND hWnd, LPCOMMCONFIG lpCC) { if (XEUNICODE_P) - return GetCharABCWidthsW (arg1, arg2, arg3, arg4); + return CommConfigDialogW ((LPCWSTR) lpszName, hWnd, lpCC); else - return GetCharABCWidthsA (arg1, arg2, arg3, arg4); + return CommConfigDialogA ((LPCSTR) lpszName, hWnd, lpCC); } -BOOL -qxeGetCharABCWidthsFloat (HDC arg1, UINT arg2, UINT arg3, LPABCFLOAT arg4) +BOOL +qxeGetDefaultCommConfig (const Extbyte * lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize) { if (XEUNICODE_P) - return GetCharABCWidthsFloatW (arg1, arg2, arg3, arg4); + return GetDefaultCommConfigW ((LPCWSTR) lpszName, lpCC, lpdwSize); else - return GetCharABCWidthsFloatA (arg1, arg2, arg3, arg4); + return GetDefaultCommConfigA ((LPCSTR) lpszName, lpCC, lpdwSize); } -DWORD -qxeGetGlyphOutline (HDC arg1, UINT arg2, UINT arg3, LPGLYPHMETRICS arg4, DWORD arg5, LPVOID arg6, CONST MAT2 * arg7) +BOOL +qxeSetDefaultCommConfig (const Extbyte * lpszName, LPCOMMCONFIG lpCC, DWORD dwSize) { if (XEUNICODE_P) - return GetGlyphOutlineW (arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return SetDefaultCommConfigW ((LPCWSTR) lpszName, lpCC, dwSize); else - return GetGlyphOutlineA (arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return SetDefaultCommConfigA ((LPCSTR) lpszName, lpCC, dwSize); } -HMETAFILE -qxeGetMetaFile (const Extbyte * arg1) +BOOL +qxeGetComputerName (Extbyte * lpBuffer, LPDWORD nSize) { if (XEUNICODE_P) - return GetMetaFileW ((LPCWSTR) arg1); + return GetComputerNameW ((LPWSTR) lpBuffer, nSize); else - return GetMetaFileA ((LPCSTR) arg1); + return GetComputerNameA ((LPSTR) lpBuffer, nSize); } -/* Error if GetOutlineTextMetrics used: split-sized LPOUTLINETEXTMETRIC */ - -BOOL -qxeGetTextExtentPoint (HDC arg1, const Extbyte * arg2, int arg3, LPSIZE arg4) +BOOL +qxeSetComputerName (const Extbyte * lpComputerName) { if (XEUNICODE_P) - return GetTextExtentPointW (arg1, (LPCWSTR) arg2, arg3, arg4); + return SetComputerNameW ((LPCWSTR) lpComputerName); else - return GetTextExtentPointA (arg1, (LPCSTR) arg2, arg3, arg4); + return SetComputerNameA ((LPCSTR) lpComputerName); } -BOOL -qxeGetTextExtentPoint32 (HDC arg1, const Extbyte * arg2, int arg3, LPSIZE arg4) +BOOL +qxeGetUserName (Extbyte * lpBuffer, LPDWORD nSize) { if (XEUNICODE_P) - return GetTextExtentPoint32W (arg1, (LPCWSTR) arg2, arg3, arg4); + return GetUserNameW ((LPWSTR) lpBuffer, nSize); else - return GetTextExtentPoint32A (arg1, (LPCSTR) arg2, arg3, arg4); + return GetUserNameA ((LPSTR) lpBuffer, nSize); } -BOOL -qxeGetTextExtentExPoint (HDC arg1, const Extbyte * arg2, int arg3, int arg4, LPINT arg5, LPINT arg6, LPSIZE arg7) +BOOL +qxeLogonUser (Extbyte * lpszUsername, Extbyte * lpszDomain, Extbyte * lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken) { if (XEUNICODE_P) - return GetTextExtentExPointW (arg1, (LPCWSTR) arg2, arg3, arg4, arg5, arg6, arg7); + return LogonUserW ((LPWSTR) lpszUsername, (LPWSTR) lpszDomain, (LPWSTR) lpszPassword, dwLogonType, dwLogonProvider, phToken); else - return GetTextExtentExPointA (arg1, (LPCSTR) arg2, arg3, arg4, arg5, arg6, arg7); + return LogonUserA ((LPSTR) lpszUsername, (LPSTR) lpszDomain, (LPSTR) lpszPassword, dwLogonType, dwLogonProvider, phToken); } -/* NOTE: NT 4.0+ only */ -DWORD -qxeGetCharacterPlacement (HDC arg1, const Extbyte * arg2, int arg3, int arg4, LPGCP_RESULTSW arg5, DWORD arg6) +BOOL +qxeCreateProcessAsUser (HANDLE hToken, const Extbyte * lpApplicationName, Extbyte * lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, const Extbyte * lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { if (XEUNICODE_P) - return GetCharacterPlacementW (arg1, (LPCWSTR) arg2, arg3, arg4, arg5, arg6); + return CreateProcessAsUserW (hToken, (LPCWSTR) lpApplicationName, (LPWSTR) lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, (LPCWSTR) lpCurrentDirectory, lpStartupInfo, lpProcessInformation); else - return GetCharacterPlacementA (arg1, (LPCSTR) arg2, arg3, arg4, (LPGCP_RESULTSA) arg5, arg6); + return CreateProcessAsUserA (hToken, (LPCSTR) lpApplicationName, (LPSTR) lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, (LPCSTR) lpCurrentDirectory, (LPSTARTUPINFOA) lpStartupInfo, lpProcessInformation); } -/* Error if GetGlyphIndices used: NT 5.0+ only */ +/* Error if GetCurrentHwProfile used: split-sized LPHW_PROFILE_INFO; NT 4.0+ only */ -/* Error if AddFontResourceEx used: NT 5.0+ only */ +/* Error if GetVersionEx used: split-sized LPOSVERSIONINFO */ -/* Error if RemoveFontResourceEx used: NT 5.0+ only */ +/* Error if CreateJobObject used: NT 5.0+ only */ -/* Error if CreateFontIndirectEx used: split-sized ENUMLOGFONTEXDV; NT 5.0+ only */ +/* Error if OpenJobObject used: NT 5.0+ only */ -/* Skipping ResetDC because split-sized DEVMODE */ + +/*----------------------------------------------------------------------*/ +/* Processing file MMSYSTEM.H */ +/*----------------------------------------------------------------------*/ BOOL -qxeRemoveFontResource (const Extbyte * arg1) +qxesndPlaySound (const Extbyte * pszSound, UINT fuSound) { if (XEUNICODE_P) - return RemoveFontResourceW ((LPCWSTR) arg1); + return sndPlaySoundW ((LPCWSTR) pszSound, fuSound); else - return RemoveFontResourceA ((LPCSTR) arg1); + return sndPlaySoundA ((LPCSTR) pszSound, fuSound); } -HENHMETAFILE -qxeCopyEnhMetaFile (HENHMETAFILE arg1, const Extbyte * arg2) +BOOL +qxePlaySound (const Extbyte * pszSound, HMODULE hmod, DWORD fdwSound) { if (XEUNICODE_P) - return CopyEnhMetaFileW (arg1, (LPCWSTR) arg2); + return PlaySoundW ((LPCWSTR) pszSound, hmod, fdwSound); else - return CopyEnhMetaFileA (arg1, (LPCSTR) arg2); + return PlaySoundA ((LPCSTR) pszSound, hmod, fdwSound); } -HDC -qxeCreateEnhMetaFile (HDC arg1, const Extbyte * arg2, CONST RECT * arg3, const Extbyte * arg4) +/* Error if waveOutGetDevCaps used: split-sized LPWAVEOUTCAPS */ + +MMRESULT +qxewaveOutGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText) { if (XEUNICODE_P) - return CreateEnhMetaFileW (arg1, (LPCWSTR) arg2, arg3, (LPCWSTR) arg4); + return waveOutGetErrorTextW (mmrError, (LPWSTR) pszText, cchText); else - return CreateEnhMetaFileA (arg1, (LPCSTR) arg2, arg3, (LPCSTR) arg4); + return waveOutGetErrorTextA (mmrError, (LPSTR) pszText, cchText); } -HENHMETAFILE -qxeGetEnhMetaFile (const Extbyte * arg1) +/* Error if waveInGetDevCaps used: split-sized LPWAVEINCAPS */ + +MMRESULT +qxewaveInGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText) { if (XEUNICODE_P) - return GetEnhMetaFileW ((LPCWSTR) arg1); + return waveInGetErrorTextW (mmrError, (LPWSTR) pszText, cchText); else - return GetEnhMetaFileA ((LPCSTR) arg1); + return waveInGetErrorTextA (mmrError, (LPSTR) pszText, cchText); } -UINT -qxeGetEnhMetaFileDescription (HENHMETAFILE arg1, UINT arg2, Extbyte * arg3) +/* Error if midiOutGetDevCaps used: split-sized LPMIDIOUTCAPS */ + +MMRESULT +qxemidiOutGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText) { if (XEUNICODE_P) - return GetEnhMetaFileDescriptionW (arg1, arg2, (LPWSTR) arg3); + return midiOutGetErrorTextW (mmrError, (LPWSTR) pszText, cchText); else - return GetEnhMetaFileDescriptionA (arg1, arg2, (LPSTR) arg3); + return midiOutGetErrorTextA (mmrError, (LPSTR) pszText, cchText); } -/* Skipping GetTextMetrics because split-sized LPTEXTMETRIC */ +/* Error if midiInGetDevCaps used: split-sized LPMIDIOUTCAPS */ -int -qxeStartDoc (HDC arg1, CONST DOCINFOW * arg2) +MMRESULT +qxemidiInGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText) { if (XEUNICODE_P) - return StartDocW (arg1, arg2); + return midiInGetErrorTextW (mmrError, (LPWSTR) pszText, cchText); else - return StartDocA (arg1, (CONST DOCINFOA *) arg2); + return midiInGetErrorTextA (mmrError, (LPSTR) pszText, cchText); } -/* Skipping GetObject because split-sized LOGFONT */ +/* Error if auxGetDevCaps used: split-sized LPAUXCAPS */ -BOOL -qxeTextOut (HDC arg1, int arg2, int arg3, const Extbyte * arg4, int arg5) +/* Error if mixerGetDevCaps used: split-sized LPMIXERCAPS */ + +/* Error if mixerGetLineInfo used: split-sized LPMIXERLINE */ + +/* Error if mixerGetLineControls used: split-sized LPMIXERCONTROL */ + +/* Error if mixerGetControlDetails used: split-sized LPMIXERCONTROL in LPMIXERLINECONTROLS in LPMIXERCONTROLDETAILS */ + +/* Error if joyGetDevCaps used: split-sized LPJOYCAPS */ + +FOURCC +qxemmioStringToFOURCC (const Extbyte * sz, UINT uFlags) { if (XEUNICODE_P) - return TextOutW (arg1, arg2, arg3, (LPCWSTR) arg4, arg5); + return mmioStringToFOURCCW ((LPCWSTR) sz, uFlags); else - return TextOutA (arg1, arg2, arg3, (LPCSTR) arg4, arg5); + return mmioStringToFOURCCA ((LPCSTR) sz, uFlags); } -BOOL -qxeExtTextOut (HDC arg1, int arg2, int arg3, UINT arg4, CONST RECT * arg5, const Extbyte * arg6, UINT arg7, CONST INT * arg8) +LPMMIOPROC +qxemmioInstallIOProc (FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags) { if (XEUNICODE_P) - return ExtTextOutW (arg1, arg2, arg3, arg4, arg5, (LPCWSTR) arg6, arg7, arg8); + return mmioInstallIOProcW (fccIOProc, pIOProc, dwFlags); else - return ExtTextOutA (arg1, arg2, arg3, arg4, arg5, (LPCSTR) arg6, arg7, arg8); + return mmioInstallIOProcA (fccIOProc, pIOProc, dwFlags); } -BOOL -qxePolyTextOut (HDC arg1, CONST POLYTEXTW * arg2, int arg3) +HMMIO +qxemmioOpen (Extbyte * pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen) { if (XEUNICODE_P) - return PolyTextOutW (arg1, arg2, arg3); + return mmioOpenW ((LPWSTR) pszFileName, pmmioinfo, fdwOpen); else - return PolyTextOutA (arg1, (CONST POLYTEXTA *) arg2, arg3); + return mmioOpenA ((LPSTR) pszFileName, pmmioinfo, fdwOpen); } -int -qxeGetTextFace (HDC arg1, int arg2, Extbyte * arg3) +MMRESULT +qxemmioRename (const Extbyte * pszFileName, const Extbyte * pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename) { if (XEUNICODE_P) - return GetTextFaceW (arg1, arg2, (LPWSTR) arg3); + return mmioRenameW ((LPCWSTR) pszFileName, (LPCWSTR) pszNewFileName, pmmioinfo, fdwRename); else - return GetTextFaceA (arg1, arg2, (LPSTR) arg3); + return mmioRenameA ((LPCSTR) pszFileName, (LPCSTR) pszNewFileName, pmmioinfo, fdwRename); } -DWORD -qxeGetKerningPairs (HDC arg1, DWORD arg2, LPKERNINGPAIR arg3) +MCIERROR +qxemciSendCommand (MCIDEVICEID mciId, UINT uMsg, DWORD dwParam1, DWORD dwParam2) { if (XEUNICODE_P) - return GetKerningPairsW (arg1, arg2, arg3); + return mciSendCommandW (mciId, uMsg, dwParam1, dwParam2); else - return GetKerningPairsA (arg1, arg2, arg3); + return mciSendCommandA (mciId, uMsg, dwParam1, dwParam2); } -/* Error if GetLogColorSpace used: split-sized LPLOGCOLORSPACE; NT 4.0+ only */ - -/* Error if CreateColorSpace used: split-sized LPLOGCOLORSPACE; NT 4.0+ only */ - -/* Skipping GetICMProfile because NT 4.0+ only, error in Cygwin prototype */ - -/* NOTE: NT 4.0+ only */ -BOOL -qxeSetICMProfile (HDC arg1, Extbyte * arg2) +MCIERROR +qxemciSendString (const Extbyte * lpstrCommand, Extbyte * lpstrReturnString, UINT uReturnLength, HWND hwndCallback) { if (XEUNICODE_P) - return SetICMProfileW (arg1, (LPWSTR) arg2); + return mciSendStringW ((LPCWSTR) lpstrCommand, (LPWSTR) lpstrReturnString, uReturnLength, hwndCallback); else - return SetICMProfileA (arg1, (LPSTR) arg2); + return mciSendStringA ((LPCSTR) lpstrCommand, (LPSTR) lpstrReturnString, uReturnLength, hwndCallback); } -/* NOTE: NT 4.0+ only */ -int -qxeEnumICMProfiles (HDC arg1, ICMENUMPROCW arg2, LPARAM arg3) +MCIDEVICEID +qxemciGetDeviceID (const Extbyte * pszDevice) { if (XEUNICODE_P) - return EnumICMProfilesW (arg1, arg2, arg3); + return mciGetDeviceIDW ((LPCWSTR) pszDevice); else - return EnumICMProfilesA (arg1, (ICMENUMPROCA) arg2, arg3); + return mciGetDeviceIDA ((LPCSTR) pszDevice); } -/* Skipping UpdateICMRegKey because NT 4.0+ only, error in Cygwin prototype */ +#if !defined (MINGW) -/* Error if wglUseFontBitmaps used: causes link error */ +/* Error if mciGetDeviceIDFromElementID used: missing from Win98se version of ADVAPI32.dll */ -/* Error if wglUseFontOutlines used: causes link error */ +#endif /* !defined (MINGW) */ + +BOOL +qxemciGetErrorString (MCIERROR mcierr, Extbyte * pszText, UINT cchText) +{ + if (XEUNICODE_P) + return mciGetErrorStringW (mcierr, (LPWSTR) pszText, cchText); + else + return mciGetErrorStringA (mcierr, (LPSTR) pszText, cchText); +} diff --text -u 'xemacs-21.5.18/src/intl-auto-encap-win32.h' 'xemacs-21.5.19/src/intl-auto-encap-win32.h' Index: ./src/intl-auto-encap-win32.h --- ./src/intl-auto-encap-win32.h Tue Sep 16 05:21:47 2003 +++ ./src/intl-auto-encap-win32.h Tue Jan 25 08:34:00 2005 @@ -3,70 +3,192 @@ */ -/* Processing file WINNLS.H */ +/* Processing file WINCON.H */ -#undef GetCPInfoEx -#define GetCPInfoEx error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef PeekConsoleInput +#define PeekConsoleInput error_use_qxePeekConsoleInput_or_PeekConsoleInputA_and_PeekConsoleInputW +#endif +BOOL qxePeekConsoleInput (HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead); -#undef CompareString -#define CompareString error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ReadConsoleInput +#define ReadConsoleInput error_use_qxeReadConsoleInput_or_ReadConsoleInputA_and_ReadConsoleInputW +#endif +BOOL qxeReadConsoleInput (HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead); -#undef LCMapString -#define LCMapString error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef WriteConsoleInput +#define WriteConsoleInput error_use_qxeWriteConsoleInput_or_WriteConsoleInputA_and_WriteConsoleInputW +#endif +BOOL qxeWriteConsoleInput (HANDLE hConsoleInput, CONST INPUT_RECORD * lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetLocaleInfo -#define GetLocaleInfo error use qxeGetLocaleInfo or GetLocaleInfoA/GetLocaleInfoW +#undef ReadConsoleOutput +#define ReadConsoleOutput error_use_qxeReadConsoleOutput_or_ReadConsoleOutputA_and_ReadConsoleOutputW #endif -int qxeGetLocaleInfo (LCID Locale, LCTYPE LCType, Extbyte * lpLCData, int cchData); +BOOL qxeReadConsoleOutput (HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetLocaleInfo -#define SetLocaleInfo error use qxeSetLocaleInfo or SetLocaleInfoA/SetLocaleInfoW +#undef WriteConsoleOutput +#define WriteConsoleOutput error_use_qxeWriteConsoleOutput_or_WriteConsoleOutputA_and_WriteConsoleOutputW #endif -BOOL qxeSetLocaleInfo (LCID Locale, LCTYPE LCType, const Extbyte * lpLCData); +BOOL qxeWriteConsoleOutput (HANDLE hConsoleOutput, CONST CHAR_INFO * lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion); -#undef GetTimeFormat -#define GetTimeFormat error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ReadConsoleOutputCharacter +#define ReadConsoleOutputCharacter error_use_qxeReadConsoleOutputCharacter_or_ReadConsoleOutputCharacterA_and_ReadConsoleOutputCharacterW +#endif +BOOL qxeReadConsoleOutputCharacter (HANDLE hConsoleOutput, Extbyte * lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead); -#undef GetDateFormat -#define GetDateFormat error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef WriteConsoleOutputCharacter +#define WriteConsoleOutputCharacter error_use_qxeWriteConsoleOutputCharacter_or_WriteConsoleOutputCharacterA_and_WriteConsoleOutputCharacterW +#endif +BOOL qxeWriteConsoleOutputCharacter (HANDLE hConsoleOutput, const Extbyte * lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten); -#undef GetNumberFormat -#define GetNumberFormat error not used, not examined yet +#undef FillConsoleOutputCharacter +#define FillConsoleOutputCharacter error_split_CHAR -#undef GetCurrencyFormat -#define GetCurrencyFormat error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ScrollConsoleScreenBuffer +#define ScrollConsoleScreenBuffer error_use_qxeScrollConsoleScreenBuffer_or_ScrollConsoleScreenBufferA_and_ScrollConsoleScreenBufferW +#endif +BOOL qxeScrollConsoleScreenBuffer (HANDLE hConsoleOutput, CONST SMALL_RECT * lpScrollRectangle, CONST SMALL_RECT * lpClipRectangle, COORD dwDestinationOrigin, CONST CHAR_INFO * lpFill); -#undef EnumCalendarInfo -#define EnumCalendarInfo error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef GetConsoleTitle +#define GetConsoleTitle error_use_qxeGetConsoleTitle_or_GetConsoleTitleA_and_GetConsoleTitleW +#endif +DWORD qxeGetConsoleTitle (Extbyte * lpConsoleTitle, DWORD nSize); -#undef EnumCalendarInfoEx -#define EnumCalendarInfoEx error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef SetConsoleTitle +#define SetConsoleTitle error_use_qxeSetConsoleTitle_or_SetConsoleTitleA_and_SetConsoleTitleW +#endif +BOOL qxeSetConsoleTitle (const Extbyte * lpConsoleTitle); -#undef EnumTimeFormats -#define EnumTimeFormats error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ReadConsole +#define ReadConsole error_use_qxeReadConsole_or_ReadConsoleA_and_ReadConsoleW +#endif +BOOL qxeReadConsole (HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved); -#undef EnumDateFormats -#define EnumDateFormats error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef WriteConsole +#define WriteConsole error_use_qxeWriteConsole_or_WriteConsoleA_and_WriteConsoleW +#endif +BOOL qxeWriteConsole (HANDLE hConsoleOutput, CONST VOID * lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved); -#undef EnumDateFormatsEx -#define EnumDateFormatsEx error not used, not examined yet -#undef GetStringTypeEx -#define GetStringTypeEx error not used, not examined yet +/* Processing file SHELLAPI.H */ -#undef GetStringType -#define GetStringType error no such fun; A and W versions have different nos. of args +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef DragQueryFile +#define DragQueryFile error_use_qxeDragQueryFile_or_DragQueryFileA_and_DragQueryFileW +#endif +UINT qxeDragQueryFile (HDROP arg1, UINT arg2, Extbyte * arg3, UINT arg4); -#undef FoldString -#define FoldString error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ShellExecute +#define ShellExecute error_use_qxeShellExecute_or_ShellExecuteA_and_ShellExecuteW +#endif +HINSTANCE qxeShellExecute (HWND hwnd, const Extbyte * lpOperation, const Extbyte * lpFile, const Extbyte * lpParameters, const Extbyte * lpDirectory, INT nShowCmd); -#undef EnumSystemLocales -#define EnumSystemLocales error not used, not examined yet +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef FindExecutable +#define FindExecutable error_use_qxeFindExecutable_or_FindExecutableA_and_FindExecutableW +#endif +HINSTANCE qxeFindExecutable (const Extbyte * lpFile, const Extbyte * lpDirectory, Extbyte * lpResult); -#undef EnumSystemCodePages -#define EnumSystemCodePages error not used, not examined yet +#undef CommandLineToArgv +#define CommandLineToArgv error_Unicode_only + +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ShellAbout +#define ShellAbout error_use_qxeShellAbout_or_ShellAboutA_and_ShellAboutW +#endif +INT qxeShellAbout (HWND hWnd, const Extbyte * szApp, const Extbyte * szOtherStuff, HICON hIcon); + +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ExtractAssociatedIcon +#define ExtractAssociatedIcon error_use_qxeExtractAssociatedIcon_or_ExtractAssociatedIconA_and_ExtractAssociatedIconW +#endif +HICON qxeExtractAssociatedIcon (HINSTANCE hInst, Extbyte * lpIconPath, LPWORD lpiIcon); + +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ExtractIcon +#define ExtractIcon error_use_qxeExtractIcon_or_ExtractIconA_and_ExtractIconW +#endif +HICON qxeExtractIcon (HINSTANCE hInst, const Extbyte * lpszExeFileName, UINT nIconIndex); + +#if !defined (CYGWIN_HEADERS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef DoEnvironmentSubst +#define DoEnvironmentSubst error_use_qxeDoEnvironmentSubst_or_DoEnvironmentSubstA_and_DoEnvironmentSubstW +#endif +DWORD qxeDoEnvironmentSubst (Extbyte * szString, UINT cbString); +#endif /* !defined (CYGWIN_HEADERS) */ + +#undef FindEnvironmentString +#define FindEnvironmentString error_causes_link_error__NT_4_0__only + +/* Skipping ExtractIconEx because NT 4.0+ only, error in Cygwin prototype */ + +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef SHFileOperation +#define SHFileOperation error_use_qxeSHFileOperation_or_SHFileOperationA_and_SHFileOperationW +#endif +int qxeSHFileOperation (LPSHFILEOPSTRUCTW lpFileOp); + +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ShellExecuteEx +#define ShellExecuteEx error_use_qxeShellExecuteEx_or_ShellExecuteExA_and_ShellExecuteExW +#endif +BOOL qxeShellExecuteEx (LPSHELLEXECUTEINFOW lpExecInfo); + +#undef WinExecError +#define WinExecError error_causes_link_error__NT_4_0__only + +#if !defined (CYGWIN_HEADERS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef SHQueryRecycleBin +#define SHQueryRecycleBin error_use_qxeSHQueryRecycleBin_or_SHQueryRecycleBinA_and_SHQueryRecycleBinW +#endif +HRESULT qxeSHQueryRecycleBin (const Extbyte * pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo); +#endif /* !defined (CYGWIN_HEADERS) */ + +#if !defined (CYGWIN_HEADERS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef SHEmptyRecycleBin +#define SHEmptyRecycleBin error_use_qxeSHEmptyRecycleBin_or_SHEmptyRecycleBinA_and_SHEmptyRecycleBinW +#endif +HRESULT qxeSHEmptyRecycleBin (HWND hwnd, const Extbyte * pszRootPath, DWORD dwFlags); +#endif /* !defined (CYGWIN_HEADERS) */ + +#undef Shell_NotifyIcon +#define Shell_NotifyIcon error_split_sized_NOTIFYICONDATA__NT_4_0__only + +/* Skipping SHGetFileInfo because split-sized SHFILEINFO, NT 4.0+ only */ + +#undef SHGetDiskFreeSpace +#define SHGetDiskFreeSpace error_causes_link_error__NT_4_0__only + +#if !defined (CYGWIN_HEADERS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef SHGetNewLinkInfo +#define SHGetNewLinkInfo error_use_qxeSHGetNewLinkInfo_or_SHGetNewLinkInfoA_and_SHGetNewLinkInfoW +#endif +BOOL qxeSHGetNewLinkInfo (const Extbyte * pszLinkTo, const Extbyte * pszDir, Extbyte * pszName, BOOL * pfMustCopy, UINT uFlags); +#endif /* !defined (CYGWIN_HEADERS) */ + +#if !defined (CYGWIN_HEADERS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef SHInvokePrinterCommand +#define SHInvokePrinterCommand error_use_qxeSHInvokePrinterCommand_or_SHInvokePrinterCommandA_and_SHInvokePrinterCommandW +#endif +BOOL qxeSHInvokePrinterCommand (HWND hwnd, UINT uAction, const Extbyte * lpBuf1, const Extbyte * lpBuf2, BOOL fModal); +#endif /* !defined (CYGWIN_HEADERS) */ /* Processing file WINSPOOL.H */ @@ -74,7 +196,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef EnumPrinters -#define EnumPrinters error use qxeEnumPrinters or EnumPrintersA/EnumPrintersW +#define EnumPrinters error_use_qxeEnumPrinters_or_EnumPrintersA_and_EnumPrintersW #endif BOOL qxeEnumPrinters (DWORD Flags, Extbyte * Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -85,122 +207,122 @@ #if defined (HAVE_MS_WINDOWS) #undef ResetPrinter -#define ResetPrinter error split-sized DEVMODE pointer in split PRINTER_DEFAULTS +#define ResetPrinter error_split_sized_DEVMODE_pointer_in_split_PRINTER_DEFAULTS #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef SetJob -#define SetJob error split-sized DEVMODE pointer in split JOB_INFO_2 +#define SetJob error_split_sized_DEVMODE_pointer_in_split_JOB_INFO_2 #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetJob -#define GetJob error split-sized DEVMODE pointer in split JOB_INFO_2 +#define GetJob error_split_sized_DEVMODE_pointer_in_split_JOB_INFO_2 #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumJobs -#define EnumJobs error split-sized DEVMODE pointer in split JOB_INFO_2 +#define EnumJobs error_split_sized_DEVMODE_pointer_in_split_JOB_INFO_2 #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddPrinter -#define AddPrinter error split-sized DEVMODE pointer in split PRINTER_INFO_2 +#define AddPrinter error_split_sized_DEVMODE_pointer_in_split_PRINTER_INFO_2 #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef SetPrinter -#define SetPrinter error split-sized DEVMODE pointer in split PRINTER_INFO_2 +#define SetPrinter error_split_sized_DEVMODE_pointer_in_split_PRINTER_INFO_2 #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetPrinter -#define GetPrinter error split-sized DEVMODE pointer in split PRINTER_INFO_2 +#define GetPrinter error_split_sized_DEVMODE_pointer_in_split_PRINTER_INFO_2 #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddPrinterDriver -#define AddPrinterDriver error not used, complicated interface with split structures +#define AddPrinterDriver error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddPrinterDriverEx -#define AddPrinterDriverEx error not used, complicated interface with split structures +#define AddPrinterDriverEx error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumPrinterDrivers -#define EnumPrinterDrivers error not used, complicated interface with split structures +#define EnumPrinterDrivers error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetPrinterDriver -#define GetPrinterDriver error not used, complicated interface with split structures +#define GetPrinterDriver error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetPrinterDriverDirectory -#define GetPrinterDriverDirectory error not used, complicated interface with split structures +#define GetPrinterDriverDirectory error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePrinterDriver -#define DeletePrinterDriver error not used, complicated interface with split structures +#define DeletePrinterDriver error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePrinterDriverEx -#define DeletePrinterDriverEx error not used, complicated interface with split structures +#define DeletePrinterDriverEx error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddPerMachineConnection -#define AddPerMachineConnection error not used, complicated interface with split structures +#define AddPerMachineConnection error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePerMachineConnection -#define DeletePerMachineConnection error not used, complicated interface with split structures +#define DeletePerMachineConnection error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumPerMachineConnections -#define EnumPerMachineConnections error not used, complicated interface with split structures +#define EnumPerMachineConnections error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddPrintProcessor -#define AddPrintProcessor error not used, complicated interface with split structures +#define AddPrintProcessor error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumPrintProcessors -#define EnumPrintProcessors error not used, complicated interface with split structures +#define EnumPrintProcessors error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetPrintProcessorDirectory -#define GetPrintProcessorDirectory error not used, complicated interface with split structures +#define GetPrintProcessorDirectory error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumPrintProcessorDatatypes -#define EnumPrintProcessorDatatypes error not used, complicated interface with split structures +#define EnumPrintProcessorDatatypes error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePrintProcessor -#define DeletePrintProcessor error not used, complicated interface with split structures +#define DeletePrintProcessor error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef StartDocPrinter -#define StartDocPrinter error not used, complicated interface with split structures +#define StartDocPrinter error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddJob -#define AddJob error not used, complicated interface with split structures +#define AddJob error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) @@ -209,162 +331,162 @@ #if defined (HAVE_MS_WINDOWS) #undef AdvancedDocumentProperties -#define AdvancedDocumentProperties error not used, complicated interface with split structures +#define AdvancedDocumentProperties error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetPrinterData -#define GetPrinterData error not used, complicated interface with split structures +#define GetPrinterData error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetPrinterDataEx -#define GetPrinterDataEx error not used, complicated interface with split structures +#define GetPrinterDataEx error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumPrinterData -#define EnumPrinterData error not used, complicated interface with split structures +#define EnumPrinterData error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumPrinterDataEx -#define EnumPrinterDataEx error not used, complicated interface with split structures +#define EnumPrinterDataEx error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumPrinterKey -#define EnumPrinterKey error not used, complicated interface with split structures +#define EnumPrinterKey error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef SetPrinterData -#define SetPrinterData error not used, complicated interface with split structures +#define SetPrinterData error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef SetPrinterDataEx -#define SetPrinterDataEx error not used, complicated interface with split structures +#define SetPrinterDataEx error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePrinterData -#define DeletePrinterData error not used, complicated interface with split structures +#define DeletePrinterData error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePrinterDataEx -#define DeletePrinterDataEx error not used, complicated interface with split structures +#define DeletePrinterDataEx error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePrinterKey -#define DeletePrinterKey error not used, complicated interface with split structures +#define DeletePrinterKey error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef PrinterMessageBox -#define PrinterMessageBox error not used, complicated interface with split structures +#define PrinterMessageBox error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddForm -#define AddForm error not used, complicated interface with split structures +#define AddForm error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeleteForm -#define DeleteForm error not used, complicated interface with split structures +#define DeleteForm error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetForm -#define GetForm error not used, complicated interface with split structures +#define GetForm error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef SetForm -#define SetForm error not used, complicated interface with split structures +#define SetForm error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumForms -#define EnumForms error not used, complicated interface with split structures +#define EnumForms error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumMonitors -#define EnumMonitors error not used, complicated interface with split structures +#define EnumMonitors error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddMonitor -#define AddMonitor error not used, complicated interface with split structures +#define AddMonitor error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeleteMonitor -#define DeleteMonitor error not used, complicated interface with split structures +#define DeleteMonitor error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef EnumPorts -#define EnumPorts error not used, complicated interface with split structures +#define EnumPorts error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddPort -#define AddPort error not used, complicated interface with split structures +#define AddPort error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef ConfigurePort -#define ConfigurePort error not used, complicated interface with split structures +#define ConfigurePort error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePort -#define DeletePort error not used, complicated interface with split structures +#define DeletePort error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef XcvData -#define XcvData error not used, complicated interface with split structures +#define XcvData error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef SetPort -#define SetPort error not used, complicated interface with split structures +#define SetPort error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddPrinterConnection -#define AddPrinterConnection error not used, complicated interface with split structures +#define AddPrinterConnection error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePrinterConnection -#define DeletePrinterConnection error not used, complicated interface with split structures +#define DeletePrinterConnection error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef AddPrintProvidor -#define AddPrintProvidor error not used, complicated interface with split structures +#define AddPrintProvidor error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef DeletePrintProvidor -#define DeletePrintProvidor error not used, complicated interface with split structures +#define DeletePrintProvidor error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef SetPrinterHTMLView -#define SetPrinterHTMLView error not used, complicated interface with split structures +#define SetPrinterHTMLView error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ #if defined (HAVE_MS_WINDOWS) #undef GetPrinterHTMLView -#define GetPrinterHTMLView error not used, complicated interface with split structures +#define GetPrinterHTMLView error_not_used__complicated_interface_with_split_structures #endif /* defined (HAVE_MS_WINDOWS) */ @@ -373,7 +495,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetAddConnection -#define WNetAddConnection error use qxeWNetAddConnection or WNetAddConnectionA/WNetAddConnectionW +#define WNetAddConnection error_use_qxeWNetAddConnection_or_WNetAddConnectionA_and_WNetAddConnectionW #endif DWORD qxeWNetAddConnection (const Extbyte * lpRemoteName, const Extbyte * lpPassword, const Extbyte * lpLocalName); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -381,7 +503,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetAddConnection2 -#define WNetAddConnection2 error use qxeWNetAddConnection2 or WNetAddConnection2A/WNetAddConnection2W +#define WNetAddConnection2 error_use_qxeWNetAddConnection2_or_WNetAddConnection2A_and_WNetAddConnection2W #endif DWORD qxeWNetAddConnection2 (LPNETRESOURCEW lpNetResource, const Extbyte * lpPassword, const Extbyte * lpUserName, DWORD dwFlags); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -389,7 +511,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetAddConnection3 -#define WNetAddConnection3 error use qxeWNetAddConnection3 or WNetAddConnection3A/WNetAddConnection3W +#define WNetAddConnection3 error_use_qxeWNetAddConnection3_or_WNetAddConnection3A_and_WNetAddConnection3W #endif DWORD qxeWNetAddConnection3 (HWND hwndOwner, LPNETRESOURCEW lpNetResource, const Extbyte * lpPassword, const Extbyte * lpUserName, DWORD dwFlags); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -397,7 +519,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetCancelConnection -#define WNetCancelConnection error use qxeWNetCancelConnection or WNetCancelConnectionA/WNetCancelConnectionW +#define WNetCancelConnection error_use_qxeWNetCancelConnection_or_WNetCancelConnectionA_and_WNetCancelConnectionW #endif DWORD qxeWNetCancelConnection (const Extbyte * lpName, BOOL fForce); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -405,7 +527,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetCancelConnection2 -#define WNetCancelConnection2 error use qxeWNetCancelConnection2 or WNetCancelConnection2A/WNetCancelConnection2W +#define WNetCancelConnection2 error_use_qxeWNetCancelConnection2_or_WNetCancelConnection2A_and_WNetCancelConnection2W #endif DWORD qxeWNetCancelConnection2 (const Extbyte * lpName, DWORD dwFlags, BOOL fForce); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -413,7 +535,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetGetConnection -#define WNetGetConnection error use qxeWNetGetConnection or WNetGetConnectionA/WNetGetConnectionW +#define WNetGetConnection error_use_qxeWNetGetConnection_or_WNetGetConnectionA_and_WNetGetConnectionW #endif DWORD qxeWNetGetConnection (const Extbyte * lpLocalName, Extbyte * lpRemoteName, LPDWORD lpnLength); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -421,7 +543,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetUseConnection -#define WNetUseConnection error use qxeWNetUseConnection or WNetUseConnectionA/WNetUseConnectionW +#define WNetUseConnection error_use_qxeWNetUseConnection_or_WNetUseConnectionA_and_WNetUseConnectionW #endif DWORD qxeWNetUseConnection (HWND hwndOwner, LPNETRESOURCEW lpNetResource, const Extbyte * lpUserID, const Extbyte * lpPassword, DWORD dwFlags, Extbyte * lpAccessName, LPDWORD lpBufferSize, LPDWORD lpResult); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -429,7 +551,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetConnectionDialog1 -#define WNetConnectionDialog1 error use qxeWNetConnectionDialog1 or WNetConnectionDialog1A/WNetConnectionDialog1W +#define WNetConnectionDialog1 error_use_qxeWNetConnectionDialog1_or_WNetConnectionDialog1A_and_WNetConnectionDialog1W #endif DWORD qxeWNetConnectionDialog1 (LPCONNECTDLGSTRUCTW lpConnDlgStruct); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -437,7 +559,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetDisconnectDialog1 -#define WNetDisconnectDialog1 error use qxeWNetDisconnectDialog1 or WNetDisconnectDialog1A/WNetDisconnectDialog1W +#define WNetDisconnectDialog1 error_use_qxeWNetDisconnectDialog1_or_WNetDisconnectDialog1A_and_WNetDisconnectDialog1W #endif DWORD qxeWNetDisconnectDialog1 (LPDISCDLGSTRUCTW lpConnDlgStruct); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -445,7 +567,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetOpenEnum -#define WNetOpenEnum error use qxeWNetOpenEnum or WNetOpenEnumA/WNetOpenEnumW +#define WNetOpenEnum error_use_qxeWNetOpenEnum_or_WNetOpenEnumA_and_WNetOpenEnumW #endif DWORD qxeWNetOpenEnum (DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNetResource, LPHANDLE lphEnum); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -453,7 +575,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetEnumResource -#define WNetEnumResource error use qxeWNetEnumResource or WNetEnumResourceA/WNetEnumResourceW +#define WNetEnumResource error_use_qxeWNetEnumResource_or_WNetEnumResourceA_and_WNetEnumResourceW #endif DWORD qxeWNetEnumResource (HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -461,7 +583,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetGetUniversalName -#define WNetGetUniversalName error use qxeWNetGetUniversalName or WNetGetUniversalNameA/WNetGetUniversalNameW +#define WNetGetUniversalName error_use_qxeWNetGetUniversalName_or_WNetGetUniversalNameA_and_WNetGetUniversalNameW #endif DWORD qxeWNetGetUniversalName (const Extbyte * lpLocalPath, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -469,7 +591,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetGetUser -#define WNetGetUser error use qxeWNetGetUser or WNetGetUserA/WNetGetUserW +#define WNetGetUser error_use_qxeWNetGetUser_or_WNetGetUserA_and_WNetGetUserW #endif DWORD qxeWNetGetUser (const Extbyte * lpName, Extbyte * lpUserName, LPDWORD lpnLength); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -477,7 +599,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetGetProviderName -#define WNetGetProviderName error use qxeWNetGetProviderName or WNetGetProviderNameA/WNetGetProviderNameW +#define WNetGetProviderName error_use_qxeWNetGetProviderName_or_WNetGetProviderNameA_and_WNetGetProviderNameW #endif DWORD qxeWNetGetProviderName (DWORD dwNetType, Extbyte * lpProviderName, LPDWORD lpBufferSize); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -485,7 +607,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetGetNetworkInformation -#define WNetGetNetworkInformation error use qxeWNetGetNetworkInformation or WNetGetNetworkInformationA/WNetGetNetworkInformationW +#define WNetGetNetworkInformation error_use_qxeWNetGetNetworkInformation_or_WNetGetNetworkInformationA_and_WNetGetNetworkInformationW #endif DWORD qxeWNetGetNetworkInformation (const Extbyte * lpProvider, LPNETINFOSTRUCT lpNetInfoStruct); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -493,7 +615,7 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WNetGetLastError -#define WNetGetLastError error use qxeWNetGetLastError or WNetGetLastErrorA/WNetGetLastErrorW +#define WNetGetLastError error_use_qxeWNetGetLastError_or_WNetGetLastErrorA_and_WNetGetLastErrorW #endif DWORD qxeWNetGetLastError (LPDWORD lpError, Extbyte * lpErrorBuf, DWORD nErrorBufSize, Extbyte * lpNameBuf, DWORD nNameBufSize); #endif /* defined (HAVE_MS_WINDOWS) */ @@ -501,1833 +623,1863 @@ #if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef MultinetGetConnectionPerformance -#define MultinetGetConnectionPerformance error use qxeMultinetGetConnectionPerformance or MultinetGetConnectionPerformanceA/MultinetGetConnectionPerformanceW +#define MultinetGetConnectionPerformance error_use_qxeMultinetGetConnectionPerformance_or_MultinetGetConnectionPerformanceA_and_MultinetGetConnectionPerformanceW #endif DWORD qxeMultinetGetConnectionPerformance (LPNETRESOURCEW lpNetResource, LPNETCONNECTINFOSTRUCT lpNetConnectInfoStruct); #endif /* defined (HAVE_MS_WINDOWS) */ -/* Processing file WINREG.H */ - -/* Skipping RegConnectRegistry because error in Cygwin prototype */ +/* Processing file WINUSER.H */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegCreateKey -#define RegCreateKey error use qxeRegCreateKey or RegCreateKeyA/RegCreateKeyW +#undef wvsprintf +#define wvsprintf error_use_qxewvsprintf_or_wvsprintfA_and_wvsprintfW #endif -LONG - qxeRegCreateKey (HKEY hKey, const Extbyte * lpSubKey, PHKEY phkResult); +int qxewvsprintf (Extbyte * arg1, const Extbyte * arg2, va_list arglist); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegCreateKeyEx -#define RegCreateKeyEx error use qxeRegCreateKeyEx or RegCreateKeyExA/RegCreateKeyExW +#undef LoadKeyboardLayout +#define LoadKeyboardLayout error_use_qxeLoadKeyboardLayout_or_LoadKeyboardLayoutA_and_LoadKeyboardLayoutW #endif -LONG - qxeRegCreateKeyEx (HKEY hKey, const Extbyte * lpSubKey, DWORD Reserved, Extbyte * lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition); +HKL qxeLoadKeyboardLayout (const Extbyte * pwszKLID, UINT Flags); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegDeleteKey -#define RegDeleteKey error use qxeRegDeleteKey or RegDeleteKeyA/RegDeleteKeyW +#undef GetKeyboardLayoutName +#define GetKeyboardLayoutName error_use_qxeGetKeyboardLayoutName_or_GetKeyboardLayoutNameA_and_GetKeyboardLayoutNameW #endif -LONG - qxeRegDeleteKey (HKEY hKey, const Extbyte * lpSubKey); +BOOL qxeGetKeyboardLayoutName (Extbyte * pwszKLID); + +#undef CreateDesktop +#define CreateDesktop error_split_sized_LPDEVMODE #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegDeleteValue -#define RegDeleteValue error use qxeRegDeleteValue or RegDeleteValueA/RegDeleteValueW +#undef OpenDesktop +#define OpenDesktop error_use_qxeOpenDesktop_or_OpenDesktopA_and_OpenDesktopW #endif -LONG - qxeRegDeleteValue (HKEY hKey, const Extbyte * lpValueName); +HDESK qxeOpenDesktop (Extbyte * lpszDesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegEnumKey -#define RegEnumKey error use qxeRegEnumKey or RegEnumKeyA/RegEnumKeyW +#undef EnumDesktops +#define EnumDesktops error_use_qxeEnumDesktops_or_EnumDesktopsA_and_EnumDesktopsW #endif -LONG - qxeRegEnumKey (HKEY hKey, DWORD dwIndex, Extbyte * lpName, DWORD cbName); +BOOL qxeEnumDesktops (HWINSTA hwinsta, DESKTOPENUMPROCW lpEnumFunc, LPARAM lParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegEnumKeyEx -#define RegEnumKeyEx error use qxeRegEnumKeyEx or RegEnumKeyExA/RegEnumKeyExW +#undef CreateWindowStation +#define CreateWindowStation error_use_qxeCreateWindowStation_or_CreateWindowStationA_and_CreateWindowStationW #endif -LONG - qxeRegEnumKeyEx (HKEY hKey, DWORD dwIndex, Extbyte * lpName, LPDWORD lpcbName, LPDWORD lpReserved, Extbyte * lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime); +HWINSTA qxeCreateWindowStation (Extbyte * lpwinsta, DWORD dwReserved, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegEnumValue -#define RegEnumValue error use qxeRegEnumValue or RegEnumValueA/RegEnumValueW +#undef OpenWindowStation +#define OpenWindowStation error_use_qxeOpenWindowStation_or_OpenWindowStationA_and_OpenWindowStationW #endif -LONG - qxeRegEnumValue (HKEY hKey, DWORD dwIndex, Extbyte * lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); +HWINSTA qxeOpenWindowStation (Extbyte * lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegLoadKey -#define RegLoadKey error use qxeRegLoadKey or RegLoadKeyA/RegLoadKeyW +#undef EnumWindowStations +#define EnumWindowStations error_use_qxeEnumWindowStations_or_EnumWindowStationsA_and_EnumWindowStationsW #endif -LONG - qxeRegLoadKey (HKEY hKey, const Extbyte * lpSubKey, const Extbyte * lpFile); +BOOL qxeEnumWindowStations (WINSTAENUMPROCW lpEnumFunc, LPARAM lParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegOpenKey -#define RegOpenKey error use qxeRegOpenKey or RegOpenKeyA/RegOpenKeyW +#undef GetUserObjectInformation +#define GetUserObjectInformation error_use_qxeGetUserObjectInformation_or_GetUserObjectInformationA_and_GetUserObjectInformationW #endif -LONG - qxeRegOpenKey (HKEY hKey, const Extbyte * lpSubKey, PHKEY phkResult); +BOOL qxeGetUserObjectInformation (HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegOpenKeyEx -#define RegOpenKeyEx error use qxeRegOpenKeyEx or RegOpenKeyExA/RegOpenKeyExW +#undef SetUserObjectInformation +#define SetUserObjectInformation error_use_qxeSetUserObjectInformation_or_SetUserObjectInformationA_and_SetUserObjectInformationW #endif -LONG - qxeRegOpenKeyEx (HKEY hKey, const Extbyte * lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); +BOOL qxeSetUserObjectInformation (HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegQueryInfoKey -#define RegQueryInfoKey error use qxeRegQueryInfoKey or RegQueryInfoKeyA/RegQueryInfoKeyW +#undef RegisterWindowMessage +#define RegisterWindowMessage error_use_qxeRegisterWindowMessage_or_RegisterWindowMessageA_and_RegisterWindowMessageW #endif -LONG - qxeRegQueryInfoKey (HKEY hKey, Extbyte * lpClass, LPDWORD lpcbClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen, LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime); +UINT qxeRegisterWindowMessage (const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegQueryValue -#define RegQueryValue error use qxeRegQueryValue or RegQueryValueA/RegQueryValueW +#undef GetMessage +#define GetMessage error_use_qxeGetMessage_or_GetMessageA_and_GetMessageW #endif -LONG - qxeRegQueryValue (HKEY hKey, const Extbyte * lpSubKey, Extbyte * lpValue, PLONG lpcbValue); +BOOL qxeGetMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegQueryMultipleValues -#define RegQueryMultipleValues error use qxeRegQueryMultipleValues or RegQueryMultipleValuesA/RegQueryMultipleValuesW +#undef DispatchMessage +#define DispatchMessage error_use_qxeDispatchMessage_or_DispatchMessageA_and_DispatchMessageW #endif -LONG - qxeRegQueryMultipleValues (HKEY hKey, PVALENTW val_list, DWORD num_vals, Extbyte * lpValueBuf, LPDWORD ldwTotsize); +LONG qxeDispatchMessage (CONST MSG * lpMsg); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegQueryValueEx -#define RegQueryValueEx error use qxeRegQueryValueEx or RegQueryValueExA/RegQueryValueExW +#undef PeekMessage +#define PeekMessage error_use_qxePeekMessage_or_PeekMessageA_and_PeekMessageW #endif -LONG - qxeRegQueryValueEx (HKEY hKey, const Extbyte * lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); +BOOL qxePeekMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg); + +/* Skipping SendMessage because split messages and structures */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegReplaceKey -#define RegReplaceKey error use qxeRegReplaceKey or RegReplaceKeyA/RegReplaceKeyW +#undef SendMessageTimeout +#define SendMessageTimeout error_use_qxeSendMessageTimeout_or_SendMessageTimeoutA_and_SendMessageTimeoutW #endif -LONG - qxeRegReplaceKey (HKEY hKey, const Extbyte * lpSubKey, const Extbyte * lpNewFile, const Extbyte * lpOldFile); +LRESULT qxeSendMessageTimeout (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, LPDWORD lpdwResult); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegRestoreKey -#define RegRestoreKey error use qxeRegRestoreKey or RegRestoreKeyA/RegRestoreKeyW +#undef SendNotifyMessage +#define SendNotifyMessage error_use_qxeSendNotifyMessage_or_SendNotifyMessageA_and_SendNotifyMessageW #endif -LONG - qxeRegRestoreKey (HKEY hKey, const Extbyte * lpFile, DWORD dwFlags); +BOOL qxeSendNotifyMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegSaveKey -#define RegSaveKey error use qxeRegSaveKey or RegSaveKeyA/RegSaveKeyW +#undef SendMessageCallback +#define SendMessageCallback error_use_qxeSendMessageCallback_or_SendMessageCallbackA_and_SendMessageCallbackW #endif -LONG - qxeRegSaveKey (HKEY hKey, const Extbyte * lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes); +BOOL qxeSendMessageCallback (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, SENDASYNCPROC lpResultCallBack, DWORD dwData); + +#undef BroadcastSystemMessage +#define BroadcastSystemMessage error_win95_version_not_split__NT_4_0__only + +#undef RegisterDeviceNotification +#define RegisterDeviceNotification error_NT_5_0__only #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegSetValue -#define RegSetValue error use qxeRegSetValue or RegSetValueA/RegSetValueW +#undef PostMessage +#define PostMessage error_use_qxePostMessage_or_PostMessageA_and_PostMessageW #endif -LONG - qxeRegSetValue (HKEY hKey, const Extbyte * lpSubKey, DWORD dwType, const Extbyte * lpData, DWORD cbData); +BOOL qxePostMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegSetValueEx -#define RegSetValueEx error use qxeRegSetValueEx or RegSetValueExA/RegSetValueExW +#undef PostThreadMessage +#define PostThreadMessage error_use_qxePostThreadMessage_or_PostThreadMessageA_and_PostThreadMessageW #endif -LONG - qxeRegSetValueEx (HKEY hKey, const Extbyte * lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData); +BOOL qxePostThreadMessage (DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegUnLoadKey -#define RegUnLoadKey error use qxeRegUnLoadKey or RegUnLoadKeyA/RegUnLoadKeyW -#endif -LONG - qxeRegUnLoadKey (HKEY hKey, const Extbyte * lpSubKey); +/* Skipping DefWindowProc because return value is conditionalized on _MAC, messes up parser */ -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef InitiateSystemShutdown -#define InitiateSystemShutdown error use qxeInitiateSystemShutdown or InitiateSystemShutdownA/InitiateSystemShutdownW -#endif -BOOL - qxeInitiateSystemShutdown (Extbyte * lpMachineName, Extbyte * lpMessage, DWORD dwTimeout, BOOL bForceAppsClosed, BOOL bRebootAfterShutdown); +#undef CallWindowProc +#define CallWindowProc error_two_versions__STRICT_and_non_STRICT -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef AbortSystemShutdown -#define AbortSystemShutdown error use qxeAbortSystemShutdown or AbortSystemShutdownA/AbortSystemShutdownW -#endif -BOOL - qxeAbortSystemShutdown (Extbyte * lpMachineName); +#undef CallWindowProc +#define CallWindowProc error_two_versions__STRICT_and_non_STRICT +/* Skipping RegisterClass because need to intercept so we can provide our own window procedure and handle split notify messages; split-simple WNDCLASS */ -/* Processing file SHELLAPI.H */ +/* Skipping UnregisterClass because need to intercept for reasons related to RegisterClass */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DragQueryFile -#define DragQueryFile error use qxeDragQueryFile or DragQueryFileA/DragQueryFileW +#undef GetClassInfo +#define GetClassInfo error_use_qxeGetClassInfo_or_GetClassInfoA_and_GetClassInfoW #endif -UINT qxeDragQueryFile (HDROP arg1, UINT arg2, Extbyte * arg3, UINT arg4); +BOOL qxeGetClassInfo (HINSTANCE hInstance, const Extbyte * lpClassName, LPWNDCLASSW lpWndClass); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ShellExecute -#define ShellExecute error use qxeShellExecute or ShellExecuteA/ShellExecuteW -#endif -HINSTANCE qxeShellExecute (HWND hwnd, const Extbyte * lpOperation, const Extbyte * lpFile, const Extbyte * lpParameters, const Extbyte * lpDirectory, INT nShowCmd); +/* Skipping RegisterClassEx because need to intercept so we can provide our own window procedure and handle split notify messages; split-simple WNDCLASSEX; NT 4.0+ only */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef FindExecutable -#define FindExecutable error use qxeFindExecutable or FindExecutableA/FindExecutableW +#undef GetClassInfoEx +#define GetClassInfoEx error_use_qxeGetClassInfoEx_or_GetClassInfoExA_and_GetClassInfoExW #endif -HINSTANCE qxeFindExecutable (const Extbyte * lpFile, const Extbyte * lpDirectory, Extbyte * lpResult); - -#undef CommandLineToArgv -#define CommandLineToArgv error Unicode-only +BOOL qxeGetClassInfoEx (HINSTANCE arg1, const Extbyte * arg2, LPWNDCLASSEXW arg3); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ShellAbout -#define ShellAbout error use qxeShellAbout or ShellAboutA/ShellAboutW +#undef CreateWindowEx +#define CreateWindowEx error_use_qxeCreateWindowEx_or_CreateWindowExA_and_CreateWindowExW #endif -INT qxeShellAbout (HWND hWnd, const Extbyte * szApp, const Extbyte * szOtherStuff, HICON hIcon); +HWND qxeCreateWindowEx (DWORD dwExStyle, const Extbyte * lpClassName, const Extbyte * lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ExtractAssociatedIcon -#define ExtractAssociatedIcon error use qxeExtractAssociatedIcon or ExtractAssociatedIconA/ExtractAssociatedIconW +#undef CreateDialogParam +#define CreateDialogParam error_use_qxeCreateDialogParam_or_CreateDialogParamA_and_CreateDialogParamW #endif -HICON qxeExtractAssociatedIcon (HINSTANCE hInst, Extbyte * lpIconPath, LPWORD lpiIcon); +HWND qxeCreateDialogParam (HINSTANCE hInstance, const Extbyte * lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ExtractIcon -#define ExtractIcon error use qxeExtractIcon or ExtractIconA/ExtractIconW +#undef CreateDialogIndirectParam +#define CreateDialogIndirectParam error_use_qxeCreateDialogIndirectParam_or_CreateDialogIndirectParamA_and_CreateDialogIndirectParamW #endif -HICON qxeExtractIcon (HINSTANCE hInst, const Extbyte * lpszExeFileName, UINT nIconIndex); +HWND qxeCreateDialogIndirectParam (HINSTANCE hInstance, LPCDLGTEMPLATEW lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); -#if !defined (CYGWIN_HEADERS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DoEnvironmentSubst -#define DoEnvironmentSubst error use qxeDoEnvironmentSubst or DoEnvironmentSubstA/DoEnvironmentSubstW +#undef DialogBoxParam +#define DialogBoxParam error_use_qxeDialogBoxParam_or_DialogBoxParamA_and_DialogBoxParamW #endif -DWORD qxeDoEnvironmentSubst (Extbyte * szString, UINT cbString); -#endif /* !defined (CYGWIN_HEADERS) */ - -#undef FindEnvironmentString -#define FindEnvironmentString error causes link error; NT 4.0+ only - -/* Skipping ExtractIconEx because NT 4.0+ only, error in Cygwin prototype */ +int qxeDialogBoxParam (HINSTANCE hInstance, const Extbyte * lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SHFileOperation -#define SHFileOperation error use qxeSHFileOperation or SHFileOperationA/SHFileOperationW +#undef DialogBoxIndirectParam +#define DialogBoxIndirectParam error_use_qxeDialogBoxIndirectParam_or_DialogBoxIndirectParamA_and_DialogBoxIndirectParamW #endif -int qxeSHFileOperation (LPSHFILEOPSTRUCTW lpFileOp); +int qxeDialogBoxIndirectParam (HINSTANCE hInstance, LPCDLGTEMPLATEW hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ShellExecuteEx -#define ShellExecuteEx error use qxeShellExecuteEx or ShellExecuteExA/ShellExecuteExW +#undef SetDlgItemText +#define SetDlgItemText error_use_qxeSetDlgItemText_or_SetDlgItemTextA_and_SetDlgItemTextW #endif -BOOL qxeShellExecuteEx (LPSHELLEXECUTEINFOW lpExecInfo); - -#undef WinExecError -#define WinExecError error causes link error; NT 4.0+ only +BOOL qxeSetDlgItemText (HWND hDlg, int nIDDlgItem, const Extbyte * lpString); -#if !defined (CYGWIN_HEADERS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SHQueryRecycleBin -#define SHQueryRecycleBin error use qxeSHQueryRecycleBin or SHQueryRecycleBinA/SHQueryRecycleBinW +#undef GetDlgItemText +#define GetDlgItemText error_use_qxeGetDlgItemText_or_GetDlgItemTextA_and_GetDlgItemTextW #endif -HRESULT qxeSHQueryRecycleBin (const Extbyte * pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo); -#endif /* !defined (CYGWIN_HEADERS) */ +UINT qxeGetDlgItemText (HWND hDlg, int nIDDlgItem, Extbyte * lpString, int nMaxCount); -#if !defined (CYGWIN_HEADERS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SHEmptyRecycleBin -#define SHEmptyRecycleBin error use qxeSHEmptyRecycleBin or SHEmptyRecycleBinA/SHEmptyRecycleBinW +#undef SendDlgItemMessage +#define SendDlgItemMessage error_use_qxeSendDlgItemMessage_or_SendDlgItemMessageA_and_SendDlgItemMessageW #endif -HRESULT qxeSHEmptyRecycleBin (HWND hwnd, const Extbyte * pszRootPath, DWORD dwFlags); -#endif /* !defined (CYGWIN_HEADERS) */ - -#undef Shell_NotifyIcon -#define Shell_NotifyIcon error split-sized NOTIFYICONDATA, NT 4.0+ only - -/* Skipping SHGetFileInfo because split-sized SHFILEINFO, NT 4.0+ only */ +LONG qxeSendDlgItemMessage (HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam); -#undef SHGetDiskFreeSpace -#define SHGetDiskFreeSpace error causes link error; NT 4.0+ only +#undef DefDlgProc +#define DefDlgProc error_return_value_is_conditionalized_on__MAC__messes_up_parser #if !defined (CYGWIN_HEADERS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SHGetNewLinkInfo -#define SHGetNewLinkInfo error use qxeSHGetNewLinkInfo or SHGetNewLinkInfoA/SHGetNewLinkInfoW +#undef CallMsgFilter +#define CallMsgFilter error_use_qxeCallMsgFilter_or_CallMsgFilterA_and_CallMsgFilterW #endif -BOOL qxeSHGetNewLinkInfo (const Extbyte * pszLinkTo, const Extbyte * pszDir, Extbyte * pszName, BOOL * pfMustCopy, UINT uFlags); +BOOL qxeCallMsgFilter (LPMSG lpMsg, int nCode); #endif /* !defined (CYGWIN_HEADERS) */ -#if !defined (CYGWIN_HEADERS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SHInvokePrinterCommand -#define SHInvokePrinterCommand error use qxeSHInvokePrinterCommand or SHInvokePrinterCommandA/SHInvokePrinterCommandW +#undef RegisterClipboardFormat +#define RegisterClipboardFormat error_use_qxeRegisterClipboardFormat_or_RegisterClipboardFormatA_and_RegisterClipboardFormatW #endif -BOOL qxeSHInvokePrinterCommand (HWND hwnd, UINT uAction, const Extbyte * lpBuf1, const Extbyte * lpBuf2, BOOL fModal); -#endif /* !defined (CYGWIN_HEADERS) */ - - -/* Processing file WINCON.H */ +UINT qxeRegisterClipboardFormat (const Extbyte * lpszFormat); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef PeekConsoleInput -#define PeekConsoleInput error use qxePeekConsoleInput or PeekConsoleInputA/PeekConsoleInputW +#undef GetClipboardFormatName +#define GetClipboardFormatName error_use_qxeGetClipboardFormatName_or_GetClipboardFormatNameA_and_GetClipboardFormatNameW #endif -BOOL qxePeekConsoleInput (HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead); +int qxeGetClipboardFormatName (UINT format, Extbyte * lpszFormatName, int cchMaxCount); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ReadConsoleInput -#define ReadConsoleInput error use qxeReadConsoleInput or ReadConsoleInputA/ReadConsoleInputW +#undef CharToOem +#define CharToOem error_use_qxeCharToOem_or_CharToOemA_and_CharToOemW #endif -BOOL qxeReadConsoleInput (HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead); +BOOL qxeCharToOem (const Extbyte * lpszSrc, LPSTR lpszDst); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef WriteConsoleInput -#define WriteConsoleInput error use qxeWriteConsoleInput or WriteConsoleInputA/WriteConsoleInputW +#undef OemToChar +#define OemToChar error_use_qxeOemToChar_or_OemToCharA_and_OemToCharW #endif -BOOL qxeWriteConsoleInput (HANDLE hConsoleInput, CONST INPUT_RECORD * lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten); +BOOL qxeOemToChar (LPCSTR lpszSrc, Extbyte * lpszDst); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ReadConsoleOutput -#define ReadConsoleOutput error use qxeReadConsoleOutput or ReadConsoleOutputA/ReadConsoleOutputW +#undef CharToOemBuff +#define CharToOemBuff error_use_qxeCharToOemBuff_or_CharToOemBuffA_and_CharToOemBuffW #endif -BOOL qxeReadConsoleOutput (HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion); +BOOL qxeCharToOemBuff (const Extbyte * lpszSrc, LPSTR lpszDst, DWORD cchDstLength); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef WriteConsoleOutput -#define WriteConsoleOutput error use qxeWriteConsoleOutput or WriteConsoleOutputA/WriteConsoleOutputW +#undef OemToCharBuff +#define OemToCharBuff error_use_qxeOemToCharBuff_or_OemToCharBuffA_and_OemToCharBuffW #endif -BOOL qxeWriteConsoleOutput (HANDLE hConsoleOutput, CONST CHAR_INFO * lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion); +BOOL qxeOemToCharBuff (LPCSTR lpszSrc, Extbyte * lpszDst, DWORD cchDstLength); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ReadConsoleOutputCharacter -#define ReadConsoleOutputCharacter error use qxeReadConsoleOutputCharacter or ReadConsoleOutputCharacterA/ReadConsoleOutputCharacterW +#undef CharUpper +#define CharUpper error_use_qxeCharUpper_or_CharUpperA_and_CharUpperW #endif -BOOL qxeReadConsoleOutputCharacter (HANDLE hConsoleOutput, Extbyte * lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead); +Extbyte * qxeCharUpper (Extbyte * lpsz); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef WriteConsoleOutputCharacter -#define WriteConsoleOutputCharacter error use qxeWriteConsoleOutputCharacter or WriteConsoleOutputCharacterA/WriteConsoleOutputCharacterW +#undef CharUpperBuff +#define CharUpperBuff error_use_qxeCharUpperBuff_or_CharUpperBuffA_and_CharUpperBuffW #endif -BOOL qxeWriteConsoleOutputCharacter (HANDLE hConsoleOutput, const Extbyte * lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten); - -#undef FillConsoleOutputCharacter -#define FillConsoleOutputCharacter error split CHAR +DWORD qxeCharUpperBuff (Extbyte * lpsz, DWORD cchLength); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ScrollConsoleScreenBuffer -#define ScrollConsoleScreenBuffer error use qxeScrollConsoleScreenBuffer or ScrollConsoleScreenBufferA/ScrollConsoleScreenBufferW +#undef CharLower +#define CharLower error_use_qxeCharLower_or_CharLowerA_and_CharLowerW #endif -BOOL qxeScrollConsoleScreenBuffer (HANDLE hConsoleOutput, CONST SMALL_RECT * lpScrollRectangle, CONST SMALL_RECT * lpClipRectangle, COORD dwDestinationOrigin, CONST CHAR_INFO * lpFill); +Extbyte * qxeCharLower (Extbyte * lpsz); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetConsoleTitle -#define GetConsoleTitle error use qxeGetConsoleTitle or GetConsoleTitleA/GetConsoleTitleW +#undef CharLowerBuff +#define CharLowerBuff error_use_qxeCharLowerBuff_or_CharLowerBuffA_and_CharLowerBuffW #endif -DWORD qxeGetConsoleTitle (Extbyte * lpConsoleTitle, DWORD nSize); +DWORD qxeCharLowerBuff (Extbyte * lpsz, DWORD cchLength); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetConsoleTitle -#define SetConsoleTitle error use qxeSetConsoleTitle or SetConsoleTitleA/SetConsoleTitleW +#undef CharNext +#define CharNext error_use_qxeCharNext_or_CharNextA_and_CharNextW #endif -BOOL qxeSetConsoleTitle (const Extbyte * lpConsoleTitle); +Extbyte * qxeCharNext (const Extbyte * lpsz); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ReadConsole -#define ReadConsole error use qxeReadConsole or ReadConsoleA/ReadConsoleW +#undef CharPrev +#define CharPrev error_use_qxeCharPrev_or_CharPrevA_and_CharPrevW #endif -BOOL qxeReadConsole (HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved); +Extbyte * qxeCharPrev (const Extbyte * lpszStart, const Extbyte * lpszCurrent); + +#undef IsCharAlpha +#define IsCharAlpha error_split_CHAR + +#undef IsCharAlphaNumeric +#define IsCharAlphaNumeric error_split_CHAR + +#undef IsCharUpper +#define IsCharUpper error_split_CHAR + +#undef IsCharLower +#define IsCharLower error_split_CHAR #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef WriteConsole -#define WriteConsole error use qxeWriteConsole or WriteConsoleA/WriteConsoleW +#undef GetKeyNameText +#define GetKeyNameText error_use_qxeGetKeyNameText_or_GetKeyNameTextA_and_GetKeyNameTextW #endif -BOOL qxeWriteConsole (HANDLE hConsoleOutput, CONST VOID * lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved); +int qxeGetKeyNameText (LONG lParam, Extbyte * lpString, int nSize); +/* Skipping VkKeyScan because split CHAR */ -/* Processing file IMM.H */ +#undef VkKeyScanEx +#define VkKeyScanEx error_split_CHAR__NT_4_0__only -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmInstallIME -#define ImmInstallIME error use qxeImmInstallIME or ImmInstallIMEA/ImmInstallIMEW +#undef MapVirtualKey +#define MapVirtualKey error_use_qxeMapVirtualKey_or_MapVirtualKeyA_and_MapVirtualKeyW #endif -HKL qxeImmInstallIME (const Extbyte * lpszIMEFileName, const Extbyte * lpszLayoutText); -#endif /* defined (HAVE_MS_WINDOWS) */ +UINT qxeMapVirtualKey (UINT uCode, UINT uMapType); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmGetDescription -#define ImmGetDescription error use qxeImmGetDescription or ImmGetDescriptionA/ImmGetDescriptionW +#undef MapVirtualKeyEx +#define MapVirtualKeyEx error_use_qxeMapVirtualKeyEx_or_MapVirtualKeyExA_and_MapVirtualKeyExW #endif -UINT qxeImmGetDescription (HKL arg1, Extbyte * arg2, UINT uBufLen); -#endif /* defined (HAVE_MS_WINDOWS) */ +UINT qxeMapVirtualKeyEx (UINT uCode, UINT uMapType, HKL dwhkl); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmGetIMEFileName -#define ImmGetIMEFileName error use qxeImmGetIMEFileName or ImmGetIMEFileNameA/ImmGetIMEFileNameW +#undef LoadAccelerators +#define LoadAccelerators error_use_qxeLoadAccelerators_or_LoadAcceleratorsA_and_LoadAcceleratorsW #endif -UINT qxeImmGetIMEFileName (HKL arg1, Extbyte * arg2, UINT uBufLen); -#endif /* defined (HAVE_MS_WINDOWS) */ +HACCEL qxeLoadAccelerators (HINSTANCE hInstance, const Extbyte * lpTableName); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmGetCompositionString -#define ImmGetCompositionString error use qxeImmGetCompositionString or ImmGetCompositionStringA/ImmGetCompositionStringW +#undef CreateAcceleratorTable +#define CreateAcceleratorTable error_use_qxeCreateAcceleratorTable_or_CreateAcceleratorTableA_and_CreateAcceleratorTableW #endif -LONG qxeImmGetCompositionString (HIMC arg1, DWORD arg2, LPVOID arg3, DWORD arg4); -#endif /* defined (HAVE_MS_WINDOWS) */ +HACCEL qxeCreateAcceleratorTable (LPACCEL arg1, int arg2); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmSetCompositionString -#define ImmSetCompositionString error use qxeImmSetCompositionString or ImmSetCompositionStringA/ImmSetCompositionStringW +#undef CopyAcceleratorTable +#define CopyAcceleratorTable error_use_qxeCopyAcceleratorTable_or_CopyAcceleratorTableA_and_CopyAcceleratorTableW #endif -BOOL qxeImmSetCompositionString (HIMC arg1, DWORD dwIndex, LPCVOID lpComp, DWORD arg4, LPCVOID lpRead, DWORD arg6); -#endif /* defined (HAVE_MS_WINDOWS) */ +int qxeCopyAcceleratorTable (HACCEL hAccelSrc, LPACCEL lpAccelDst, int cAccelEntries); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmGetCandidateListCount -#define ImmGetCandidateListCount error use qxeImmGetCandidateListCount or ImmGetCandidateListCountA/ImmGetCandidateListCountW +#undef TranslateAccelerator +#define TranslateAccelerator error_use_qxeTranslateAccelerator_or_TranslateAcceleratorA_and_TranslateAcceleratorW #endif -DWORD qxeImmGetCandidateListCount (HIMC arg1, LPDWORD lpdwListCount); -#endif /* defined (HAVE_MS_WINDOWS) */ +int qxeTranslateAccelerator (HWND hWnd, HACCEL hAccTable, LPMSG lpMsg); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmGetCandidateList -#define ImmGetCandidateList error use qxeImmGetCandidateList or ImmGetCandidateListA/ImmGetCandidateListW +#undef LoadMenu +#define LoadMenu error_use_qxeLoadMenu_or_LoadMenuA_and_LoadMenuW #endif -DWORD qxeImmGetCandidateList (HIMC arg1, DWORD deIndex, LPCANDIDATELIST arg3, DWORD dwBufLen); -#endif /* defined (HAVE_MS_WINDOWS) */ +HMENU qxeLoadMenu (HINSTANCE hInstance, const Extbyte * lpMenuName); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmGetGuideLine -#define ImmGetGuideLine error use qxeImmGetGuideLine or ImmGetGuideLineA/ImmGetGuideLineW +#undef LoadMenuIndirect +#define LoadMenuIndirect error_use_qxeLoadMenuIndirect_or_LoadMenuIndirectA_and_LoadMenuIndirectW #endif -DWORD qxeImmGetGuideLine (HIMC arg1, DWORD dwIndex, Extbyte * arg3, DWORD dwBufLen); -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) -/* Skipping ImmGetCompositionFont because split-sized LOGFONT */ -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) -/* Skipping ImmSetCompositionFont because split-sized LOGFONT */ -#endif /* defined (HAVE_MS_WINDOWS) */ +HMENU qxeLoadMenuIndirect (CONST MENUTEMPLATEW * lpMenuTemplate); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmConfigureIME -#define ImmConfigureIME error use qxeImmConfigureIME or ImmConfigureIMEA/ImmConfigureIMEW +#undef ChangeMenu +#define ChangeMenu error_use_qxeChangeMenu_or_ChangeMenuA_and_ChangeMenuW #endif -BOOL qxeImmConfigureIME (HKL arg1, HWND arg2, DWORD arg3, LPVOID arg4); -#endif /* defined (HAVE_MS_WINDOWS) */ +BOOL qxeChangeMenu (HMENU hMenu, UINT cmd, const Extbyte * lpszNewItem, UINT cmdInsert, UINT flags); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmEscape -#define ImmEscape error use qxeImmEscape or ImmEscapeA/ImmEscapeW +#undef GetMenuString +#define GetMenuString error_use_qxeGetMenuString_or_GetMenuStringA_and_GetMenuStringW #endif -LRESULT qxeImmEscape (HKL arg1, HIMC arg2, UINT arg3, LPVOID arg4); -#endif /* defined (HAVE_MS_WINDOWS) */ +int qxeGetMenuString (HMENU hMenu, UINT uIDItem, Extbyte * lpString, int nMaxCount, UINT uFlag); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmGetConversionList -#define ImmGetConversionList error use qxeImmGetConversionList or ImmGetConversionListA/ImmGetConversionListW +#undef InsertMenu +#define InsertMenu error_use_qxeInsertMenu_or_InsertMenuA_and_InsertMenuW #endif -DWORD qxeImmGetConversionList (HKL arg1, HIMC arg2, const Extbyte * arg3, LPCANDIDATELIST arg4, DWORD dwBufLen, UINT uFlag); -#endif /* defined (HAVE_MS_WINDOWS) */ +BOOL qxeInsertMenu (HMENU hMenu, UINT uPosition, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmIsUIMessage -#define ImmIsUIMessage error use qxeImmIsUIMessage or ImmIsUIMessageA/ImmIsUIMessageW +#undef AppendMenu +#define AppendMenu error_use_qxeAppendMenu_or_AppendMenuA_and_AppendMenuW #endif -BOOL qxeImmIsUIMessage (HWND arg1, UINT arg2, WPARAM arg3, LPARAM arg4); -#endif /* defined (HAVE_MS_WINDOWS) */ +BOOL qxeAppendMenu (HMENU hMenu, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmRegisterWord -#define ImmRegisterWord error use qxeImmRegisterWord or ImmRegisterWordA/ImmRegisterWordW +#undef ModifyMenu +#define ModifyMenu error_use_qxeModifyMenu_or_ModifyMenuA_and_ModifyMenuW #endif -BOOL qxeImmRegisterWord (HKL arg1, const Extbyte * lpszReading, DWORD arg3, const Extbyte * lpszRegister); -#endif /* defined (HAVE_MS_WINDOWS) */ +BOOL qxeModifyMenu (HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem); -#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmUnregisterWord -#define ImmUnregisterWord error use qxeImmUnregisterWord or ImmUnregisterWordA/ImmUnregisterWordW +#undef InsertMenuItem +#define InsertMenuItem error_use_qxeInsertMenuItem_or_InsertMenuItemA_and_InsertMenuItemW #endif -BOOL qxeImmUnregisterWord (HKL arg1, const Extbyte * lpszReading, DWORD arg3, const Extbyte * lpszUnregister); -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) -#undef ImmGetRegisterWordStyle -#define ImmGetRegisterWordStyle error split-sized STYLEBUF -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ImmEnumRegisterWord -#define ImmEnumRegisterWord error use qxeImmEnumRegisterWord or ImmEnumRegisterWordA/ImmEnumRegisterWordW -#endif -UINT qxeImmEnumRegisterWord (HKL arg1, REGISTERWORDENUMPROCW arg2, const Extbyte * lpszReading, DWORD arg4, const Extbyte * lpszRegister, LPVOID arg6); -#endif /* defined (HAVE_MS_WINDOWS) */ - -#if defined (HAVE_MS_WINDOWS) -#undef ImmGetImeMenuItems -#define ImmGetImeMenuItems error split-sized IMEMENUITEMINFO -#endif /* defined (HAVE_MS_WINDOWS) */ - - -/* Processing file DDEML.H */ +BOOL qxeInsertMenuItem (HMENU arg1, UINT arg2, BOOL arg3, LPCMENUITEMINFOW arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DdeInitialize -#define DdeInitialize error use qxeDdeInitialize or DdeInitializeA/DdeInitializeW +#undef GetMenuItemInfo +#define GetMenuItemInfo error_use_qxeGetMenuItemInfo_or_GetMenuItemInfoA_and_GetMenuItemInfoW #endif -UINT qxeDdeInitialize (LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes); - -/* Skipping DdeCreateStringHandle because error in Cygwin prototype */ +BOOL qxeGetMenuItemInfo (HMENU arg1, UINT arg2, BOOL arg3, LPMENUITEMINFOW arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DdeQueryString -#define DdeQueryString error use qxeDdeQueryString or DdeQueryStringA/DdeQueryStringW +#undef SetMenuItemInfo +#define SetMenuItemInfo error_use_qxeSetMenuItemInfo_or_SetMenuItemInfoA_and_SetMenuItemInfoW #endif -DWORD qxeDdeQueryString (DWORD idInst, HSZ hsz, Extbyte * psz, DWORD cchMax, int iCodePage); - - -/* Processing file WINUSER.H */ +BOOL qxeSetMenuItemInfo (HMENU arg1, UINT arg2, BOOL arg3, LPCMENUITEMINFOW arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef wvsprintf -#define wvsprintf error use qxewvsprintf or wvsprintfA/wvsprintfW +#undef DrawText +#define DrawText error_use_qxeDrawText_or_DrawTextA_and_DrawTextW #endif -int qxewvsprintf (Extbyte * arg1, const Extbyte * arg2, va_list arglist); +int qxeDrawText (HDC hDC, const Extbyte * lpString, int nCount, LPRECT lpRect, UINT uFormat); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadKeyboardLayout -#define LoadKeyboardLayout error use qxeLoadKeyboardLayout or LoadKeyboardLayoutA/LoadKeyboardLayoutW +#undef DrawTextEx +#define DrawTextEx error_use_qxeDrawTextEx_or_DrawTextExA_and_DrawTextExW #endif -HKL qxeLoadKeyboardLayout (const Extbyte * pwszKLID, UINT Flags); +int qxeDrawTextEx (HDC arg1, Extbyte * arg2, int arg3, LPRECT arg4, UINT arg5, LPDRAWTEXTPARAMS arg6); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetKeyboardLayoutName -#define GetKeyboardLayoutName error use qxeGetKeyboardLayoutName or GetKeyboardLayoutNameA/GetKeyboardLayoutNameW +#undef GrayString +#define GrayString error_use_qxeGrayString_or_GrayStringA_and_GrayStringW #endif -BOOL qxeGetKeyboardLayoutName (Extbyte * pwszKLID); - -#undef CreateDesktop -#define CreateDesktop error split-sized LPDEVMODE +BOOL qxeGrayString (HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int X, int Y, int nWidth, int nHeight); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef OpenDesktop -#define OpenDesktop error use qxeOpenDesktop or OpenDesktopA/OpenDesktopW +#undef DrawState +#define DrawState error_use_qxeDrawState_or_DrawStateA_and_DrawStateW #endif -HDESK qxeOpenDesktop (Extbyte * lpszDesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess); +BOOL qxeDrawState (HDC arg1, HBRUSH arg2, DRAWSTATEPROC arg3, LPARAM arg4, WPARAM arg5, int arg6, int arg7, int arg8, int arg9, UINT arg10); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef EnumDesktops -#define EnumDesktops error use qxeEnumDesktops or EnumDesktopsA/EnumDesktopsW +#undef TabbedTextOut +#define TabbedTextOut error_use_qxeTabbedTextOut_or_TabbedTextOutA_and_TabbedTextOutW #endif -BOOL qxeEnumDesktops (HWINSTA hwinsta, DESKTOPENUMPROCW lpEnumFunc, LPARAM lParam); +LONG qxeTabbedTextOut (HDC hDC, int X, int Y, const Extbyte * lpString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateWindowStation -#define CreateWindowStation error use qxeCreateWindowStation or CreateWindowStationA/CreateWindowStationW +#undef GetTabbedTextExtent +#define GetTabbedTextExtent error_use_qxeGetTabbedTextExtent_or_GetTabbedTextExtentA_and_GetTabbedTextExtentW #endif -HWINSTA qxeCreateWindowStation (Extbyte * lpwinsta, DWORD dwReserved, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa); +DWORD qxeGetTabbedTextExtent (HDC hDC, const Extbyte * lpString, int nCount, int nTabPositions, LPINT lpnTabStopPositions); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef OpenWindowStation -#define OpenWindowStation error use qxeOpenWindowStation or OpenWindowStationA/OpenWindowStationW +#undef SetProp +#define SetProp error_use_qxeSetProp_or_SetPropA_and_SetPropW #endif -HWINSTA qxeOpenWindowStation (Extbyte * lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess); +BOOL qxeSetProp (HWND hWnd, const Extbyte * lpString, HANDLE hData); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef EnumWindowStations -#define EnumWindowStations error use qxeEnumWindowStations or EnumWindowStationsA/EnumWindowStationsW +#undef GetProp +#define GetProp error_use_qxeGetProp_or_GetPropA_and_GetPropW #endif -BOOL qxeEnumWindowStations (WINSTAENUMPROCW lpEnumFunc, LPARAM lParam); +HANDLE qxeGetProp (HWND hWnd, const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetUserObjectInformation -#define GetUserObjectInformation error use qxeGetUserObjectInformation or GetUserObjectInformationA/GetUserObjectInformationW +#undef RemoveProp +#define RemoveProp error_use_qxeRemoveProp_or_RemovePropA_and_RemovePropW #endif -BOOL qxeGetUserObjectInformation (HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded); +HANDLE qxeRemoveProp (HWND hWnd, const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetUserObjectInformation -#define SetUserObjectInformation error use qxeSetUserObjectInformation or SetUserObjectInformationA/SetUserObjectInformationW +#undef EnumPropsEx +#define EnumPropsEx error_use_qxeEnumPropsEx_or_EnumPropsExA_and_EnumPropsExW #endif -BOOL qxeSetUserObjectInformation (HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength); +int qxeEnumPropsEx (HWND hWnd, PROPENUMPROCEXW lpEnumFunc, LPARAM lParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegisterWindowMessage -#define RegisterWindowMessage error use qxeRegisterWindowMessage or RegisterWindowMessageA/RegisterWindowMessageW +#undef EnumProps +#define EnumProps error_use_qxeEnumProps_or_EnumPropsA_and_EnumPropsW #endif -UINT qxeRegisterWindowMessage (const Extbyte * lpString); +int qxeEnumProps (HWND hWnd, PROPENUMPROCW lpEnumFunc); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetMessage -#define GetMessage error use qxeGetMessage or GetMessageA/GetMessageW +#undef SetWindowText +#define SetWindowText error_use_qxeSetWindowText_or_SetWindowTextA_and_SetWindowTextW #endif -BOOL qxeGetMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); +BOOL qxeSetWindowText (HWND hWnd, const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DispatchMessage -#define DispatchMessage error use qxeDispatchMessage or DispatchMessageA/DispatchMessageW +#undef GetWindowText +#define GetWindowText error_use_qxeGetWindowText_or_GetWindowTextA_and_GetWindowTextW #endif -LONG qxeDispatchMessage (CONST MSG * lpMsg); +int qxeGetWindowText (HWND hWnd, Extbyte * lpString, int nMaxCount); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef PeekMessage -#define PeekMessage error use qxePeekMessage or PeekMessageA/PeekMessageW +#undef GetWindowTextLength +#define GetWindowTextLength error_use_qxeGetWindowTextLength_or_GetWindowTextLengthA_and_GetWindowTextLengthW #endif -BOOL qxePeekMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg); - -/* Skipping SendMessage because split messages and structures */ +int qxeGetWindowTextLength (HWND hWnd); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SendMessageTimeout -#define SendMessageTimeout error use qxeSendMessageTimeout or SendMessageTimeoutA/SendMessageTimeoutW +#undef MessageBox +#define MessageBox error_use_qxeMessageBox_or_MessageBoxA_and_MessageBoxW #endif -LRESULT qxeSendMessageTimeout (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, LPDWORD lpdwResult); +int qxeMessageBox (HWND hWnd, const Extbyte * lpText, const Extbyte * lpCaption, UINT uType); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SendNotifyMessage -#define SendNotifyMessage error use qxeSendNotifyMessage or SendNotifyMessageA/SendNotifyMessageW +#undef MessageBoxEx +#define MessageBoxEx error_use_qxeMessageBoxEx_or_MessageBoxExA_and_MessageBoxExW #endif -BOOL qxeSendNotifyMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); +int qxeMessageBoxEx (HWND hWnd, const Extbyte * lpText, const Extbyte * lpCaption, UINT uType, WORD wLanguageId); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SendMessageCallback -#define SendMessageCallback error use qxeSendMessageCallback or SendMessageCallbackA/SendMessageCallbackW +#undef MessageBoxIndirect +#define MessageBoxIndirect error_use_qxeMessageBoxIndirect_or_MessageBoxIndirectA_and_MessageBoxIndirectW #endif -BOOL qxeSendMessageCallback (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, SENDASYNCPROC lpResultCallBack, DWORD dwData); - -#undef BroadcastSystemMessage -#define BroadcastSystemMessage error win95 version not split; NT 4.0+ only - -#undef RegisterDeviceNotification -#define RegisterDeviceNotification error NT 5.0+ only +int qxeMessageBoxIndirect (LPMSGBOXPARAMSW arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef PostMessage -#define PostMessage error use qxePostMessage or PostMessageA/PostMessageW +#undef GetWindowLong +#define GetWindowLong error_use_qxeGetWindowLong_or_GetWindowLongA_and_GetWindowLongW #endif -BOOL qxePostMessage (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); +LONG qxeGetWindowLong (HWND hWnd, int nIndex); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef PostThreadMessage -#define PostThreadMessage error use qxePostThreadMessage or PostThreadMessageA/PostThreadMessageW +#undef SetWindowLong +#define SetWindowLong error_use_qxeSetWindowLong_or_SetWindowLongA_and_SetWindowLongW #endif -BOOL qxePostThreadMessage (DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam); - -/* Skipping DefWindowProc because return value is conditionalized on _MAC, messes up parser */ - -#undef CallWindowProc -#define CallWindowProc error two versions, STRICT and non-STRICT - -#undef CallWindowProc -#define CallWindowProc error two versions, STRICT and non-STRICT - -/* Skipping RegisterClass because need to intercept so we can provide our own window procedure and handle split notify messages; split-simple WNDCLASS */ - -/* Skipping UnregisterClass because need to intercept for reasons related to RegisterClass */ +LONG qxeSetWindowLong (HWND hWnd, int nIndex, LONG dwNewLong); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetClassInfo -#define GetClassInfo error use qxeGetClassInfo or GetClassInfoA/GetClassInfoW +#undef GetClassLong +#define GetClassLong error_use_qxeGetClassLong_or_GetClassLongA_and_GetClassLongW #endif -BOOL qxeGetClassInfo (HINSTANCE hInstance, const Extbyte * lpClassName, LPWNDCLASSW lpWndClass); - -/* Skipping RegisterClassEx because need to intercept so we can provide our own window procedure and handle split notify messages; split-simple WNDCLASSEX; NT 4.0+ only */ +DWORD qxeGetClassLong (HWND hWnd, int nIndex); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetClassInfoEx -#define GetClassInfoEx error use qxeGetClassInfoEx or GetClassInfoExA/GetClassInfoExW +#undef SetClassLong +#define SetClassLong error_use_qxeSetClassLong_or_SetClassLongA_and_SetClassLongW #endif -BOOL qxeGetClassInfoEx (HINSTANCE arg1, const Extbyte * arg2, LPWNDCLASSEXW arg3); +DWORD qxeSetClassLong (HWND hWnd, int nIndex, LONG dwNewLong); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateWindowEx -#define CreateWindowEx error use qxeCreateWindowEx or CreateWindowExA/CreateWindowExW +#undef FindWindow +#define FindWindow error_use_qxeFindWindow_or_FindWindowA_and_FindWindowW #endif -HWND qxeCreateWindowEx (DWORD dwExStyle, const Extbyte * lpClassName, const Extbyte * lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); +HWND qxeFindWindow (const Extbyte * lpClassName, const Extbyte * lpWindowName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateDialogParam -#define CreateDialogParam error use qxeCreateDialogParam or CreateDialogParamA/CreateDialogParamW +#undef FindWindowEx +#define FindWindowEx error_use_qxeFindWindowEx_or_FindWindowExA_and_FindWindowExW #endif -HWND qxeCreateDialogParam (HINSTANCE hInstance, const Extbyte * lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); +HWND qxeFindWindowEx (HWND arg1, HWND arg2, const Extbyte * arg3, const Extbyte * arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateDialogIndirectParam -#define CreateDialogIndirectParam error use qxeCreateDialogIndirectParam or CreateDialogIndirectParamA/CreateDialogIndirectParamW +#undef GetClassName +#define GetClassName error_use_qxeGetClassName_or_GetClassNameA_and_GetClassNameW #endif -HWND qxeCreateDialogIndirectParam (HINSTANCE hInstance, LPCDLGTEMPLATEW lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); +int qxeGetClassName (HWND hWnd, Extbyte * lpClassName, int nMaxCount); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DialogBoxParam -#define DialogBoxParam error use qxeDialogBoxParam or DialogBoxParamA/DialogBoxParamW -#endif -int qxeDialogBoxParam (HINSTANCE hInstance, const Extbyte * lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); +#undef SetWindowsHook +#define SetWindowsHook error_obsolete__two_versions__STRICT_and_non_STRICT -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DialogBoxIndirectParam -#define DialogBoxIndirectParam error use qxeDialogBoxIndirectParam or DialogBoxIndirectParamA/DialogBoxIndirectParamW -#endif -int qxeDialogBoxIndirectParam (HINSTANCE hInstance, LPCDLGTEMPLATEW hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); +#undef SetWindowsHook +#define SetWindowsHook error_obsolete__two_versions__STRICT_and_non_STRICT #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetDlgItemText -#define SetDlgItemText error use qxeSetDlgItemText or SetDlgItemTextA/SetDlgItemTextW +#undef SetWindowsHookEx +#define SetWindowsHookEx error_use_qxeSetWindowsHookEx_or_SetWindowsHookExA_and_SetWindowsHookExW #endif -BOOL qxeSetDlgItemText (HWND hDlg, int nIDDlgItem, const Extbyte * lpString); +HHOOK qxeSetWindowsHookEx (int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetDlgItemText -#define GetDlgItemText error use qxeGetDlgItemText or GetDlgItemTextA/GetDlgItemTextW +#undef LoadBitmap +#define LoadBitmap error_use_qxeLoadBitmap_or_LoadBitmapA_and_LoadBitmapW #endif -UINT qxeGetDlgItemText (HWND hDlg, int nIDDlgItem, Extbyte * lpString, int nMaxCount); +HBITMAP qxeLoadBitmap (HINSTANCE hInstance, const Extbyte * lpBitmapName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SendDlgItemMessage -#define SendDlgItemMessage error use qxeSendDlgItemMessage or SendDlgItemMessageA/SendDlgItemMessageW +#undef LoadCursor +#define LoadCursor error_use_qxeLoadCursor_or_LoadCursorA_and_LoadCursorW #endif -LONG qxeSendDlgItemMessage (HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam); - -#undef DefDlgProc -#define DefDlgProc error return value is conditionalized on _MAC, messes up parser +HCURSOR qxeLoadCursor (HINSTANCE hInstance, const Extbyte * lpCursorName); -#if !defined (CYGWIN_HEADERS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CallMsgFilter -#define CallMsgFilter error use qxeCallMsgFilter or CallMsgFilterA/CallMsgFilterW +#undef LoadCursorFromFile +#define LoadCursorFromFile error_use_qxeLoadCursorFromFile_or_LoadCursorFromFileA_and_LoadCursorFromFileW #endif -BOOL qxeCallMsgFilter (LPMSG lpMsg, int nCode); -#endif /* !defined (CYGWIN_HEADERS) */ +HCURSOR qxeLoadCursorFromFile (const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RegisterClipboardFormat -#define RegisterClipboardFormat error use qxeRegisterClipboardFormat or RegisterClipboardFormatA/RegisterClipboardFormatW +#undef LoadIcon +#define LoadIcon error_use_qxeLoadIcon_or_LoadIconA_and_LoadIconW #endif -UINT qxeRegisterClipboardFormat (const Extbyte * lpszFormat); +HICON qxeLoadIcon (HINSTANCE hInstance, const Extbyte * lpIconName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetClipboardFormatName -#define GetClipboardFormatName error use qxeGetClipboardFormatName or GetClipboardFormatNameA/GetClipboardFormatNameW +#undef LoadImage +#define LoadImage error_use_qxeLoadImage_or_LoadImageA_and_LoadImageW #endif -int qxeGetClipboardFormatName (UINT format, Extbyte * lpszFormatName, int cchMaxCount); +HANDLE qxeLoadImage (HINSTANCE arg1, const Extbyte * arg2, UINT arg3, int arg4, int arg5, UINT arg6); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CharToOem -#define CharToOem error use qxeCharToOem or CharToOemA/CharToOemW +#undef LoadString +#define LoadString error_use_qxeLoadString_or_LoadStringA_and_LoadStringW #endif -BOOL qxeCharToOem (const Extbyte * lpszSrc, LPSTR lpszDst); +int qxeLoadString (HINSTANCE hInstance, UINT uID, Extbyte * lpBuffer, int nBufferMax); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef OemToChar -#define OemToChar error use qxeOemToChar or OemToCharA/OemToCharW +#undef IsDialogMessage +#define IsDialogMessage error_use_qxeIsDialogMessage_or_IsDialogMessageA_and_IsDialogMessageW #endif -BOOL qxeOemToChar (LPCSTR lpszSrc, Extbyte * lpszDst); +BOOL qxeIsDialogMessage (HWND hDlg, LPMSG lpMsg); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CharToOemBuff -#define CharToOemBuff error use qxeCharToOemBuff or CharToOemBuffA/CharToOemBuffW +#undef DlgDirList +#define DlgDirList error_use_qxeDlgDirList_or_DlgDirListA_and_DlgDirListW #endif -BOOL qxeCharToOemBuff (const Extbyte * lpszSrc, LPSTR lpszDst, DWORD cchDstLength); +int qxeDlgDirList (HWND hDlg, Extbyte * lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef OemToCharBuff -#define OemToCharBuff error use qxeOemToCharBuff or OemToCharBuffA/OemToCharBuffW +#undef DlgDirSelectEx +#define DlgDirSelectEx error_use_qxeDlgDirSelectEx_or_DlgDirSelectExA_and_DlgDirSelectExW #endif -BOOL qxeOemToCharBuff (LPCSTR lpszSrc, Extbyte * lpszDst, DWORD cchDstLength); +BOOL qxeDlgDirSelectEx (HWND hDlg, Extbyte * lpString, int nCount, int nIDListBox); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CharUpper -#define CharUpper error use qxeCharUpper or CharUpperA/CharUpperW +#undef DlgDirListComboBox +#define DlgDirListComboBox error_use_qxeDlgDirListComboBox_or_DlgDirListComboBoxA_and_DlgDirListComboBoxW #endif -Extbyte * qxeCharUpper (Extbyte * lpsz); +int qxeDlgDirListComboBox (HWND hDlg, Extbyte * lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CharUpperBuff -#define CharUpperBuff error use qxeCharUpperBuff or CharUpperBuffA/CharUpperBuffW +#undef DlgDirSelectComboBoxEx +#define DlgDirSelectComboBoxEx error_use_qxeDlgDirSelectComboBoxEx_or_DlgDirSelectComboBoxExA_and_DlgDirSelectComboBoxExW #endif -DWORD qxeCharUpperBuff (Extbyte * lpsz, DWORD cchLength); +BOOL qxeDlgDirSelectComboBoxEx (HWND hDlg, Extbyte * lpString, int nCount, int nIDComboBox); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CharLower -#define CharLower error use qxeCharLower or CharLowerA/CharLowerW +#undef DefFrameProc +#define DefFrameProc error_use_qxeDefFrameProc_or_DefFrameProcA_and_DefFrameProcW #endif -Extbyte * qxeCharLower (Extbyte * lpsz); +LRESULT qxeDefFrameProc (HWND hWnd, HWND hWndMDIClient, UINT uMsg, WPARAM wParam, LPARAM lParam); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CharLowerBuff -#define CharLowerBuff error use qxeCharLowerBuff or CharLowerBuffA/CharLowerBuffW -#endif -DWORD qxeCharLowerBuff (Extbyte * lpsz, DWORD cchLength); +#undef DefMDIChildProc +#define DefMDIChildProc error_return_value_is_conditionalized_on__MAC__messes_up_parser #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CharNext -#define CharNext error use qxeCharNext or CharNextA/CharNextW +#undef CreateMDIWindow +#define CreateMDIWindow error_use_qxeCreateMDIWindow_or_CreateMDIWindowA_and_CreateMDIWindowW #endif -Extbyte * qxeCharNext (const Extbyte * lpsz); +HWND qxeCreateMDIWindow (Extbyte * lpClassName, Extbyte * lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HINSTANCE hInstance, LPARAM lParam); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CharPrev -#define CharPrev error use qxeCharPrev or CharPrevA/CharPrevW +#undef WinHelp +#define WinHelp error_use_qxeWinHelp_or_WinHelpA_and_WinHelpW #endif -Extbyte * qxeCharPrev (const Extbyte * lpszStart, const Extbyte * lpszCurrent); +BOOL qxeWinHelp (HWND hWndMain, const Extbyte * lpszHelp, UINT uCommand, DWORD dwData); -#undef IsCharAlpha -#define IsCharAlpha error split CHAR +#undef ChangeDisplaySettings +#define ChangeDisplaySettings error_split_sized_LPDEVMODE -#undef IsCharAlphaNumeric -#define IsCharAlphaNumeric error split CHAR +#undef ChangeDisplaySettingsEx +#define ChangeDisplaySettingsEx error_split_sized_LPDEVMODE__NT_5_0_Win98__only -#undef IsCharUpper -#define IsCharUpper error split CHAR +#undef EnumDisplaySettings +#define EnumDisplaySettings error_split_sized_LPDEVMODE -#undef IsCharLower -#define IsCharLower error split CHAR +#undef EnumDisplayDevices +#define EnumDisplayDevices error_split_sized_PDISPLAY_DEVICE__NT_5_0__only__no_Win98 #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetKeyNameText -#define GetKeyNameText error use qxeGetKeyNameText or GetKeyNameTextA/GetKeyNameTextW +#undef SystemParametersInfo +#define SystemParametersInfo error_use_qxeSystemParametersInfo_or_SystemParametersInfoA_and_SystemParametersInfoW #endif -int qxeGetKeyNameText (LONG lParam, Extbyte * lpString, int nSize); +BOOL qxeSystemParametersInfo (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); -/* Skipping VkKeyScan because split CHAR */ +#undef GetMonitorInfo +#define GetMonitorInfo error_NT_5_0_Win98__only -#undef VkKeyScanEx -#define VkKeyScanEx error split CHAR; NT 4.0+ only +#undef GetWindowModuleFileName +#define GetWindowModuleFileName error_NT_5_0__only + +#undef RealGetWindowClass +#define RealGetWindowClass error_NT_5_0__only + +#undef GetAltTabInfo +#define GetAltTabInfo error_NT_5_0__only + + +/* Processing file DDEML.H */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef MapVirtualKey -#define MapVirtualKey error use qxeMapVirtualKey or MapVirtualKeyA/MapVirtualKeyW +#undef DdeInitialize +#define DdeInitialize error_use_qxeDdeInitialize_or_DdeInitializeA_and_DdeInitializeW #endif -UINT qxeMapVirtualKey (UINT uCode, UINT uMapType); +UINT qxeDdeInitialize (LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes); + +/* Skipping DdeCreateStringHandle because error in Cygwin prototype */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef MapVirtualKeyEx -#define MapVirtualKeyEx error use qxeMapVirtualKeyEx or MapVirtualKeyExA/MapVirtualKeyExW +#undef DdeQueryString +#define DdeQueryString error_use_qxeDdeQueryString_or_DdeQueryStringA_and_DdeQueryStringW #endif -UINT qxeMapVirtualKeyEx (UINT uCode, UINT uMapType, HKL dwhkl); +DWORD qxeDdeQueryString (DWORD idInst, HSZ hsz, Extbyte * psz, DWORD cchMax, int iCodePage); + + +/* Processing file WINREG.H */ + +/* Skipping RegConnectRegistry because error in Cygwin prototype */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadAccelerators -#define LoadAccelerators error use qxeLoadAccelerators or LoadAcceleratorsA/LoadAcceleratorsW +#undef RegCreateKey +#define RegCreateKey error_use_qxeRegCreateKey_or_RegCreateKeyA_and_RegCreateKeyW #endif -HACCEL qxeLoadAccelerators (HINSTANCE hInstance, const Extbyte * lpTableName); +LONG + qxeRegCreateKey (HKEY hKey, const Extbyte * lpSubKey, PHKEY phkResult); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateAcceleratorTable -#define CreateAcceleratorTable error use qxeCreateAcceleratorTable or CreateAcceleratorTableA/CreateAcceleratorTableW +#undef RegCreateKeyEx +#define RegCreateKeyEx error_use_qxeRegCreateKeyEx_or_RegCreateKeyExA_and_RegCreateKeyExW #endif -HACCEL qxeCreateAcceleratorTable (LPACCEL arg1, int arg2); +LONG + qxeRegCreateKeyEx (HKEY hKey, const Extbyte * lpSubKey, DWORD Reserved, Extbyte * lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CopyAcceleratorTable -#define CopyAcceleratorTable error use qxeCopyAcceleratorTable or CopyAcceleratorTableA/CopyAcceleratorTableW +#undef RegDeleteKey +#define RegDeleteKey error_use_qxeRegDeleteKey_or_RegDeleteKeyA_and_RegDeleteKeyW #endif -int qxeCopyAcceleratorTable (HACCEL hAccelSrc, LPACCEL lpAccelDst, int cAccelEntries); +LONG + qxeRegDeleteKey (HKEY hKey, const Extbyte * lpSubKey); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef TranslateAccelerator -#define TranslateAccelerator error use qxeTranslateAccelerator or TranslateAcceleratorA/TranslateAcceleratorW +#undef RegDeleteValue +#define RegDeleteValue error_use_qxeRegDeleteValue_or_RegDeleteValueA_and_RegDeleteValueW #endif -int qxeTranslateAccelerator (HWND hWnd, HACCEL hAccTable, LPMSG lpMsg); +LONG + qxeRegDeleteValue (HKEY hKey, const Extbyte * lpValueName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadMenu -#define LoadMenu error use qxeLoadMenu or LoadMenuA/LoadMenuW +#undef RegEnumKey +#define RegEnumKey error_use_qxeRegEnumKey_or_RegEnumKeyA_and_RegEnumKeyW #endif -HMENU qxeLoadMenu (HINSTANCE hInstance, const Extbyte * lpMenuName); +LONG + qxeRegEnumKey (HKEY hKey, DWORD dwIndex, Extbyte * lpName, DWORD cbName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadMenuIndirect -#define LoadMenuIndirect error use qxeLoadMenuIndirect or LoadMenuIndirectA/LoadMenuIndirectW +#undef RegEnumKeyEx +#define RegEnumKeyEx error_use_qxeRegEnumKeyEx_or_RegEnumKeyExA_and_RegEnumKeyExW #endif -HMENU qxeLoadMenuIndirect (CONST MENUTEMPLATEW * lpMenuTemplate); +LONG + qxeRegEnumKeyEx (HKEY hKey, DWORD dwIndex, Extbyte * lpName, LPDWORD lpcbName, LPDWORD lpReserved, Extbyte * lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ChangeMenu -#define ChangeMenu error use qxeChangeMenu or ChangeMenuA/ChangeMenuW +#undef RegEnumValue +#define RegEnumValue error_use_qxeRegEnumValue_or_RegEnumValueA_and_RegEnumValueW #endif -BOOL qxeChangeMenu (HMENU hMenu, UINT cmd, const Extbyte * lpszNewItem, UINT cmdInsert, UINT flags); +LONG + qxeRegEnumValue (HKEY hKey, DWORD dwIndex, Extbyte * lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetMenuString -#define GetMenuString error use qxeGetMenuString or GetMenuStringA/GetMenuStringW +#undef RegLoadKey +#define RegLoadKey error_use_qxeRegLoadKey_or_RegLoadKeyA_and_RegLoadKeyW #endif -int qxeGetMenuString (HMENU hMenu, UINT uIDItem, Extbyte * lpString, int nMaxCount, UINT uFlag); +LONG + qxeRegLoadKey (HKEY hKey, const Extbyte * lpSubKey, const Extbyte * lpFile); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef InsertMenu -#define InsertMenu error use qxeInsertMenu or InsertMenuA/InsertMenuW +#undef RegOpenKey +#define RegOpenKey error_use_qxeRegOpenKey_or_RegOpenKeyA_and_RegOpenKeyW #endif -BOOL qxeInsertMenu (HMENU hMenu, UINT uPosition, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem); +LONG + qxeRegOpenKey (HKEY hKey, const Extbyte * lpSubKey, PHKEY phkResult); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef AppendMenu -#define AppendMenu error use qxeAppendMenu or AppendMenuA/AppendMenuW +#undef RegOpenKeyEx +#define RegOpenKeyEx error_use_qxeRegOpenKeyEx_or_RegOpenKeyExA_and_RegOpenKeyExW #endif -BOOL qxeAppendMenu (HMENU hMenu, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem); +LONG + qxeRegOpenKeyEx (HKEY hKey, const Extbyte * lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ModifyMenu -#define ModifyMenu error use qxeModifyMenu or ModifyMenuA/ModifyMenuW +#undef RegQueryInfoKey +#define RegQueryInfoKey error_use_qxeRegQueryInfoKey_or_RegQueryInfoKeyA_and_RegQueryInfoKeyW #endif -BOOL qxeModifyMenu (HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, const Extbyte * lpNewItem); +LONG + qxeRegQueryInfoKey (HKEY hKey, Extbyte * lpClass, LPDWORD lpcbClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen, LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef InsertMenuItem -#define InsertMenuItem error use qxeInsertMenuItem or InsertMenuItemA/InsertMenuItemW +#undef RegQueryValue +#define RegQueryValue error_use_qxeRegQueryValue_or_RegQueryValueA_and_RegQueryValueW #endif -BOOL qxeInsertMenuItem (HMENU arg1, UINT arg2, BOOL arg3, LPCMENUITEMINFOW arg4); +LONG + qxeRegQueryValue (HKEY hKey, const Extbyte * lpSubKey, Extbyte * lpValue, PLONG lpcbValue); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetMenuItemInfo -#define GetMenuItemInfo error use qxeGetMenuItemInfo or GetMenuItemInfoA/GetMenuItemInfoW +#undef RegQueryMultipleValues +#define RegQueryMultipleValues error_use_qxeRegQueryMultipleValues_or_RegQueryMultipleValuesA_and_RegQueryMultipleValuesW #endif -BOOL qxeGetMenuItemInfo (HMENU arg1, UINT arg2, BOOL arg3, LPMENUITEMINFOW arg4); +LONG + qxeRegQueryMultipleValues (HKEY hKey, PVALENTW val_list, DWORD num_vals, Extbyte * lpValueBuf, LPDWORD ldwTotsize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetMenuItemInfo -#define SetMenuItemInfo error use qxeSetMenuItemInfo or SetMenuItemInfoA/SetMenuItemInfoW +#undef RegQueryValueEx +#define RegQueryValueEx error_use_qxeRegQueryValueEx_or_RegQueryValueExA_and_RegQueryValueExW #endif -BOOL qxeSetMenuItemInfo (HMENU arg1, UINT arg2, BOOL arg3, LPCMENUITEMINFOW arg4); +LONG + qxeRegQueryValueEx (HKEY hKey, const Extbyte * lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DrawText -#define DrawText error use qxeDrawText or DrawTextA/DrawTextW +#undef RegReplaceKey +#define RegReplaceKey error_use_qxeRegReplaceKey_or_RegReplaceKeyA_and_RegReplaceKeyW #endif -int qxeDrawText (HDC hDC, const Extbyte * lpString, int nCount, LPRECT lpRect, UINT uFormat); +LONG + qxeRegReplaceKey (HKEY hKey, const Extbyte * lpSubKey, const Extbyte * lpNewFile, const Extbyte * lpOldFile); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DrawTextEx -#define DrawTextEx error use qxeDrawTextEx or DrawTextExA/DrawTextExW +#undef RegRestoreKey +#define RegRestoreKey error_use_qxeRegRestoreKey_or_RegRestoreKeyA_and_RegRestoreKeyW #endif -int qxeDrawTextEx (HDC arg1, Extbyte * arg2, int arg3, LPRECT arg4, UINT arg5, LPDRAWTEXTPARAMS arg6); +LONG + qxeRegRestoreKey (HKEY hKey, const Extbyte * lpFile, DWORD dwFlags); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GrayString -#define GrayString error use qxeGrayString or GrayStringA/GrayStringW +#undef RegSaveKey +#define RegSaveKey error_use_qxeRegSaveKey_or_RegSaveKeyA_and_RegSaveKeyW #endif -BOOL qxeGrayString (HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int X, int Y, int nWidth, int nHeight); +LONG + qxeRegSaveKey (HKEY hKey, const Extbyte * lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DrawState -#define DrawState error use qxeDrawState or DrawStateA/DrawStateW +#undef RegSetValue +#define RegSetValue error_use_qxeRegSetValue_or_RegSetValueA_and_RegSetValueW #endif -BOOL qxeDrawState (HDC arg1, HBRUSH arg2, DRAWSTATEPROC arg3, LPARAM arg4, WPARAM arg5, int arg6, int arg7, int arg8, int arg9, UINT arg10); +LONG + qxeRegSetValue (HKEY hKey, const Extbyte * lpSubKey, DWORD dwType, const Extbyte * lpData, DWORD cbData); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef TabbedTextOut -#define TabbedTextOut error use qxeTabbedTextOut or TabbedTextOutA/TabbedTextOutW +#undef RegSetValueEx +#define RegSetValueEx error_use_qxeRegSetValueEx_or_RegSetValueExA_and_RegSetValueExW #endif -LONG qxeTabbedTextOut (HDC hDC, int X, int Y, const Extbyte * lpString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin); +LONG + qxeRegSetValueEx (HKEY hKey, const Extbyte * lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetTabbedTextExtent -#define GetTabbedTextExtent error use qxeGetTabbedTextExtent or GetTabbedTextExtentA/GetTabbedTextExtentW +#undef RegUnLoadKey +#define RegUnLoadKey error_use_qxeRegUnLoadKey_or_RegUnLoadKeyA_and_RegUnLoadKeyW #endif -DWORD qxeGetTabbedTextExtent (HDC hDC, const Extbyte * lpString, int nCount, int nTabPositions, LPINT lpnTabStopPositions); +LONG + qxeRegUnLoadKey (HKEY hKey, const Extbyte * lpSubKey); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetProp -#define SetProp error use qxeSetProp or SetPropA/SetPropW +#undef InitiateSystemShutdown +#define InitiateSystemShutdown error_use_qxeInitiateSystemShutdown_or_InitiateSystemShutdownA_and_InitiateSystemShutdownW #endif -BOOL qxeSetProp (HWND hWnd, const Extbyte * lpString, HANDLE hData); +BOOL + qxeInitiateSystemShutdown (Extbyte * lpMachineName, Extbyte * lpMessage, DWORD dwTimeout, BOOL bForceAppsClosed, BOOL bRebootAfterShutdown); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetProp -#define GetProp error use qxeGetProp or GetPropA/GetPropW +#undef AbortSystemShutdown +#define AbortSystemShutdown error_use_qxeAbortSystemShutdown_or_AbortSystemShutdownA_and_AbortSystemShutdownW #endif -HANDLE qxeGetProp (HWND hWnd, const Extbyte * lpString); +BOOL + qxeAbortSystemShutdown (Extbyte * lpMachineName); + + +/* Processing file WINNLS.H */ + +#undef GetCPInfoEx +#define GetCPInfoEx error_not_used__not_examined_yet + +#undef CompareString +#define CompareString error_not_used__not_examined_yet + +#undef LCMapString +#define LCMapString error_not_used__not_examined_yet #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RemoveProp -#define RemoveProp error use qxeRemoveProp or RemovePropA/RemovePropW +#undef GetLocaleInfo +#define GetLocaleInfo error_use_qxeGetLocaleInfo_or_GetLocaleInfoA_and_GetLocaleInfoW #endif -HANDLE qxeRemoveProp (HWND hWnd, const Extbyte * lpString); +int qxeGetLocaleInfo (LCID Locale, LCTYPE LCType, Extbyte * lpLCData, int cchData); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef EnumPropsEx -#define EnumPropsEx error use qxeEnumPropsEx or EnumPropsExA/EnumPropsExW +#undef SetLocaleInfo +#define SetLocaleInfo error_use_qxeSetLocaleInfo_or_SetLocaleInfoA_and_SetLocaleInfoW #endif -int qxeEnumPropsEx (HWND hWnd, PROPENUMPROCEXW lpEnumFunc, LPARAM lParam); +BOOL qxeSetLocaleInfo (LCID Locale, LCTYPE LCType, const Extbyte * lpLCData); + +#undef GetTimeFormat +#define GetTimeFormat error_not_used__not_examined_yet + +#undef GetDateFormat +#define GetDateFormat error_not_used__not_examined_yet + +#undef GetNumberFormat +#define GetNumberFormat error_not_used__not_examined_yet + +#undef GetCurrencyFormat +#define GetCurrencyFormat error_not_used__not_examined_yet + +#undef EnumCalendarInfo +#define EnumCalendarInfo error_not_used__not_examined_yet + +#undef EnumCalendarInfoEx +#define EnumCalendarInfoEx error_not_used__not_examined_yet + +#undef EnumTimeFormats +#define EnumTimeFormats error_not_used__not_examined_yet + +#undef EnumDateFormats +#define EnumDateFormats error_not_used__not_examined_yet + +#undef EnumDateFormatsEx +#define EnumDateFormatsEx error_not_used__not_examined_yet + +#undef GetStringTypeEx +#define GetStringTypeEx error_not_used__not_examined_yet + +#undef GetStringType +#define GetStringType error_no_such_fun__A_and_W_versions_have_different_nos__of_args + +#undef FoldString +#define FoldString error_not_used__not_examined_yet + +#undef EnumSystemLocales +#define EnumSystemLocales error_not_used__not_examined_yet + +#undef EnumSystemCodePages +#define EnumSystemCodePages error_not_used__not_examined_yet + + +/* Processing file IME.H */ + +#undef SendIMEMessageEx +#define SendIMEMessageEx error_obsolete__no_docs_available + + +/* Processing file WINGDI.H */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef EnumProps -#define EnumProps error use qxeEnumProps or EnumPropsA/EnumPropsW +#undef AddFontResource +#define AddFontResource error_use_qxeAddFontResource_or_AddFontResourceA_and_AddFontResourceW #endif -int qxeEnumProps (HWND hWnd, PROPENUMPROCW lpEnumFunc); +int qxeAddFontResource (const Extbyte * arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetWindowText -#define SetWindowText error use qxeSetWindowText or SetWindowTextA/SetWindowTextW +#undef CopyMetaFile +#define CopyMetaFile error_use_qxeCopyMetaFile_or_CopyMetaFileA_and_CopyMetaFileW #endif -BOOL qxeSetWindowText (HWND hWnd, const Extbyte * lpString); +HMETAFILE qxeCopyMetaFile (HMETAFILE arg1, const Extbyte * arg2); + +/* Skipping CreateDC because split-sized DEVMODE */ + +/* Skipping CreateFontIndirect because split-sized LOGFONT */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetWindowText -#define GetWindowText error use qxeGetWindowText or GetWindowTextA/GetWindowTextW +#undef CreateFont +#define CreateFont error_use_qxeCreateFont_or_CreateFontA_and_CreateFontW #endif -int qxeGetWindowText (HWND hWnd, Extbyte * lpString, int nMaxCount); +HFONT qxeCreateFont (int arg1, int arg2, int arg3, int arg4, int arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD arg10, DWORD arg11, DWORD arg12, DWORD arg13, const Extbyte * arg14); + +/* Skipping CreateIC because split-sized DEVMODE */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetWindowTextLength -#define GetWindowTextLength error use qxeGetWindowTextLength or GetWindowTextLengthA/GetWindowTextLengthW +#undef CreateMetaFile +#define CreateMetaFile error_use_qxeCreateMetaFile_or_CreateMetaFileA_and_CreateMetaFileW #endif -int qxeGetWindowTextLength (HWND hWnd); +HDC qxeCreateMetaFile (const Extbyte * arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef MessageBox -#define MessageBox error use qxeMessageBox or MessageBoxA/MessageBoxW +#undef CreateScalableFontResource +#define CreateScalableFontResource error_use_qxeCreateScalableFontResource_or_CreateScalableFontResourceA_and_CreateScalableFontResourceW #endif -int qxeMessageBox (HWND hWnd, const Extbyte * lpText, const Extbyte * lpCaption, UINT uType); +BOOL qxeCreateScalableFontResource (DWORD arg1, const Extbyte * arg2, const Extbyte * arg3, const Extbyte * arg4); + +/* Skipping DeviceCapabilities because split-sized DEVMODE */ + +/* Skipping EnumFontFamiliesEx because split-complex FONTENUMPROC; NT 4.0+ only */ + +#undef EnumFontFamilies +#define EnumFontFamilies error_split_complex_FONTENUMPROC + +#undef EnumFonts +#define EnumFonts error_split_complex_FONTENUMPROC #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef MessageBoxEx -#define MessageBoxEx error use qxeMessageBoxEx or MessageBoxExA/MessageBoxExW +#undef GetCharWidth +#define GetCharWidth error_use_qxeGetCharWidth_or_GetCharWidthA_and_GetCharWidthW #endif -int qxeMessageBoxEx (HWND hWnd, const Extbyte * lpText, const Extbyte * lpCaption, UINT uType, WORD wLanguageId); +BOOL qxeGetCharWidth (HDC arg1, UINT arg2, UINT arg3, LPINT arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef MessageBoxIndirect -#define MessageBoxIndirect error use qxeMessageBoxIndirect or MessageBoxIndirectA/MessageBoxIndirectW +#undef GetCharWidth32 +#define GetCharWidth32 error_use_qxeGetCharWidth32_or_GetCharWidth32A_and_GetCharWidth32W #endif -int qxeMessageBoxIndirect (LPMSGBOXPARAMSW arg1); +BOOL qxeGetCharWidth32 (HDC arg1, UINT arg2, UINT arg3, LPINT arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetWindowLong -#define GetWindowLong error use qxeGetWindowLong or GetWindowLongA/GetWindowLongW +#undef GetCharWidthFloat +#define GetCharWidthFloat error_use_qxeGetCharWidthFloat_or_GetCharWidthFloatA_and_GetCharWidthFloatW #endif -LONG qxeGetWindowLong (HWND hWnd, int nIndex); +BOOL qxeGetCharWidthFloat (HDC arg1, UINT arg2, UINT arg3, PFLOAT arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetWindowLong -#define SetWindowLong error use qxeSetWindowLong or SetWindowLongA/SetWindowLongW +#undef GetCharABCWidths +#define GetCharABCWidths error_use_qxeGetCharABCWidths_or_GetCharABCWidthsA_and_GetCharABCWidthsW #endif -LONG qxeSetWindowLong (HWND hWnd, int nIndex, LONG dwNewLong); +BOOL qxeGetCharABCWidths (HDC arg1, UINT arg2, UINT arg3, LPABC arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetClassLong -#define GetClassLong error use qxeGetClassLong or GetClassLongA/GetClassLongW +#undef GetCharABCWidthsFloat +#define GetCharABCWidthsFloat error_use_qxeGetCharABCWidthsFloat_or_GetCharABCWidthsFloatA_and_GetCharABCWidthsFloatW #endif -DWORD qxeGetClassLong (HWND hWnd, int nIndex); +BOOL qxeGetCharABCWidthsFloat (HDC arg1, UINT arg2, UINT arg3, LPABCFLOAT arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetClassLong -#define SetClassLong error use qxeSetClassLong or SetClassLongA/SetClassLongW +#undef GetGlyphOutline +#define GetGlyphOutline error_use_qxeGetGlyphOutline_or_GetGlyphOutlineA_and_GetGlyphOutlineW #endif -DWORD qxeSetClassLong (HWND hWnd, int nIndex, LONG dwNewLong); +DWORD qxeGetGlyphOutline (HDC arg1, UINT arg2, UINT arg3, LPGLYPHMETRICS arg4, DWORD arg5, LPVOID arg6, CONST MAT2 * arg7); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef FindWindow -#define FindWindow error use qxeFindWindow or FindWindowA/FindWindowW +#undef GetMetaFile +#define GetMetaFile error_use_qxeGetMetaFile_or_GetMetaFileA_and_GetMetaFileW #endif -HWND qxeFindWindow (const Extbyte * lpClassName, const Extbyte * lpWindowName); +HMETAFILE qxeGetMetaFile (const Extbyte * arg1); + +#undef GetOutlineTextMetrics +#define GetOutlineTextMetrics error_split_sized_LPOUTLINETEXTMETRIC #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef FindWindowEx -#define FindWindowEx error use qxeFindWindowEx or FindWindowExA/FindWindowExW +#undef GetTextExtentPoint +#define GetTextExtentPoint error_use_qxeGetTextExtentPoint_or_GetTextExtentPointA_and_GetTextExtentPointW #endif -HWND qxeFindWindowEx (HWND arg1, HWND arg2, const Extbyte * arg3, const Extbyte * arg4); +BOOL qxeGetTextExtentPoint (HDC arg1, const Extbyte * arg2, int arg3, LPSIZE arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetClassName -#define GetClassName error use qxeGetClassName or GetClassNameA/GetClassNameW +#undef GetTextExtentPoint32 +#define GetTextExtentPoint32 error_use_qxeGetTextExtentPoint32_or_GetTextExtentPoint32A_and_GetTextExtentPoint32W #endif -int qxeGetClassName (HWND hWnd, Extbyte * lpClassName, int nMaxCount); - -#undef SetWindowsHook -#define SetWindowsHook error obsolete; two versions, STRICT and non-STRICT - -#undef SetWindowsHook -#define SetWindowsHook error obsolete; two versions, STRICT and non-STRICT +BOOL qxeGetTextExtentPoint32 (HDC arg1, const Extbyte * arg2, int arg3, LPSIZE arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetWindowsHookEx -#define SetWindowsHookEx error use qxeSetWindowsHookEx or SetWindowsHookExA/SetWindowsHookExW +#undef GetTextExtentExPoint +#define GetTextExtentExPoint error_use_qxeGetTextExtentExPoint_or_GetTextExtentExPointA_and_GetTextExtentExPointW #endif -HHOOK qxeSetWindowsHookEx (int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId); +BOOL qxeGetTextExtentExPoint (HDC arg1, const Extbyte * arg2, int arg3, int arg4, LPINT arg5, LPINT arg6, LPSIZE arg7); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadBitmap -#define LoadBitmap error use qxeLoadBitmap or LoadBitmapA/LoadBitmapW +#undef GetCharacterPlacement +#define GetCharacterPlacement error_use_qxeGetCharacterPlacement_or_GetCharacterPlacementA_and_GetCharacterPlacementW #endif -HBITMAP qxeLoadBitmap (HINSTANCE hInstance, const Extbyte * lpBitmapName); +DWORD qxeGetCharacterPlacement (HDC arg1, const Extbyte * arg2, int arg3, int arg4, LPGCP_RESULTSW arg5, DWORD arg6); + +#undef GetGlyphIndices +#define GetGlyphIndices error_NT_5_0__only + +#undef AddFontResourceEx +#define AddFontResourceEx error_NT_5_0__only + +#undef RemoveFontResourceEx +#define RemoveFontResourceEx error_NT_5_0__only + +#undef CreateFontIndirectEx +#define CreateFontIndirectEx error_split_sized_ENUMLOGFONTEXDV__NT_5_0__only + +/* Skipping ResetDC because split-sized DEVMODE */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadCursor -#define LoadCursor error use qxeLoadCursor or LoadCursorA/LoadCursorW +#undef RemoveFontResource +#define RemoveFontResource error_use_qxeRemoveFontResource_or_RemoveFontResourceA_and_RemoveFontResourceW #endif -HCURSOR qxeLoadCursor (HINSTANCE hInstance, const Extbyte * lpCursorName); +BOOL qxeRemoveFontResource (const Extbyte * arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadCursorFromFile -#define LoadCursorFromFile error use qxeLoadCursorFromFile or LoadCursorFromFileA/LoadCursorFromFileW +#undef CopyEnhMetaFile +#define CopyEnhMetaFile error_use_qxeCopyEnhMetaFile_or_CopyEnhMetaFileA_and_CopyEnhMetaFileW #endif -HCURSOR qxeLoadCursorFromFile (const Extbyte * lpFileName); +HENHMETAFILE qxeCopyEnhMetaFile (HENHMETAFILE arg1, const Extbyte * arg2); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadIcon -#define LoadIcon error use qxeLoadIcon or LoadIconA/LoadIconW +#undef CreateEnhMetaFile +#define CreateEnhMetaFile error_use_qxeCreateEnhMetaFile_or_CreateEnhMetaFileA_and_CreateEnhMetaFileW #endif -HICON qxeLoadIcon (HINSTANCE hInstance, const Extbyte * lpIconName); +HDC qxeCreateEnhMetaFile (HDC arg1, const Extbyte * arg2, CONST RECT * arg3, const Extbyte * arg4); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadImage -#define LoadImage error use qxeLoadImage or LoadImageA/LoadImageW +#undef GetEnhMetaFile +#define GetEnhMetaFile error_use_qxeGetEnhMetaFile_or_GetEnhMetaFileA_and_GetEnhMetaFileW #endif -HANDLE qxeLoadImage (HINSTANCE arg1, const Extbyte * arg2, UINT arg3, int arg4, int arg5, UINT arg6); +HENHMETAFILE qxeGetEnhMetaFile (const Extbyte * arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef LoadString -#define LoadString error use qxeLoadString or LoadStringA/LoadStringW +#undef GetEnhMetaFileDescription +#define GetEnhMetaFileDescription error_use_qxeGetEnhMetaFileDescription_or_GetEnhMetaFileDescriptionA_and_GetEnhMetaFileDescriptionW #endif -int qxeLoadString (HINSTANCE hInstance, UINT uID, Extbyte * lpBuffer, int nBufferMax); +UINT qxeGetEnhMetaFileDescription (HENHMETAFILE arg1, UINT arg2, Extbyte * arg3); + +/* Skipping GetTextMetrics because split-sized LPTEXTMETRIC */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef IsDialogMessage -#define IsDialogMessage error use qxeIsDialogMessage or IsDialogMessageA/IsDialogMessageW +#undef StartDoc +#define StartDoc error_use_qxeStartDoc_or_StartDocA_and_StartDocW #endif -BOOL qxeIsDialogMessage (HWND hDlg, LPMSG lpMsg); +int qxeStartDoc (HDC arg1, CONST DOCINFOW * arg2); + +/* Skipping GetObject because split-sized LOGFONT */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DlgDirList -#define DlgDirList error use qxeDlgDirList or DlgDirListA/DlgDirListW +#undef TextOut +#define TextOut error_use_qxeTextOut_or_TextOutA_and_TextOutW #endif -int qxeDlgDirList (HWND hDlg, Extbyte * lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType); +BOOL qxeTextOut (HDC arg1, int arg2, int arg3, const Extbyte * arg4, int arg5); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DlgDirSelectEx -#define DlgDirSelectEx error use qxeDlgDirSelectEx or DlgDirSelectExA/DlgDirSelectExW +#undef ExtTextOut +#define ExtTextOut error_use_qxeExtTextOut_or_ExtTextOutA_and_ExtTextOutW #endif -BOOL qxeDlgDirSelectEx (HWND hDlg, Extbyte * lpString, int nCount, int nIDListBox); +BOOL qxeExtTextOut (HDC arg1, int arg2, int arg3, UINT arg4, CONST RECT * arg5, const Extbyte * arg6, UINT arg7, CONST INT * arg8); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DlgDirListComboBox -#define DlgDirListComboBox error use qxeDlgDirListComboBox or DlgDirListComboBoxA/DlgDirListComboBoxW +#undef PolyTextOut +#define PolyTextOut error_use_qxePolyTextOut_or_PolyTextOutA_and_PolyTextOutW #endif -int qxeDlgDirListComboBox (HWND hDlg, Extbyte * lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype); +BOOL qxePolyTextOut (HDC arg1, CONST POLYTEXTW * arg2, int arg3); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DlgDirSelectComboBoxEx -#define DlgDirSelectComboBoxEx error use qxeDlgDirSelectComboBoxEx or DlgDirSelectComboBoxExA/DlgDirSelectComboBoxExW +#undef GetTextFace +#define GetTextFace error_use_qxeGetTextFace_or_GetTextFaceA_and_GetTextFaceW #endif -BOOL qxeDlgDirSelectComboBoxEx (HWND hDlg, Extbyte * lpString, int nCount, int nIDComboBox); +int qxeGetTextFace (HDC arg1, int arg2, Extbyte * arg3); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef DefFrameProc -#define DefFrameProc error use qxeDefFrameProc or DefFrameProcA/DefFrameProcW +#undef GetKerningPairs +#define GetKerningPairs error_use_qxeGetKerningPairs_or_GetKerningPairsA_and_GetKerningPairsW #endif -LRESULT qxeDefFrameProc (HWND hWnd, HWND hWndMDIClient, UINT uMsg, WPARAM wParam, LPARAM lParam); +DWORD qxeGetKerningPairs (HDC arg1, DWORD arg2, LPKERNINGPAIR arg3); -#undef DefMDIChildProc -#define DefMDIChildProc error return value is conditionalized on _MAC, messes up parser +#undef GetLogColorSpace +#define GetLogColorSpace error_split_sized_LPLOGCOLORSPACE__NT_4_0__only + +#undef CreateColorSpace +#define CreateColorSpace error_split_sized_LPLOGCOLORSPACE__NT_4_0__only + +/* Skipping GetICMProfile because NT 4.0+ only, error in Cygwin prototype */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateMDIWindow -#define CreateMDIWindow error use qxeCreateMDIWindow or CreateMDIWindowA/CreateMDIWindowW +#undef SetICMProfile +#define SetICMProfile error_use_qxeSetICMProfile_or_SetICMProfileA_and_SetICMProfileW #endif -HWND qxeCreateMDIWindow (Extbyte * lpClassName, Extbyte * lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HINSTANCE hInstance, LPARAM lParam); +BOOL qxeSetICMProfile (HDC arg1, Extbyte * arg2); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef WinHelp -#define WinHelp error use qxeWinHelp or WinHelpA/WinHelpW +#undef EnumICMProfiles +#define EnumICMProfiles error_use_qxeEnumICMProfiles_or_EnumICMProfilesA_and_EnumICMProfilesW #endif -BOOL qxeWinHelp (HWND hWndMain, const Extbyte * lpszHelp, UINT uCommand, DWORD dwData); +int qxeEnumICMProfiles (HDC arg1, ICMENUMPROCW arg2, LPARAM arg3); -#undef ChangeDisplaySettings -#define ChangeDisplaySettings error split-sized LPDEVMODE +/* Skipping UpdateICMRegKey because NT 4.0+ only, error in Cygwin prototype */ -#undef ChangeDisplaySettingsEx -#define ChangeDisplaySettingsEx error split-sized LPDEVMODE; NT 5.0/Win98+ only +#undef wglUseFontBitmaps +#define wglUseFontBitmaps error_causes_link_error -#undef EnumDisplaySettings -#define EnumDisplaySettings error split-sized LPDEVMODE +#undef wglUseFontOutlines +#define wglUseFontOutlines error_causes_link_error -#undef EnumDisplayDevices -#define EnumDisplayDevices error split-sized PDISPLAY_DEVICE; NT 5.0+ only, no Win98 + +/* Processing file SHLOBJ.H */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SystemParametersInfo -#define SystemParametersInfo error use qxeSystemParametersInfo or SystemParametersInfoA/SystemParametersInfoW +#undef SHGetPathFromIDList +#define SHGetPathFromIDList error_use_qxeSHGetPathFromIDList_or_SHGetPathFromIDListA_and_SHGetPathFromIDListW #endif -BOOL qxeSystemParametersInfo (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); - -#undef GetMonitorInfo -#define GetMonitorInfo error NT 5.0/Win98+ only +BOOL qxeSHGetPathFromIDList (LPCITEMIDLIST pidl, Extbyte * pszPath); -#undef GetWindowModuleFileName -#define GetWindowModuleFileName error NT 5.0+ only +/* Skipping SHGetSpecialFolderPath because error in Cygwin prototype, missing from Cygwin libraries */ -#undef RealGetWindowClass -#define RealGetWindowClass error NT 5.0+ only +/* Skipping SHBrowseForFolder because need to intercept callback for SendMessage */ -#undef GetAltTabInfo -#define GetAltTabInfo error NT 5.0+ only +/* Skipping SHGetDataFromIDList because split-sized WIN32_FIND_DATA or split-simple NETRESOURCE, missing from Cygwin libraries */ -/* Processing file MMSYSTEM.H */ +/* Processing file COMMDLG.H */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef sndPlaySound -#define sndPlaySound error use qxesndPlaySound or sndPlaySoundA/sndPlaySoundW +#undef GetOpenFileName +#define GetOpenFileName error_use_qxeGetOpenFileName_or_GetOpenFileNameA_and_GetOpenFileNameW #endif -BOOL qxesndPlaySound (const Extbyte * pszSound, UINT fuSound); +BOOL qxeGetOpenFileName (LPOPENFILENAMEW arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef PlaySound -#define PlaySound error use qxePlaySound or PlaySoundA/PlaySoundW +#undef GetSaveFileName +#define GetSaveFileName error_use_qxeGetSaveFileName_or_GetSaveFileNameA_and_GetSaveFileNameW #endif -BOOL qxePlaySound (const Extbyte * pszSound, HMODULE hmod, DWORD fdwSound); - -#undef waveOutGetDevCaps -#define waveOutGetDevCaps error split-sized LPWAVEOUTCAPS +BOOL qxeGetSaveFileName (LPOPENFILENAMEW arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef waveOutGetErrorText -#define waveOutGetErrorText error use qxewaveOutGetErrorText or waveOutGetErrorTextA/waveOutGetErrorTextW +#undef GetFileTitle +#define GetFileTitle error_use_qxeGetFileTitle_or_GetFileTitleA_and_GetFileTitleW #endif -MMRESULT qxewaveOutGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText); - -#undef waveInGetDevCaps -#define waveInGetDevCaps error split-sized LPWAVEINCAPS +short qxeGetFileTitle (const Extbyte * arg1, Extbyte * arg2, WORD arg3); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef waveInGetErrorText -#define waveInGetErrorText error use qxewaveInGetErrorText or waveInGetErrorTextA/waveInGetErrorTextW +#undef ChooseColor +#define ChooseColor error_use_qxeChooseColor_or_ChooseColorA_and_ChooseColorW #endif -MMRESULT qxewaveInGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText); +BOOL qxeChooseColor (LPCHOOSECOLORW arg1); -#undef midiOutGetDevCaps -#define midiOutGetDevCaps error split-sized LPMIDIOUTCAPS +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef FindText +#define FindText error_use_qxeFindText_or_FindTextA_and_FindTextW +#endif +HWND qxeFindText (LPFINDREPLACEW arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef midiOutGetErrorText -#define midiOutGetErrorText error use qxemidiOutGetErrorText or midiOutGetErrorTextA/midiOutGetErrorTextW +#undef ReplaceText +#define ReplaceText error_use_qxeReplaceText_or_ReplaceTextA_and_ReplaceTextW #endif -MMRESULT qxemidiOutGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText); +HWND qxeReplaceText (LPFINDREPLACEW arg1); -#undef midiInGetDevCaps -#define midiInGetDevCaps error split-sized LPMIDIOUTCAPS +#undef AfxReplaceText +#define AfxReplaceText error_mac_only + +#undef ChooseFont +#define ChooseFont error_split_sized_LPLOGFONT_in_LPCHOOSEFONT +/* Skipping PrintDlg because LPPRINTDLG with split-sized DEVMODE handle */ + +/* Skipping PageSetupDlg because LPPAGESETUPDLG with split-sized DEVMODE handle */ + + +/* Processing file IMM.H */ + +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef midiInGetErrorText -#define midiInGetErrorText error use qxemidiInGetErrorText or midiInGetErrorTextA/midiInGetErrorTextW +#undef ImmInstallIME +#define ImmInstallIME error_use_qxeImmInstallIME_or_ImmInstallIMEA_and_ImmInstallIMEW #endif -MMRESULT qxemidiInGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText); - -#undef auxGetDevCaps -#define auxGetDevCaps error split-sized LPAUXCAPS +HKL qxeImmInstallIME (const Extbyte * lpszIMEFileName, const Extbyte * lpszLayoutText); +#endif /* defined (HAVE_MS_WINDOWS) */ -#undef mixerGetDevCaps -#define mixerGetDevCaps error split-sized LPMIXERCAPS +#if defined (HAVE_MS_WINDOWS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ImmGetDescription +#define ImmGetDescription error_use_qxeImmGetDescription_or_ImmGetDescriptionA_and_ImmGetDescriptionW +#endif +UINT qxeImmGetDescription (HKL arg1, Extbyte * arg2, UINT uBufLen); +#endif /* defined (HAVE_MS_WINDOWS) */ -#undef mixerGetLineInfo -#define mixerGetLineInfo error split-sized LPMIXERLINE +#if defined (HAVE_MS_WINDOWS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ImmGetIMEFileName +#define ImmGetIMEFileName error_use_qxeImmGetIMEFileName_or_ImmGetIMEFileNameA_and_ImmGetIMEFileNameW +#endif +UINT qxeImmGetIMEFileName (HKL arg1, Extbyte * arg2, UINT uBufLen); +#endif /* defined (HAVE_MS_WINDOWS) */ -#undef mixerGetLineControls -#define mixerGetLineControls error split-sized LPMIXERCONTROL +#if defined (HAVE_MS_WINDOWS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ImmGetCompositionString +#define ImmGetCompositionString error_use_qxeImmGetCompositionString_or_ImmGetCompositionStringA_and_ImmGetCompositionStringW +#endif +LONG qxeImmGetCompositionString (HIMC arg1, DWORD arg2, LPVOID arg3, DWORD arg4); +#endif /* defined (HAVE_MS_WINDOWS) */ -#undef mixerGetControlDetails -#define mixerGetControlDetails error split-sized LPMIXERCONTROL in LPMIXERLINECONTROLS in LPMIXERCONTROLDETAILS +#if defined (HAVE_MS_WINDOWS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ImmGetCandidateListCount +#define ImmGetCandidateListCount error_use_qxeImmGetCandidateListCount_or_ImmGetCandidateListCountA_and_ImmGetCandidateListCountW +#endif +DWORD qxeImmGetCandidateListCount (HIMC arg1, LPDWORD lpdwListCount); +#endif /* defined (HAVE_MS_WINDOWS) */ -#undef joyGetDevCaps -#define joyGetDevCaps error split-sized LPJOYCAPS +#if defined (HAVE_MS_WINDOWS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ImmGetCandidateList +#define ImmGetCandidateList error_use_qxeImmGetCandidateList_or_ImmGetCandidateListA_and_ImmGetCandidateListW +#endif +DWORD qxeImmGetCandidateList (HIMC arg1, DWORD deIndex, LPCANDIDATELIST arg3, DWORD dwBufLen); +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef mmioStringToFOURCC -#define mmioStringToFOURCC error use qxemmioStringToFOURCC or mmioStringToFOURCCA/mmioStringToFOURCCW +#undef ImmGetGuideLine +#define ImmGetGuideLine error_use_qxeImmGetGuideLine_or_ImmGetGuideLineA_and_ImmGetGuideLineW #endif -FOURCC qxemmioStringToFOURCC (const Extbyte * sz, UINT uFlags); +DWORD qxeImmGetGuideLine (HIMC arg1, DWORD dwIndex, Extbyte * arg3, DWORD dwBufLen); +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) +/* Skipping ImmGetCompositionFont because split-sized LOGFONT */ +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) +/* Skipping ImmSetCompositionFont because split-sized LOGFONT */ +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef mmioInstallIOProc -#define mmioInstallIOProc error use qxemmioInstallIOProc or mmioInstallIOProcA/mmioInstallIOProcW +#undef ImmConfigureIME +#define ImmConfigureIME error_use_qxeImmConfigureIME_or_ImmConfigureIMEA_and_ImmConfigureIMEW #endif -LPMMIOPROC qxemmioInstallIOProc (FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags); +BOOL qxeImmConfigureIME (HKL arg1, HWND arg2, DWORD arg3, LPVOID arg4); +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef mmioOpen -#define mmioOpen error use qxemmioOpen or mmioOpenA/mmioOpenW +#undef ImmEscape +#define ImmEscape error_use_qxeImmEscape_or_ImmEscapeA_and_ImmEscapeW #endif -HMMIO qxemmioOpen (Extbyte * pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen); +LRESULT qxeImmEscape (HKL arg1, HIMC arg2, UINT arg3, LPVOID arg4); +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef mmioRename -#define mmioRename error use qxemmioRename or mmioRenameA/mmioRenameW +#undef ImmGetConversionList +#define ImmGetConversionList error_use_qxeImmGetConversionList_or_ImmGetConversionListA_and_ImmGetConversionListW #endif -MMRESULT qxemmioRename (const Extbyte * pszFileName, const Extbyte * pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename); +DWORD qxeImmGetConversionList (HKL arg1, HIMC arg2, const Extbyte * arg3, LPCANDIDATELIST arg4, DWORD dwBufLen, UINT uFlag); +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef mciSendCommand -#define mciSendCommand error use qxemciSendCommand or mciSendCommandA/mciSendCommandW +#undef ImmIsUIMessage +#define ImmIsUIMessage error_use_qxeImmIsUIMessage_or_ImmIsUIMessageA_and_ImmIsUIMessageW #endif -MCIERROR qxemciSendCommand (MCIDEVICEID mciId, UINT uMsg, DWORD dwParam1, DWORD dwParam2); +BOOL qxeImmIsUIMessage (HWND arg1, UINT arg2, WPARAM arg3, LPARAM arg4); +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef mciSendString -#define mciSendString error use qxemciSendString or mciSendStringA/mciSendStringW +#undef ImmRegisterWord +#define ImmRegisterWord error_use_qxeImmRegisterWord_or_ImmRegisterWordA_and_ImmRegisterWordW #endif -MCIERROR qxemciSendString (const Extbyte * lpstrCommand, Extbyte * lpstrReturnString, UINT uReturnLength, HWND hwndCallback); +BOOL qxeImmRegisterWord (HKL arg1, const Extbyte * lpszReading, DWORD arg3, const Extbyte * lpszRegister); +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef mciGetDeviceID -#define mciGetDeviceID error use qxemciGetDeviceID or mciGetDeviceIDA/mciGetDeviceIDW +#undef ImmUnregisterWord +#define ImmUnregisterWord error_use_qxeImmUnregisterWord_or_ImmUnregisterWordA_and_ImmUnregisterWordW #endif -MCIDEVICEID qxemciGetDeviceID (const Extbyte * pszDevice); +BOOL qxeImmUnregisterWord (HKL arg1, const Extbyte * lpszReading, DWORD arg3, const Extbyte * lpszUnregister); +#endif /* defined (HAVE_MS_WINDOWS) */ -#if !defined (MINGW) -#undef mciGetDeviceIDFromElementID -#define mciGetDeviceIDFromElementID error missing from Win98se version of ADVAPI32.dll -#endif /* !defined (MINGW) */ +#if defined (HAVE_MS_WINDOWS) +#undef ImmGetRegisterWordStyle +#define ImmGetRegisterWordStyle error_split_sized_STYLEBUF +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef mciGetErrorString -#define mciGetErrorString error use qxemciGetErrorString or mciGetErrorStringA/mciGetErrorStringW +#undef ImmEnumRegisterWord +#define ImmEnumRegisterWord error_use_qxeImmEnumRegisterWord_or_ImmEnumRegisterWordA_and_ImmEnumRegisterWordW #endif -BOOL qxemciGetErrorString (MCIERROR mcierr, Extbyte * pszText, UINT cchText); +UINT qxeImmEnumRegisterWord (HKL arg1, REGISTERWORDENUMPROCW arg2, const Extbyte * lpszReading, DWORD arg4, const Extbyte * lpszRegister, LPVOID arg6); +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) +#undef ImmGetImeMenuItems +#define ImmGetImeMenuItems error_split_sized_IMEMENUITEMINFO +#endif /* defined (HAVE_MS_WINDOWS) */ /* Processing file WINBASE.H */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetBinaryType -#define GetBinaryType error use qxeGetBinaryType or GetBinaryTypeA/GetBinaryTypeW +#define GetBinaryType error_use_qxeGetBinaryType_or_GetBinaryTypeA_and_GetBinaryTypeW #endif BOOL qxeGetBinaryType (const Extbyte * lpApplicationName, LPDWORD lpBinaryType); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetShortPathName -#define GetShortPathName error use qxeGetShortPathName or GetShortPathNameA/GetShortPathNameW +#define GetShortPathName error_use_qxeGetShortPathName_or_GetShortPathNameA_and_GetShortPathNameW #endif DWORD qxeGetShortPathName (const Extbyte * lpszLongPath, Extbyte * lpszShortPath, DWORD cchBuffer); #undef GetLongPathName -#define GetLongPathName error Win98/2K+ only +#define GetLongPathName error_Win98_2K__only /* Skipping GetEnvironmentStrings because misnamed ANSI version of the function */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef FreeEnvironmentStrings -#define FreeEnvironmentStrings error use qxeFreeEnvironmentStrings or FreeEnvironmentStringsA/FreeEnvironmentStringsW +#define FreeEnvironmentStrings error_use_qxeFreeEnvironmentStrings_or_FreeEnvironmentStringsA_and_FreeEnvironmentStringsW #endif BOOL qxeFreeEnvironmentStrings (Extbyte * arg1); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef FormatMessage -#define FormatMessage error use qxeFormatMessage or FormatMessageA/FormatMessageW +#define FormatMessage error_use_qxeFormatMessage_or_FormatMessageA_and_FormatMessageW #endif DWORD qxeFormatMessage (DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, Extbyte * lpBuffer, DWORD nSize, va_list * Arguments); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateMailslot -#define CreateMailslot error use qxeCreateMailslot or CreateMailslotA/CreateMailslotW +#define CreateMailslot error_use_qxeCreateMailslot_or_CreateMailslotA_and_CreateMailslotW #endif HANDLE qxeCreateMailslot (const Extbyte * lpName, DWORD nMaxMessageSize, DWORD lReadTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes); #if !defined (CYGWIN_HEADERS) #undef EncryptFile -#define EncryptFile error Win2K+ only +#define EncryptFile error_Win2K__only #endif /* !defined (CYGWIN_HEADERS) */ #if !defined (CYGWIN_HEADERS) #undef DecryptFile -#define DecryptFile error Win2K+ only +#define DecryptFile error_Win2K__only #endif /* !defined (CYGWIN_HEADERS) */ #undef OpenRaw -#define OpenRaw error error "The procedure entry point OpenRawW could not be located in the dynamic link library ADVAPI32.dll." +#define OpenRaw error_error__The_procedure_entry_point_OpenRawW_could_not_be_located_in_the_dynamic_link_library_ADVAPI32_dll__ #undef QueryRecoveryAgents -#define QueryRecoveryAgents error split-sized LPRECOVERY_AGENT_INFORMATION +#define QueryRecoveryAgents error_split_sized_LPRECOVERY_AGENT_INFORMATION #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef lstrcmp -#define lstrcmp error use qxelstrcmp or lstrcmpA/lstrcmpW +#define lstrcmp error_use_qxelstrcmp_or_lstrcmpA_and_lstrcmpW #endif int qxelstrcmp (const Extbyte * lpString1, const Extbyte * lpString2); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef lstrcmpi -#define lstrcmpi error use qxelstrcmpi or lstrcmpiA/lstrcmpiW +#define lstrcmpi error_use_qxelstrcmpi_or_lstrcmpiA_and_lstrcmpiW #endif int qxelstrcmpi (const Extbyte * lpString1, const Extbyte * lpString2); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef lstrcpyn -#define lstrcpyn error use qxelstrcpyn or lstrcpynA/lstrcpynW +#define lstrcpyn error_use_qxelstrcpyn_or_lstrcpynA_and_lstrcpynW #endif Extbyte * qxelstrcpyn (Extbyte * lpString1, const Extbyte * lpString2, int iMaxLength); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef lstrcpy -#define lstrcpy error use qxelstrcpy or lstrcpyA/lstrcpyW +#define lstrcpy error_use_qxelstrcpy_or_lstrcpyA_and_lstrcpyW #endif Extbyte * qxelstrcpy (Extbyte * lpString1, const Extbyte * lpString2); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef lstrcat -#define lstrcat error use qxelstrcat or lstrcatA/lstrcatW +#define lstrcat error_use_qxelstrcat_or_lstrcatA_and_lstrcatW #endif Extbyte * qxelstrcat (Extbyte * lpString1, const Extbyte * lpString2); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef lstrlen -#define lstrlen error use qxelstrlen or lstrlenA/lstrlenW +#define lstrlen error_use_qxelstrlen_or_lstrlenA_and_lstrlenW #endif int qxelstrlen (const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateMutex -#define CreateMutex error use qxeCreateMutex or CreateMutexA/CreateMutexW +#define CreateMutex error_use_qxeCreateMutex_or_CreateMutexA_and_CreateMutexW #endif HANDLE qxeCreateMutex (LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, const Extbyte * lpName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef OpenMutex -#define OpenMutex error use qxeOpenMutex or OpenMutexA/OpenMutexW +#define OpenMutex error_use_qxeOpenMutex_or_OpenMutexA_and_OpenMutexW #endif HANDLE qxeOpenMutex (DWORD dwDesiredAccess, BOOL bInheritHandle, const Extbyte * lpName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateEvent -#define CreateEvent error use qxeCreateEvent or CreateEventA/CreateEventW +#define CreateEvent error_use_qxeCreateEvent_or_CreateEventA_and_CreateEventW #endif HANDLE qxeCreateEvent (LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, const Extbyte * lpName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef OpenEvent -#define OpenEvent error use qxeOpenEvent or OpenEventA/OpenEventW +#define OpenEvent error_use_qxeOpenEvent_or_OpenEventA_and_OpenEventW #endif HANDLE qxeOpenEvent (DWORD dwDesiredAccess, BOOL bInheritHandle, const Extbyte * lpName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateSemaphore -#define CreateSemaphore error use qxeCreateSemaphore or CreateSemaphoreA/CreateSemaphoreW +#define CreateSemaphore error_use_qxeCreateSemaphore_or_CreateSemaphoreA_and_CreateSemaphoreW #endif HANDLE qxeCreateSemaphore (LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, const Extbyte * lpName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef OpenSemaphore -#define OpenSemaphore error use qxeOpenSemaphore or OpenSemaphoreA/OpenSemaphoreW +#define OpenSemaphore error_use_qxeOpenSemaphore_or_OpenSemaphoreA_and_OpenSemaphoreW #endif HANDLE qxeOpenSemaphore (DWORD dwDesiredAccess, BOOL bInheritHandle, const Extbyte * lpName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateWaitableTimer -#define CreateWaitableTimer error use qxeCreateWaitableTimer or CreateWaitableTimerA/CreateWaitableTimerW +#define CreateWaitableTimer error_use_qxeCreateWaitableTimer_or_CreateWaitableTimerA_and_CreateWaitableTimerW #endif HANDLE qxeCreateWaitableTimer (LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, const Extbyte * lpTimerName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef OpenWaitableTimer -#define OpenWaitableTimer error use qxeOpenWaitableTimer or OpenWaitableTimerA/OpenWaitableTimerW +#define OpenWaitableTimer error_use_qxeOpenWaitableTimer_or_OpenWaitableTimerA_and_OpenWaitableTimerW #endif HANDLE qxeOpenWaitableTimer (DWORD dwDesiredAccess, BOOL bInheritHandle, const Extbyte * lpTimerName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateFileMapping -#define CreateFileMapping error use qxeCreateFileMapping or CreateFileMappingA/CreateFileMappingW +#define CreateFileMapping error_use_qxeCreateFileMapping_or_CreateFileMappingA_and_CreateFileMappingW #endif HANDLE qxeCreateFileMapping (HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, const Extbyte * lpName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef OpenFileMapping -#define OpenFileMapping error use qxeOpenFileMapping or OpenFileMappingA/OpenFileMappingW +#define OpenFileMapping error_use_qxeOpenFileMapping_or_OpenFileMappingA_and_OpenFileMappingW #endif HANDLE qxeOpenFileMapping (DWORD dwDesiredAccess, BOOL bInheritHandle, const Extbyte * lpName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetLogicalDriveStrings -#define GetLogicalDriveStrings error use qxeGetLogicalDriveStrings or GetLogicalDriveStringsA/GetLogicalDriveStringsW +#define GetLogicalDriveStrings error_use_qxeGetLogicalDriveStrings_or_GetLogicalDriveStringsA_and_GetLogicalDriveStringsW #endif DWORD qxeGetLogicalDriveStrings (DWORD nBufferLength, Extbyte * lpBuffer); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef LoadLibrary -#define LoadLibrary error use qxeLoadLibrary or LoadLibraryA/LoadLibraryW +#define LoadLibrary error_use_qxeLoadLibrary_or_LoadLibraryA_and_LoadLibraryW #endif HMODULE qxeLoadLibrary (const Extbyte * lpLibFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef LoadLibraryEx -#define LoadLibraryEx error use qxeLoadLibraryEx or LoadLibraryExA/LoadLibraryExW +#define LoadLibraryEx error_use_qxeLoadLibraryEx_or_LoadLibraryExA_and_LoadLibraryExW #endif HMODULE qxeLoadLibraryEx (const Extbyte * lpLibFileName, HANDLE hFile, DWORD dwFlags); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetModuleFileName -#define GetModuleFileName error use qxeGetModuleFileName or GetModuleFileNameA/GetModuleFileNameW +#define GetModuleFileName error_use_qxeGetModuleFileName_or_GetModuleFileNameA_and_GetModuleFileNameW #endif DWORD qxeGetModuleFileName (HMODULE hModule, Extbyte * lpFilename, DWORD nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetModuleHandle -#define GetModuleHandle error use qxeGetModuleHandle or GetModuleHandleA/GetModuleHandleW +#define GetModuleHandle error_use_qxeGetModuleHandle_or_GetModuleHandleA_and_GetModuleHandleW #endif HMODULE qxeGetModuleHandle (const Extbyte * lpModuleName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateProcess -#define CreateProcess error use qxeCreateProcess or CreateProcessA/CreateProcessW +#define CreateProcess error_use_qxeCreateProcess_or_CreateProcessA_and_CreateProcessW #endif BOOL qxeCreateProcess (const Extbyte * lpApplicationName, Extbyte * lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, const Extbyte * lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef FatalAppExit -#define FatalAppExit error use qxeFatalAppExit or FatalAppExitA/FatalAppExitW +#define FatalAppExit error_use_qxeFatalAppExit_or_FatalAppExitA_and_FatalAppExitW #endif VOID qxeFatalAppExit (UINT uAction, const Extbyte * lpMessageText); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetStartupInfo -#define GetStartupInfo error use qxeGetStartupInfo or GetStartupInfoA/GetStartupInfoW +#define GetStartupInfo error_use_qxeGetStartupInfo_or_GetStartupInfoA_and_GetStartupInfoW #endif VOID qxeGetStartupInfo (LPSTARTUPINFOW lpStartupInfo); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetCommandLine -#define GetCommandLine error use qxeGetCommandLine or GetCommandLineA/GetCommandLineW +#define GetCommandLine error_use_qxeGetCommandLine_or_GetCommandLineA_and_GetCommandLineW #endif Extbyte * qxeGetCommandLine (void); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetEnvironmentVariable -#define GetEnvironmentVariable error use qxeGetEnvironmentVariable or GetEnvironmentVariableA/GetEnvironmentVariableW +#define GetEnvironmentVariable error_use_qxeGetEnvironmentVariable_or_GetEnvironmentVariableA_and_GetEnvironmentVariableW #endif DWORD qxeGetEnvironmentVariable (const Extbyte * lpName, Extbyte * lpBuffer, DWORD nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef SetEnvironmentVariable -#define SetEnvironmentVariable error use qxeSetEnvironmentVariable or SetEnvironmentVariableA/SetEnvironmentVariableW +#define SetEnvironmentVariable error_use_qxeSetEnvironmentVariable_or_SetEnvironmentVariableA_and_SetEnvironmentVariableW #endif BOOL qxeSetEnvironmentVariable (const Extbyte * lpName, const Extbyte * lpValue); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ExpandEnvironmentStrings -#define ExpandEnvironmentStrings error use qxeExpandEnvironmentStrings or ExpandEnvironmentStringsA/ExpandEnvironmentStringsW +#define ExpandEnvironmentStrings error_use_qxeExpandEnvironmentStrings_or_ExpandEnvironmentStringsA_and_ExpandEnvironmentStringsW #endif DWORD qxeExpandEnvironmentStrings (const Extbyte * lpSrc, Extbyte * lpDst, DWORD nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef OutputDebugString -#define OutputDebugString error use qxeOutputDebugString or OutputDebugStringA/OutputDebugStringW +#define OutputDebugString error_use_qxeOutputDebugString_or_OutputDebugStringA_and_OutputDebugStringW #endif VOID qxeOutputDebugString (const Extbyte * lpOutputString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef FindResource -#define FindResource error use qxeFindResource or FindResourceA/FindResourceW +#define FindResource error_use_qxeFindResource_or_FindResourceA_and_FindResourceW #endif HRSRC qxeFindResource (HMODULE hModule, const Extbyte * lpName, const Extbyte * lpType); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef FindResourceEx -#define FindResourceEx error use qxeFindResourceEx or FindResourceExA/FindResourceExW +#define FindResourceEx error_use_qxeFindResourceEx_or_FindResourceExA_and_FindResourceExW #endif HRSRC qxeFindResourceEx (HMODULE hModule, const Extbyte * lpType, const Extbyte * lpName, WORD wLanguage); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef EnumResourceTypes -#define EnumResourceTypes error use qxeEnumResourceTypes or EnumResourceTypesA/EnumResourceTypesW -#endif -BOOL qxeEnumResourceTypes (HMODULE hModule, ENUMRESTYPEPROC lpEnumFunc, LONG lParam); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef EnumResourceNames -#define EnumResourceNames error use qxeEnumResourceNames or EnumResourceNamesA/EnumResourceNamesW -#endif -BOOL qxeEnumResourceNames (HMODULE hModule, const Extbyte * lpType, ENUMRESNAMEPROC lpEnumFunc, LONG lParam); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef EnumResourceLanguages -#define EnumResourceLanguages error use qxeEnumResourceLanguages or EnumResourceLanguagesA/EnumResourceLanguagesW -#endif -BOOL qxeEnumResourceLanguages (HMODULE hModule, const Extbyte * lpType, const Extbyte * lpName, ENUMRESLANGPROC lpEnumFunc, LONG lParam); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef BeginUpdateResource -#define BeginUpdateResource error use qxeBeginUpdateResource or BeginUpdateResourceA/BeginUpdateResourceW +#define BeginUpdateResource error_use_qxeBeginUpdateResource_or_BeginUpdateResourceA_and_BeginUpdateResourceW #endif HANDLE qxeBeginUpdateResource (const Extbyte * pFileName, BOOL bDeleteExistingResources); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef UpdateResource -#define UpdateResource error use qxeUpdateResource or UpdateResourceA/UpdateResourceW +#define UpdateResource error_use_qxeUpdateResource_or_UpdateResourceA_and_UpdateResourceW #endif BOOL qxeUpdateResource (HANDLE hUpdate, const Extbyte * lpType, const Extbyte * lpName, WORD wLanguage, LPVOID lpData, DWORD cbData); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef EndUpdateResource -#define EndUpdateResource error use qxeEndUpdateResource or EndUpdateResourceA/EndUpdateResourceW +#define EndUpdateResource error_use_qxeEndUpdateResource_or_EndUpdateResourceA_and_EndUpdateResourceW #endif BOOL qxeEndUpdateResource (HANDLE hUpdate, BOOL fDiscard); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GlobalAddAtom -#define GlobalAddAtom error use qxeGlobalAddAtom or GlobalAddAtomA/GlobalAddAtomW +#define GlobalAddAtom error_use_qxeGlobalAddAtom_or_GlobalAddAtomA_and_GlobalAddAtomW #endif ATOM qxeGlobalAddAtom (const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GlobalFindAtom -#define GlobalFindAtom error use qxeGlobalFindAtom or GlobalFindAtomA/GlobalFindAtomW +#define GlobalFindAtom error_use_qxeGlobalFindAtom_or_GlobalFindAtomA_and_GlobalFindAtomW #endif ATOM qxeGlobalFindAtom (const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GlobalGetAtomName -#define GlobalGetAtomName error use qxeGlobalGetAtomName or GlobalGetAtomNameA/GlobalGetAtomNameW +#define GlobalGetAtomName error_use_qxeGlobalGetAtomName_or_GlobalGetAtomNameA_and_GlobalGetAtomNameW #endif UINT qxeGlobalGetAtomName (ATOM nAtom, Extbyte * lpBuffer, int nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef AddAtom -#define AddAtom error use qxeAddAtom or AddAtomA/AddAtomW +#define AddAtom error_use_qxeAddAtom_or_AddAtomA_and_AddAtomW #endif ATOM qxeAddAtom (const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef FindAtom -#define FindAtom error use qxeFindAtom or FindAtomA/FindAtomW +#define FindAtom error_use_qxeFindAtom_or_FindAtomA_and_FindAtomW #endif ATOM qxeFindAtom (const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetAtomName -#define GetAtomName error use qxeGetAtomName or GetAtomNameA/GetAtomNameW +#define GetAtomName error_use_qxeGetAtomName_or_GetAtomNameA_and_GetAtomNameW #endif UINT qxeGetAtomName (ATOM nAtom, Extbyte * lpBuffer, int nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetProfileInt -#define GetProfileInt error use qxeGetProfileInt or GetProfileIntA/GetProfileIntW +#define GetProfileInt error_use_qxeGetProfileInt_or_GetProfileIntA_and_GetProfileIntW #endif UINT qxeGetProfileInt (const Extbyte * lpAppName, const Extbyte * lpKeyName, INT nDefault); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetProfileString -#define GetProfileString error use qxeGetProfileString or GetProfileStringA/GetProfileStringW +#define GetProfileString error_use_qxeGetProfileString_or_GetProfileStringA_and_GetProfileStringW #endif DWORD qxeGetProfileString (const Extbyte * lpAppName, const Extbyte * lpKeyName, const Extbyte * lpDefault, Extbyte * lpReturnedString, DWORD nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WriteProfileString -#define WriteProfileString error use qxeWriteProfileString or WriteProfileStringA/WriteProfileStringW +#define WriteProfileString error_use_qxeWriteProfileString_or_WriteProfileStringA_and_WriteProfileStringW #endif BOOL qxeWriteProfileString (const Extbyte * lpAppName, const Extbyte * lpKeyName, const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetProfileSection -#define GetProfileSection error use qxeGetProfileSection or GetProfileSectionA/GetProfileSectionW +#define GetProfileSection error_use_qxeGetProfileSection_or_GetProfileSectionA_and_GetProfileSectionW #endif DWORD qxeGetProfileSection (const Extbyte * lpAppName, Extbyte * lpReturnedString, DWORD nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WriteProfileSection -#define WriteProfileSection error use qxeWriteProfileSection or WriteProfileSectionA/WriteProfileSectionW +#define WriteProfileSection error_use_qxeWriteProfileSection_or_WriteProfileSectionA_and_WriteProfileSectionW #endif BOOL qxeWriteProfileSection (const Extbyte * lpAppName, const Extbyte * lpString); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetPrivateProfileInt -#define GetPrivateProfileInt error use qxeGetPrivateProfileInt or GetPrivateProfileIntA/GetPrivateProfileIntW +#define GetPrivateProfileInt error_use_qxeGetPrivateProfileInt_or_GetPrivateProfileIntA_and_GetPrivateProfileIntW #endif UINT qxeGetPrivateProfileInt (const Extbyte * lpAppName, const Extbyte * lpKeyName, INT nDefault, const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetPrivateProfileString -#define GetPrivateProfileString error use qxeGetPrivateProfileString or GetPrivateProfileStringA/GetPrivateProfileStringW +#define GetPrivateProfileString error_use_qxeGetPrivateProfileString_or_GetPrivateProfileStringA_and_GetPrivateProfileStringW #endif DWORD qxeGetPrivateProfileString (const Extbyte * lpAppName, const Extbyte * lpKeyName, const Extbyte * lpDefault, Extbyte * lpReturnedString, DWORD nSize, const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WritePrivateProfileString -#define WritePrivateProfileString error use qxeWritePrivateProfileString or WritePrivateProfileStringA/WritePrivateProfileStringW +#define WritePrivateProfileString error_use_qxeWritePrivateProfileString_or_WritePrivateProfileStringA_and_WritePrivateProfileStringW #endif BOOL qxeWritePrivateProfileString (const Extbyte * lpAppName, const Extbyte * lpKeyName, const Extbyte * lpString, const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetPrivateProfileSection -#define GetPrivateProfileSection error use qxeGetPrivateProfileSection or GetPrivateProfileSectionA/GetPrivateProfileSectionW +#define GetPrivateProfileSection error_use_qxeGetPrivateProfileSection_or_GetPrivateProfileSectionA_and_GetPrivateProfileSectionW #endif DWORD qxeGetPrivateProfileSection (const Extbyte * lpAppName, Extbyte * lpReturnedString, DWORD nSize, const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WritePrivateProfileSection -#define WritePrivateProfileSection error use qxeWritePrivateProfileSection or WritePrivateProfileSectionA/WritePrivateProfileSectionW +#define WritePrivateProfileSection error_use_qxeWritePrivateProfileSection_or_WritePrivateProfileSectionA_and_WritePrivateProfileSectionW #endif BOOL qxeWritePrivateProfileSection (const Extbyte * lpAppName, const Extbyte * lpString, const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetPrivateProfileSectionNames -#define GetPrivateProfileSectionNames error use qxeGetPrivateProfileSectionNames or GetPrivateProfileSectionNamesA/GetPrivateProfileSectionNamesW +#define GetPrivateProfileSectionNames error_use_qxeGetPrivateProfileSectionNames_or_GetPrivateProfileSectionNamesA_and_GetPrivateProfileSectionNamesW #endif DWORD qxeGetPrivateProfileSectionNames (Extbyte * lpszReturnBuffer, DWORD nSize, const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetPrivateProfileStruct -#define GetPrivateProfileStruct error use qxeGetPrivateProfileStruct or GetPrivateProfileStructA/GetPrivateProfileStructW +#define GetPrivateProfileStruct error_use_qxeGetPrivateProfileStruct_or_GetPrivateProfileStructA_and_GetPrivateProfileStructW #endif BOOL qxeGetPrivateProfileStruct (const Extbyte * lpszSection, const Extbyte * lpszKey, LPVOID lpStruct, UINT uSizeStruct, const Extbyte * szFile); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WritePrivateProfileStruct -#define WritePrivateProfileStruct error use qxeWritePrivateProfileStruct or WritePrivateProfileStructA/WritePrivateProfileStructW +#define WritePrivateProfileStruct error_use_qxeWritePrivateProfileStruct_or_WritePrivateProfileStructA_and_WritePrivateProfileStructW #endif BOOL qxeWritePrivateProfileStruct (const Extbyte * lpszSection, const Extbyte * lpszKey, LPVOID lpStruct, UINT uSizeStruct, const Extbyte * szFile); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetDriveType -#define GetDriveType error use qxeGetDriveType or GetDriveTypeA/GetDriveTypeW +#define GetDriveType error_use_qxeGetDriveType_or_GetDriveTypeA_and_GetDriveTypeW #endif UINT qxeGetDriveType (const Extbyte * lpRootPathName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetSystemDirectory -#define GetSystemDirectory error use qxeGetSystemDirectory or GetSystemDirectoryA/GetSystemDirectoryW +#define GetSystemDirectory error_use_qxeGetSystemDirectory_or_GetSystemDirectoryA_and_GetSystemDirectoryW #endif UINT qxeGetSystemDirectory (Extbyte * lpBuffer, UINT uSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetTempPath -#define GetTempPath error use qxeGetTempPath or GetTempPathA/GetTempPathW +#define GetTempPath error_use_qxeGetTempPath_or_GetTempPathA_and_GetTempPathW #endif DWORD qxeGetTempPath (DWORD nBufferLength, Extbyte * lpBuffer); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetTempFileName -#define GetTempFileName error use qxeGetTempFileName or GetTempFileNameA/GetTempFileNameW +#define GetTempFileName error_use_qxeGetTempFileName_or_GetTempFileNameA_and_GetTempFileNameW #endif UINT qxeGetTempFileName (const Extbyte * lpPathName, const Extbyte * lpPrefixString, UINT uUnique, Extbyte * lpTempFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetWindowsDirectory -#define GetWindowsDirectory error use qxeGetWindowsDirectory or GetWindowsDirectoryA/GetWindowsDirectoryW +#define GetWindowsDirectory error_use_qxeGetWindowsDirectory_or_GetWindowsDirectoryA_and_GetWindowsDirectoryW #endif UINT qxeGetWindowsDirectory (Extbyte * lpBuffer, UINT uSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef SetCurrentDirectory -#define SetCurrentDirectory error use qxeSetCurrentDirectory or SetCurrentDirectoryA/SetCurrentDirectoryW +#define SetCurrentDirectory error_use_qxeSetCurrentDirectory_or_SetCurrentDirectoryA_and_SetCurrentDirectoryW #endif BOOL qxeSetCurrentDirectory (const Extbyte * lpPathName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetCurrentDirectory -#define GetCurrentDirectory error use qxeGetCurrentDirectory or GetCurrentDirectoryA/GetCurrentDirectoryW +#define GetCurrentDirectory error_use_qxeGetCurrentDirectory_or_GetCurrentDirectoryA_and_GetCurrentDirectoryW #endif DWORD qxeGetCurrentDirectory (DWORD nBufferLength, Extbyte * lpBuffer); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetDiskFreeSpace -#define GetDiskFreeSpace error use qxeGetDiskFreeSpace or GetDiskFreeSpaceA/GetDiskFreeSpaceW +#define GetDiskFreeSpace error_use_qxeGetDiskFreeSpace_or_GetDiskFreeSpaceA_and_GetDiskFreeSpaceW #endif BOOL qxeGetDiskFreeSpace (const Extbyte * lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetDiskFreeSpaceEx -#define GetDiskFreeSpaceEx error use qxeGetDiskFreeSpaceEx or GetDiskFreeSpaceExA/GetDiskFreeSpaceExW +#define GetDiskFreeSpaceEx error_use_qxeGetDiskFreeSpaceEx_or_GetDiskFreeSpaceExA_and_GetDiskFreeSpaceExW #endif BOOL qxeGetDiskFreeSpaceEx (const Extbyte * lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateDirectory -#define CreateDirectory error use qxeCreateDirectory or CreateDirectoryA/CreateDirectoryW +#define CreateDirectory error_use_qxeCreateDirectory_or_CreateDirectoryA_and_CreateDirectoryW #endif BOOL qxeCreateDirectory (const Extbyte * lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateDirectoryEx -#define CreateDirectoryEx error use qxeCreateDirectoryEx or CreateDirectoryExA/CreateDirectoryExW +#define CreateDirectoryEx error_use_qxeCreateDirectoryEx_or_CreateDirectoryExA_and_CreateDirectoryExW #endif BOOL qxeCreateDirectoryEx (const Extbyte * lpTemplateDirectory, const Extbyte * lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef RemoveDirectory -#define RemoveDirectory error use qxeRemoveDirectory or RemoveDirectoryA/RemoveDirectoryW +#define RemoveDirectory error_use_qxeRemoveDirectory_or_RemoveDirectoryA_and_RemoveDirectoryW #endif BOOL qxeRemoveDirectory (const Extbyte * lpPathName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetFullPathName -#define GetFullPathName error use qxeGetFullPathName or GetFullPathNameA/GetFullPathNameW +#define GetFullPathName error_use_qxeGetFullPathName_or_GetFullPathNameA_and_GetFullPathNameW #endif DWORD qxeGetFullPathName (const Extbyte * lpFileName, DWORD nBufferLength, Extbyte * lpBuffer, Extbyte * * lpFilePart); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef DefineDosDevice -#define DefineDosDevice error use qxeDefineDosDevice or DefineDosDeviceA/DefineDosDeviceW +#define DefineDosDevice error_use_qxeDefineDosDevice_or_DefineDosDeviceA_and_DefineDosDeviceW #endif BOOL qxeDefineDosDevice (DWORD dwFlags, const Extbyte * lpDeviceName, const Extbyte * lpTargetPath); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef QueryDosDevice -#define QueryDosDevice error use qxeQueryDosDevice or QueryDosDeviceA/QueryDosDeviceW +#define QueryDosDevice error_use_qxeQueryDosDevice_or_QueryDosDeviceA_and_QueryDosDeviceW #endif DWORD qxeQueryDosDevice (const Extbyte * lpDeviceName, Extbyte * lpTargetPath, DWORD ucchMax); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateFile -#define CreateFile error use qxeCreateFile or CreateFileA/CreateFileW +#define CreateFile error_use_qxeCreateFile_or_CreateFileA_and_CreateFileW #endif HANDLE qxeCreateFile (const Extbyte * lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef SetFileAttributes -#define SetFileAttributes error use qxeSetFileAttributes or SetFileAttributesA/SetFileAttributesW +#define SetFileAttributes error_use_qxeSetFileAttributes_or_SetFileAttributesA_and_SetFileAttributesW #endif BOOL qxeSetFileAttributes (const Extbyte * lpFileName, DWORD dwFileAttributes); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetFileAttributes -#define GetFileAttributes error use qxeGetFileAttributes or GetFileAttributesA/GetFileAttributesW +#define GetFileAttributes error_use_qxeGetFileAttributes_or_GetFileAttributesA_and_GetFileAttributesW #endif DWORD qxeGetFileAttributes (const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetFileAttributesEx -#define GetFileAttributesEx error use qxeGetFileAttributesEx or GetFileAttributesExA/GetFileAttributesExW +#define GetFileAttributesEx error_use_qxeGetFileAttributesEx_or_GetFileAttributesExA_and_GetFileAttributesExW #endif BOOL qxeGetFileAttributesEx (const Extbyte * lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetCompressedFileSize -#define GetCompressedFileSize error use qxeGetCompressedFileSize or GetCompressedFileSizeA/GetCompressedFileSizeW +#define GetCompressedFileSize error_use_qxeGetCompressedFileSize_or_GetCompressedFileSizeA_and_GetCompressedFileSizeW #endif DWORD qxeGetCompressedFileSize (const Extbyte * lpFileName, LPDWORD lpFileSizeHigh); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef DeleteFile -#define DeleteFile error use qxeDeleteFile or DeleteFileA/DeleteFileW +#define DeleteFile error_use_qxeDeleteFile_or_DeleteFileA_and_DeleteFileW #endif BOOL qxeDeleteFile (const Extbyte * lpFileName); #undef FindFirstFileEx -#define FindFirstFileEx error split-sized LPWIN32_FIND_DATA; not used, NT 4.0+ only +#define FindFirstFileEx error_split_sized_LPWIN32_FIND_DATA__not_used__NT_4_0__only /* Skipping FindFirstFile because split-sized LPWIN32_FIND_DATA */ @@ -2335,586 +2487,408 @@ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef SearchPath -#define SearchPath error use qxeSearchPath or SearchPathA/SearchPathW +#define SearchPath error_use_qxeSearchPath_or_SearchPathA_and_SearchPathW #endif DWORD qxeSearchPath (const Extbyte * lpPath, const Extbyte * lpFileName, const Extbyte * lpExtension, DWORD nBufferLength, Extbyte * lpBuffer, Extbyte * * lpFilePart); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CopyFile -#define CopyFile error use qxeCopyFile or CopyFileA/CopyFileW +#define CopyFile error_use_qxeCopyFile_or_CopyFileA_and_CopyFileW #endif BOOL qxeCopyFile (const Extbyte * lpExistingFileName, const Extbyte * lpNewFileName, BOOL bFailIfExists); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CopyFileEx -#define CopyFileEx error use qxeCopyFileEx or CopyFileExA/CopyFileExW +#define CopyFileEx error_use_qxeCopyFileEx_or_CopyFileExA_and_CopyFileExW #endif BOOL qxeCopyFileEx (const Extbyte * lpExistingFileName, const Extbyte * lpNewFileName, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef MoveFile -#define MoveFile error use qxeMoveFile or MoveFileA/MoveFileW +#define MoveFile error_use_qxeMoveFile_or_MoveFileA_and_MoveFileW #endif BOOL qxeMoveFile (const Extbyte * lpExistingFileName, const Extbyte * lpNewFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef MoveFileEx -#define MoveFileEx error use qxeMoveFileEx or MoveFileExA/MoveFileExW +#define MoveFileEx error_use_qxeMoveFileEx_or_MoveFileExA_and_MoveFileExW #endif BOOL qxeMoveFileEx (const Extbyte * lpExistingFileName, const Extbyte * lpNewFileName, DWORD dwFlags); #undef MoveFileWithProgress -#define MoveFileWithProgress error NT 5.0+ only +#define MoveFileWithProgress error_NT_5_0__only #undef CreateHardLink -#define CreateHardLink error NT 5.0+ only +#define CreateHardLink error_NT_5_0__only #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateNamedPipe -#define CreateNamedPipe error use qxeCreateNamedPipe or CreateNamedPipeA/CreateNamedPipeW +#define CreateNamedPipe error_use_qxeCreateNamedPipe_or_CreateNamedPipeA_and_CreateNamedPipeW #endif HANDLE qxeCreateNamedPipe (const Extbyte * lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetNamedPipeHandleState -#define GetNamedPipeHandleState error use qxeGetNamedPipeHandleState or GetNamedPipeHandleStateA/GetNamedPipeHandleStateW +#define GetNamedPipeHandleState error_use_qxeGetNamedPipeHandleState_or_GetNamedPipeHandleStateA_and_GetNamedPipeHandleStateW #endif BOOL qxeGetNamedPipeHandleState (HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout, Extbyte * lpUserName, DWORD nMaxUserNameSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CallNamedPipe -#define CallNamedPipe error use qxeCallNamedPipe or CallNamedPipeA/CallNamedPipeW +#define CallNamedPipe error_use_qxeCallNamedPipe_or_CallNamedPipeA_and_CallNamedPipeW #endif BOOL qxeCallNamedPipe (const Extbyte * lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, DWORD nTimeOut); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef WaitNamedPipe -#define WaitNamedPipe error use qxeWaitNamedPipe or WaitNamedPipeA/WaitNamedPipeW +#define WaitNamedPipe error_use_qxeWaitNamedPipe_or_WaitNamedPipeA_and_WaitNamedPipeW #endif BOOL qxeWaitNamedPipe (const Extbyte * lpNamedPipeName, DWORD nTimeOut); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef SetVolumeLabel -#define SetVolumeLabel error use qxeSetVolumeLabel or SetVolumeLabelA/SetVolumeLabelW +#define SetVolumeLabel error_use_qxeSetVolumeLabel_or_SetVolumeLabelA_and_SetVolumeLabelW #endif BOOL qxeSetVolumeLabel (const Extbyte * lpRootPathName, const Extbyte * lpVolumeName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetVolumeInformation -#define GetVolumeInformation error use qxeGetVolumeInformation or GetVolumeInformationA/GetVolumeInformationW +#define GetVolumeInformation error_use_qxeGetVolumeInformation_or_GetVolumeInformationA_and_GetVolumeInformationW #endif BOOL qxeGetVolumeInformation (const Extbyte * lpRootPathName, Extbyte * lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, Extbyte * lpFileSystemNameBuffer, DWORD nFileSystemNameSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ClearEventLog -#define ClearEventLog error use qxeClearEventLog or ClearEventLogA/ClearEventLogW +#define ClearEventLog error_use_qxeClearEventLog_or_ClearEventLogA_and_ClearEventLogW #endif BOOL qxeClearEventLog (HANDLE hEventLog, const Extbyte * lpBackupFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef BackupEventLog -#define BackupEventLog error use qxeBackupEventLog or BackupEventLogA/BackupEventLogW +#define BackupEventLog error_use_qxeBackupEventLog_or_BackupEventLogA_and_BackupEventLogW #endif BOOL qxeBackupEventLog (HANDLE hEventLog, const Extbyte * lpBackupFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef OpenEventLog -#define OpenEventLog error use qxeOpenEventLog or OpenEventLogA/OpenEventLogW +#define OpenEventLog error_use_qxeOpenEventLog_or_OpenEventLogA_and_OpenEventLogW #endif HANDLE qxeOpenEventLog (const Extbyte * lpUNCServerName, const Extbyte * lpSourceName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef RegisterEventSource -#define RegisterEventSource error use qxeRegisterEventSource or RegisterEventSourceA/RegisterEventSourceW +#define RegisterEventSource error_use_qxeRegisterEventSource_or_RegisterEventSourceA_and_RegisterEventSourceW #endif HANDLE qxeRegisterEventSource (const Extbyte * lpUNCServerName, const Extbyte * lpSourceName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef OpenBackupEventLog -#define OpenBackupEventLog error use qxeOpenBackupEventLog or OpenBackupEventLogA/OpenBackupEventLogW +#define OpenBackupEventLog error_use_qxeOpenBackupEventLog_or_OpenBackupEventLogA_and_OpenBackupEventLogW #endif HANDLE qxeOpenBackupEventLog (const Extbyte * lpUNCServerName, const Extbyte * lpFileName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ReadEventLog -#define ReadEventLog error use qxeReadEventLog or ReadEventLogA/ReadEventLogW +#define ReadEventLog error_use_qxeReadEventLog_or_ReadEventLogA_and_ReadEventLogW #endif BOOL qxeReadEventLog (HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD * pnBytesRead, DWORD * pnMinNumberOfBytesNeeded); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ReportEvent -#define ReportEvent error use qxeReportEvent or ReportEventA/ReportEventW +#define ReportEvent error_use_qxeReportEvent_or_ReportEventA_and_ReportEventW #endif BOOL qxeReportEvent (HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, const Extbyte * * lpStrings, LPVOID lpRawData); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef AccessCheckAndAuditAlarm -#define AccessCheckAndAuditAlarm error use qxeAccessCheckAndAuditAlarm or AccessCheckAndAuditAlarmA/AccessCheckAndAuditAlarmW +#define AccessCheckAndAuditAlarm error_use_qxeAccessCheckAndAuditAlarm_or_AccessCheckAndAuditAlarmA_and_AccessCheckAndAuditAlarmW #endif BOOL qxeAccessCheckAndAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, Extbyte * ObjectTypeName, Extbyte * ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess, LPBOOL AccessStatus, LPBOOL pfGenerateOnClose); #undef AccessCheckByTypeAndAuditAlarm -#define AccessCheckByTypeAndAuditAlarm error NT 5.0+ only +#define AccessCheckByTypeAndAuditAlarm error_NT_5_0__only #undef AccessCheckByTypeResultListAndAuditAlarm -#define AccessCheckByTypeResultListAndAuditAlarm error NT 5.0+ only +#define AccessCheckByTypeResultListAndAuditAlarm error_NT_5_0__only #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ObjectOpenAuditAlarm -#define ObjectOpenAuditAlarm error use qxeObjectOpenAuditAlarm or ObjectOpenAuditAlarmA/ObjectOpenAuditAlarmW +#define ObjectOpenAuditAlarm error_use_qxeObjectOpenAuditAlarm_or_ObjectOpenAuditAlarmA_and_ObjectOpenAuditAlarmW #endif BOOL qxeObjectOpenAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, Extbyte * ObjectTypeName, Extbyte * ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted, LPBOOL GenerateOnClose); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ObjectPrivilegeAuditAlarm -#define ObjectPrivilegeAuditAlarm error use qxeObjectPrivilegeAuditAlarm or ObjectPrivilegeAuditAlarmA/ObjectPrivilegeAuditAlarmW +#define ObjectPrivilegeAuditAlarm error_use_qxeObjectPrivilegeAuditAlarm_or_ObjectPrivilegeAuditAlarmA_and_ObjectPrivilegeAuditAlarmW #endif BOOL qxeObjectPrivilegeAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, HANDLE ClientToken, DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ObjectCloseAuditAlarm -#define ObjectCloseAuditAlarm error use qxeObjectCloseAuditAlarm or ObjectCloseAuditAlarmA/ObjectCloseAuditAlarmW +#define ObjectCloseAuditAlarm error_use_qxeObjectCloseAuditAlarm_or_ObjectCloseAuditAlarmA_and_ObjectCloseAuditAlarmW #endif BOOL qxeObjectCloseAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, BOOL GenerateOnClose); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ObjectDeleteAuditAlarm -#define ObjectDeleteAuditAlarm error use qxeObjectDeleteAuditAlarm or ObjectDeleteAuditAlarmA/ObjectDeleteAuditAlarmW +#define ObjectDeleteAuditAlarm error_use_qxeObjectDeleteAuditAlarm_or_ObjectDeleteAuditAlarmA_and_ObjectDeleteAuditAlarmW #endif BOOL qxeObjectDeleteAuditAlarm (const Extbyte * SubsystemName, LPVOID HandleId, BOOL GenerateOnClose); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef PrivilegedServiceAuditAlarm -#define PrivilegedServiceAuditAlarm error use qxePrivilegedServiceAuditAlarm or PrivilegedServiceAuditAlarmA/PrivilegedServiceAuditAlarmW +#define PrivilegedServiceAuditAlarm error_use_qxePrivilegedServiceAuditAlarm_or_PrivilegedServiceAuditAlarmA_and_PrivilegedServiceAuditAlarmW #endif BOOL qxePrivilegedServiceAuditAlarm (const Extbyte * SubsystemName, const Extbyte * ServiceName, HANDLE ClientToken, PPRIVILEGE_SET Privileges, BOOL AccessGranted); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef SetFileSecurity -#define SetFileSecurity error use qxeSetFileSecurity or SetFileSecurityA/SetFileSecurityW +#define SetFileSecurity error_use_qxeSetFileSecurity_or_SetFileSecurityA_and_SetFileSecurityW #endif BOOL qxeSetFileSecurity (const Extbyte * lpFileName, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetFileSecurity -#define GetFileSecurity error use qxeGetFileSecurity or GetFileSecurityA/GetFileSecurityW +#define GetFileSecurity error_use_qxeGetFileSecurity_or_GetFileSecurityA_and_GetFileSecurityW #endif BOOL qxeGetFileSecurity (const Extbyte * lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef FindFirstChangeNotification -#define FindFirstChangeNotification error use qxeFindFirstChangeNotification or FindFirstChangeNotificationA/FindFirstChangeNotificationW +#define FindFirstChangeNotification error_use_qxeFindFirstChangeNotification_or_FindFirstChangeNotificationA_and_FindFirstChangeNotificationW #endif HANDLE qxeFindFirstChangeNotification (const Extbyte * lpPathName, BOOL bWatchSubtree, DWORD dwNotifyFilter); #undef ReadDirectoryChanges -#define ReadDirectoryChanges error Unicode-only +#define ReadDirectoryChanges error_Unicode_only #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef IsBadStringPtr -#define IsBadStringPtr error use qxeIsBadStringPtr or IsBadStringPtrA/IsBadStringPtrW +#define IsBadStringPtr error_use_qxeIsBadStringPtr_or_IsBadStringPtrA_and_IsBadStringPtrW #endif BOOL qxeIsBadStringPtr (const Extbyte * lpsz, UINT ucchMax); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef LookupAccountSid -#define LookupAccountSid error use qxeLookupAccountSid or LookupAccountSidA/LookupAccountSidW +#define LookupAccountSid error_use_qxeLookupAccountSid_or_LookupAccountSidA_and_LookupAccountSidW #endif BOOL qxeLookupAccountSid (const Extbyte * lpSystemName, PSID Sid, Extbyte * Name, LPDWORD cbName, Extbyte * ReferencedDomainName, LPDWORD cbReferencedDomainName, PSID_NAME_USE peUse); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef LookupAccountName -#define LookupAccountName error use qxeLookupAccountName or LookupAccountNameA/LookupAccountNameW +#define LookupAccountName error_use_qxeLookupAccountName_or_LookupAccountNameA_and_LookupAccountNameW #endif BOOL qxeLookupAccountName (const Extbyte * lpSystemName, const Extbyte * lpAccountName, PSID Sid, LPDWORD cbSid, Extbyte * ReferencedDomainName, LPDWORD cbReferencedDomainName, PSID_NAME_USE peUse); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef LookupPrivilegeValue -#define LookupPrivilegeValue error use qxeLookupPrivilegeValue or LookupPrivilegeValueA/LookupPrivilegeValueW +#define LookupPrivilegeValue error_use_qxeLookupPrivilegeValue_or_LookupPrivilegeValueA_and_LookupPrivilegeValueW #endif BOOL qxeLookupPrivilegeValue (const Extbyte * lpSystemName, const Extbyte * lpName, PLUID lpLuid); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef LookupPrivilegeName -#define LookupPrivilegeName error use qxeLookupPrivilegeName or LookupPrivilegeNameA/LookupPrivilegeNameW +#define LookupPrivilegeName error_use_qxeLookupPrivilegeName_or_LookupPrivilegeNameA_and_LookupPrivilegeNameW #endif BOOL qxeLookupPrivilegeName (const Extbyte * lpSystemName, PLUID lpLuid, Extbyte * lpName, LPDWORD cbName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef LookupPrivilegeDisplayName -#define LookupPrivilegeDisplayName error use qxeLookupPrivilegeDisplayName or LookupPrivilegeDisplayNameA/LookupPrivilegeDisplayNameW +#define LookupPrivilegeDisplayName error_use_qxeLookupPrivilegeDisplayName_or_LookupPrivilegeDisplayNameA_and_LookupPrivilegeDisplayNameW #endif BOOL qxeLookupPrivilegeDisplayName (const Extbyte * lpSystemName, const Extbyte * lpName, Extbyte * lpDisplayName, LPDWORD cbDisplayName, LPDWORD lpLanguageId); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef BuildCommDCB -#define BuildCommDCB error use qxeBuildCommDCB or BuildCommDCBA/BuildCommDCBW +#define BuildCommDCB error_use_qxeBuildCommDCB_or_BuildCommDCBA_and_BuildCommDCBW #endif BOOL qxeBuildCommDCB (const Extbyte * lpDef, LPDCB lpDCB); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef BuildCommDCBAndTimeouts -#define BuildCommDCBAndTimeouts error use qxeBuildCommDCBAndTimeouts or BuildCommDCBAndTimeoutsA/BuildCommDCBAndTimeoutsW +#define BuildCommDCBAndTimeouts error_use_qxeBuildCommDCBAndTimeouts_or_BuildCommDCBAndTimeoutsA_and_BuildCommDCBAndTimeoutsW #endif BOOL qxeBuildCommDCBAndTimeouts (const Extbyte * lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CommConfigDialog -#define CommConfigDialog error use qxeCommConfigDialog or CommConfigDialogA/CommConfigDialogW +#define CommConfigDialog error_use_qxeCommConfigDialog_or_CommConfigDialogA_and_CommConfigDialogW #endif BOOL qxeCommConfigDialog (const Extbyte * lpszName, HWND hWnd, LPCOMMCONFIG lpCC); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetDefaultCommConfig -#define GetDefaultCommConfig error use qxeGetDefaultCommConfig or GetDefaultCommConfigA/GetDefaultCommConfigW +#define GetDefaultCommConfig error_use_qxeGetDefaultCommConfig_or_GetDefaultCommConfigA_and_GetDefaultCommConfigW #endif BOOL qxeGetDefaultCommConfig (const Extbyte * lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef SetDefaultCommConfig -#define SetDefaultCommConfig error use qxeSetDefaultCommConfig or SetDefaultCommConfigA/SetDefaultCommConfigW +#define SetDefaultCommConfig error_use_qxeSetDefaultCommConfig_or_SetDefaultCommConfigA_and_SetDefaultCommConfigW #endif BOOL qxeSetDefaultCommConfig (const Extbyte * lpszName, LPCOMMCONFIG lpCC, DWORD dwSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetComputerName -#define GetComputerName error use qxeGetComputerName or GetComputerNameA/GetComputerNameW +#define GetComputerName error_use_qxeGetComputerName_or_GetComputerNameA_and_GetComputerNameW #endif BOOL qxeGetComputerName (Extbyte * lpBuffer, LPDWORD nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef SetComputerName -#define SetComputerName error use qxeSetComputerName or SetComputerNameA/SetComputerNameW +#define SetComputerName error_use_qxeSetComputerName_or_SetComputerNameA_and_SetComputerNameW #endif BOOL qxeSetComputerName (const Extbyte * lpComputerName); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetUserName -#define GetUserName error use qxeGetUserName or GetUserNameA/GetUserNameW +#define GetUserName error_use_qxeGetUserName_or_GetUserNameA_and_GetUserNameW #endif BOOL qxeGetUserName (Extbyte * lpBuffer, LPDWORD nSize); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef LogonUser -#define LogonUser error use qxeLogonUser or LogonUserA/LogonUserW +#define LogonUser error_use_qxeLogonUser_or_LogonUserA_and_LogonUserW #endif BOOL qxeLogonUser (Extbyte * lpszUsername, Extbyte * lpszDomain, Extbyte * lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef CreateProcessAsUser -#define CreateProcessAsUser error use qxeCreateProcessAsUser or CreateProcessAsUserA/CreateProcessAsUserW +#define CreateProcessAsUser error_use_qxeCreateProcessAsUser_or_CreateProcessAsUserA_and_CreateProcessAsUserW #endif BOOL qxeCreateProcessAsUser (HANDLE hToken, const Extbyte * lpApplicationName, Extbyte * lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, const Extbyte * lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); #undef GetCurrentHwProfile -#define GetCurrentHwProfile error split-sized LPHW_PROFILE_INFO; NT 4.0+ only +#define GetCurrentHwProfile error_split_sized_LPHW_PROFILE_INFO__NT_4_0__only #undef GetVersionEx -#define GetVersionEx error split-sized LPOSVERSIONINFO +#define GetVersionEx error_split_sized_LPOSVERSIONINFO #undef CreateJobObject -#define CreateJobObject error NT 5.0+ only +#define CreateJobObject error_NT_5_0__only #undef OpenJobObject -#define OpenJobObject error NT 5.0+ only - - -/* Processing file COMMDLG.H */ - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetOpenFileName -#define GetOpenFileName error use qxeGetOpenFileName or GetOpenFileNameA/GetOpenFileNameW -#endif -BOOL qxeGetOpenFileName (LPOPENFILENAMEW arg1); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetSaveFileName -#define GetSaveFileName error use qxeGetSaveFileName or GetSaveFileNameA/GetSaveFileNameW -#endif -BOOL qxeGetSaveFileName (LPOPENFILENAMEW arg1); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetFileTitle -#define GetFileTitle error use qxeGetFileTitle or GetFileTitleA/GetFileTitleW -#endif -short qxeGetFileTitle (const Extbyte * arg1, Extbyte * arg2, WORD arg3); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ChooseColor -#define ChooseColor error use qxeChooseColor or ChooseColorA/ChooseColorW -#endif -BOOL qxeChooseColor (LPCHOOSECOLORW arg1); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef FindText -#define FindText error use qxeFindText or FindTextA/FindTextW -#endif -HWND qxeFindText (LPFINDREPLACEW arg1); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ReplaceText -#define ReplaceText error use qxeReplaceText or ReplaceTextA/ReplaceTextW -#endif -HWND qxeReplaceText (LPFINDREPLACEW arg1); - -#undef AfxReplaceText -#define AfxReplaceText error mac only - -#undef ChooseFont -#define ChooseFont error split-sized LPLOGFONT in LPCHOOSEFONT - -/* Skipping PrintDlg because LPPRINTDLG with split-sized DEVMODE handle */ - -/* Skipping PageSetupDlg because LPPAGESETUPDLG with split-sized DEVMODE handle */ - - -/* Processing file SHLOBJ.H */ - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SHGetPathFromIDList -#define SHGetPathFromIDList error use qxeSHGetPathFromIDList or SHGetPathFromIDListA/SHGetPathFromIDListW -#endif -BOOL qxeSHGetPathFromIDList (LPCITEMIDLIST pidl, Extbyte * pszPath); - -/* Skipping SHGetSpecialFolderPath because error in Cygwin prototype, missing from Cygwin libraries */ - -/* Skipping SHBrowseForFolder because need to intercept callback for SendMessage */ - -/* Skipping SHGetDataFromIDList because split-sized WIN32_FIND_DATA or split-simple NETRESOURCE, missing from Cygwin libraries */ - - -/* Processing file IME.H */ - -#undef SendIMEMessageEx -#define SendIMEMessageEx error obsolete, no docs available - - -/* Processing file WINGDI.H */ - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef AddFontResource -#define AddFontResource error use qxeAddFontResource or AddFontResourceA/AddFontResourceW -#endif -int qxeAddFontResource (const Extbyte * arg1); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CopyMetaFile -#define CopyMetaFile error use qxeCopyMetaFile or CopyMetaFileA/CopyMetaFileW -#endif -HMETAFILE qxeCopyMetaFile (HMETAFILE arg1, const Extbyte * arg2); - -/* Skipping CreateDC because split-sized DEVMODE */ - -/* Skipping CreateFontIndirect because split-sized LOGFONT */ +#define OpenJobObject error_NT_5_0__only -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateFont -#define CreateFont error use qxeCreateFont or CreateFontA/CreateFontW -#endif -HFONT qxeCreateFont (int arg1, int arg2, int arg3, int arg4, int arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD arg10, DWORD arg11, DWORD arg12, DWORD arg13, const Extbyte * arg14); - -/* Skipping CreateIC because split-sized DEVMODE */ - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateMetaFile -#define CreateMetaFile error use qxeCreateMetaFile or CreateMetaFileA/CreateMetaFileW -#endif -HDC qxeCreateMetaFile (const Extbyte * arg1); - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateScalableFontResource -#define CreateScalableFontResource error use qxeCreateScalableFontResource or CreateScalableFontResourceA/CreateScalableFontResourceW -#endif -BOOL qxeCreateScalableFontResource (DWORD arg1, const Extbyte * arg2, const Extbyte * arg3, const Extbyte * arg4); -/* Skipping DeviceCapabilities because split-sized DEVMODE */ - -/* Skipping EnumFontFamiliesEx because split-complex FONTENUMPROC; NT 4.0+ only */ - -#undef EnumFontFamilies -#define EnumFontFamilies error split-complex FONTENUMPROC - -#undef EnumFonts -#define EnumFonts error split-complex FONTENUMPROC - -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetCharWidth -#define GetCharWidth error use qxeGetCharWidth or GetCharWidthA/GetCharWidthW -#endif -BOOL qxeGetCharWidth (HDC arg1, UINT arg2, UINT arg3, LPINT arg4); +/* Processing file MMSYSTEM.H */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetCharWidth32 -#define GetCharWidth32 error use qxeGetCharWidth32 or GetCharWidth32A/GetCharWidth32W +#undef sndPlaySound +#define sndPlaySound error_use_qxesndPlaySound_or_sndPlaySoundA_and_sndPlaySoundW #endif -BOOL qxeGetCharWidth32 (HDC arg1, UINT arg2, UINT arg3, LPINT arg4); +BOOL qxesndPlaySound (const Extbyte * pszSound, UINT fuSound); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetCharWidthFloat -#define GetCharWidthFloat error use qxeGetCharWidthFloat or GetCharWidthFloatA/GetCharWidthFloatW +#undef PlaySound +#define PlaySound error_use_qxePlaySound_or_PlaySoundA_and_PlaySoundW #endif -BOOL qxeGetCharWidthFloat (HDC arg1, UINT arg2, UINT arg3, PFLOAT arg4); +BOOL qxePlaySound (const Extbyte * pszSound, HMODULE hmod, DWORD fdwSound); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetCharABCWidths -#define GetCharABCWidths error use qxeGetCharABCWidths or GetCharABCWidthsA/GetCharABCWidthsW -#endif -BOOL qxeGetCharABCWidths (HDC arg1, UINT arg2, UINT arg3, LPABC arg4); +#undef waveOutGetDevCaps +#define waveOutGetDevCaps error_split_sized_LPWAVEOUTCAPS #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetCharABCWidthsFloat -#define GetCharABCWidthsFloat error use qxeGetCharABCWidthsFloat or GetCharABCWidthsFloatA/GetCharABCWidthsFloatW +#undef waveOutGetErrorText +#define waveOutGetErrorText error_use_qxewaveOutGetErrorText_or_waveOutGetErrorTextA_and_waveOutGetErrorTextW #endif -BOOL qxeGetCharABCWidthsFloat (HDC arg1, UINT arg2, UINT arg3, LPABCFLOAT arg4); +MMRESULT qxewaveOutGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetGlyphOutline -#define GetGlyphOutline error use qxeGetGlyphOutline or GetGlyphOutlineA/GetGlyphOutlineW -#endif -DWORD qxeGetGlyphOutline (HDC arg1, UINT arg2, UINT arg3, LPGLYPHMETRICS arg4, DWORD arg5, LPVOID arg6, CONST MAT2 * arg7); +#undef waveInGetDevCaps +#define waveInGetDevCaps error_split_sized_LPWAVEINCAPS #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetMetaFile -#define GetMetaFile error use qxeGetMetaFile or GetMetaFileA/GetMetaFileW +#undef waveInGetErrorText +#define waveInGetErrorText error_use_qxewaveInGetErrorText_or_waveInGetErrorTextA_and_waveInGetErrorTextW #endif -HMETAFILE qxeGetMetaFile (const Extbyte * arg1); - -#undef GetOutlineTextMetrics -#define GetOutlineTextMetrics error split-sized LPOUTLINETEXTMETRIC +MMRESULT qxewaveInGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetTextExtentPoint -#define GetTextExtentPoint error use qxeGetTextExtentPoint or GetTextExtentPointA/GetTextExtentPointW -#endif -BOOL qxeGetTextExtentPoint (HDC arg1, const Extbyte * arg2, int arg3, LPSIZE arg4); +#undef midiOutGetDevCaps +#define midiOutGetDevCaps error_split_sized_LPMIDIOUTCAPS #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetTextExtentPoint32 -#define GetTextExtentPoint32 error use qxeGetTextExtentPoint32 or GetTextExtentPoint32A/GetTextExtentPoint32W +#undef midiOutGetErrorText +#define midiOutGetErrorText error_use_qxemidiOutGetErrorText_or_midiOutGetErrorTextA_and_midiOutGetErrorTextW #endif -BOOL qxeGetTextExtentPoint32 (HDC arg1, const Extbyte * arg2, int arg3, LPSIZE arg4); +MMRESULT qxemidiOutGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetTextExtentExPoint -#define GetTextExtentExPoint error use qxeGetTextExtentExPoint or GetTextExtentExPointA/GetTextExtentExPointW -#endif -BOOL qxeGetTextExtentExPoint (HDC arg1, const Extbyte * arg2, int arg3, int arg4, LPINT arg5, LPINT arg6, LPSIZE arg7); +#undef midiInGetDevCaps +#define midiInGetDevCaps error_split_sized_LPMIDIOUTCAPS #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetCharacterPlacement -#define GetCharacterPlacement error use qxeGetCharacterPlacement or GetCharacterPlacementA/GetCharacterPlacementW +#undef midiInGetErrorText +#define midiInGetErrorText error_use_qxemidiInGetErrorText_or_midiInGetErrorTextA_and_midiInGetErrorTextW #endif -DWORD qxeGetCharacterPlacement (HDC arg1, const Extbyte * arg2, int arg3, int arg4, LPGCP_RESULTSW arg5, DWORD arg6); - -#undef GetGlyphIndices -#define GetGlyphIndices error NT 5.0+ only - -#undef AddFontResourceEx -#define AddFontResourceEx error NT 5.0+ only - -#undef RemoveFontResourceEx -#define RemoveFontResourceEx error NT 5.0+ only +MMRESULT qxemidiInGetErrorText (MMRESULT mmrError, Extbyte * pszText, UINT cchText); -#undef CreateFontIndirectEx -#define CreateFontIndirectEx error split-sized ENUMLOGFONTEXDV; NT 5.0+ only +#undef auxGetDevCaps +#define auxGetDevCaps error_split_sized_LPAUXCAPS -/* Skipping ResetDC because split-sized DEVMODE */ +#undef mixerGetDevCaps +#define mixerGetDevCaps error_split_sized_LPMIXERCAPS -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef RemoveFontResource -#define RemoveFontResource error use qxeRemoveFontResource or RemoveFontResourceA/RemoveFontResourceW -#endif -BOOL qxeRemoveFontResource (const Extbyte * arg1); +#undef mixerGetLineInfo +#define mixerGetLineInfo error_split_sized_LPMIXERLINE -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CopyEnhMetaFile -#define CopyEnhMetaFile error use qxeCopyEnhMetaFile or CopyEnhMetaFileA/CopyEnhMetaFileW -#endif -HENHMETAFILE qxeCopyEnhMetaFile (HENHMETAFILE arg1, const Extbyte * arg2); +#undef mixerGetLineControls +#define mixerGetLineControls error_split_sized_LPMIXERCONTROL -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef CreateEnhMetaFile -#define CreateEnhMetaFile error use qxeCreateEnhMetaFile or CreateEnhMetaFileA/CreateEnhMetaFileW -#endif -HDC qxeCreateEnhMetaFile (HDC arg1, const Extbyte * arg2, CONST RECT * arg3, const Extbyte * arg4); +#undef mixerGetControlDetails +#define mixerGetControlDetails error_split_sized_LPMIXERCONTROL_in_LPMIXERLINECONTROLS_in_LPMIXERCONTROLDETAILS -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetEnhMetaFile -#define GetEnhMetaFile error use qxeGetEnhMetaFile or GetEnhMetaFileA/GetEnhMetaFileW -#endif -HENHMETAFILE qxeGetEnhMetaFile (const Extbyte * arg1); +#undef joyGetDevCaps +#define joyGetDevCaps error_split_sized_LPJOYCAPS #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetEnhMetaFileDescription -#define GetEnhMetaFileDescription error use qxeGetEnhMetaFileDescription or GetEnhMetaFileDescriptionA/GetEnhMetaFileDescriptionW +#undef mmioStringToFOURCC +#define mmioStringToFOURCC error_use_qxemmioStringToFOURCC_or_mmioStringToFOURCCA_and_mmioStringToFOURCCW #endif -UINT qxeGetEnhMetaFileDescription (HENHMETAFILE arg1, UINT arg2, Extbyte * arg3); - -/* Skipping GetTextMetrics because split-sized LPTEXTMETRIC */ +FOURCC qxemmioStringToFOURCC (const Extbyte * sz, UINT uFlags); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef StartDoc -#define StartDoc error use qxeStartDoc or StartDocA/StartDocW +#undef mmioInstallIOProc +#define mmioInstallIOProc error_use_qxemmioInstallIOProc_or_mmioInstallIOProcA_and_mmioInstallIOProcW #endif -int qxeStartDoc (HDC arg1, CONST DOCINFOW * arg2); - -/* Skipping GetObject because split-sized LOGFONT */ +LPMMIOPROC qxemmioInstallIOProc (FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef TextOut -#define TextOut error use qxeTextOut or TextOutA/TextOutW +#undef mmioOpen +#define mmioOpen error_use_qxemmioOpen_or_mmioOpenA_and_mmioOpenW #endif -BOOL qxeTextOut (HDC arg1, int arg2, int arg3, const Extbyte * arg4, int arg5); +HMMIO qxemmioOpen (Extbyte * pszFileName, LPMMIOINFO pmmioinfo, DWORD fdwOpen); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef ExtTextOut -#define ExtTextOut error use qxeExtTextOut or ExtTextOutA/ExtTextOutW +#undef mmioRename +#define mmioRename error_use_qxemmioRename_or_mmioRenameA_and_mmioRenameW #endif -BOOL qxeExtTextOut (HDC arg1, int arg2, int arg3, UINT arg4, CONST RECT * arg5, const Extbyte * arg6, UINT arg7, CONST INT * arg8); +MMRESULT qxemmioRename (const Extbyte * pszFileName, const Extbyte * pszNewFileName, LPCMMIOINFO pmmioinfo, DWORD fdwRename); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef PolyTextOut -#define PolyTextOut error use qxePolyTextOut or PolyTextOutA/PolyTextOutW +#undef mciSendCommand +#define mciSendCommand error_use_qxemciSendCommand_or_mciSendCommandA_and_mciSendCommandW #endif -BOOL qxePolyTextOut (HDC arg1, CONST POLYTEXTW * arg2, int arg3); +MCIERROR qxemciSendCommand (MCIDEVICEID mciId, UINT uMsg, DWORD dwParam1, DWORD dwParam2); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetTextFace -#define GetTextFace error use qxeGetTextFace or GetTextFaceA/GetTextFaceW +#undef mciSendString +#define mciSendString error_use_qxemciSendString_or_mciSendStringA_and_mciSendStringW #endif -int qxeGetTextFace (HDC arg1, int arg2, Extbyte * arg3); +MCIERROR qxemciSendString (const Extbyte * lpstrCommand, Extbyte * lpstrReturnString, UINT uReturnLength, HWND hwndCallback); #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef GetKerningPairs -#define GetKerningPairs error use qxeGetKerningPairs or GetKerningPairsA/GetKerningPairsW +#undef mciGetDeviceID +#define mciGetDeviceID error_use_qxemciGetDeviceID_or_mciGetDeviceIDA_and_mciGetDeviceIDW #endif -DWORD qxeGetKerningPairs (HDC arg1, DWORD arg2, LPKERNINGPAIR arg3); - -#undef GetLogColorSpace -#define GetLogColorSpace error split-sized LPLOGCOLORSPACE; NT 4.0+ only - -#undef CreateColorSpace -#define CreateColorSpace error split-sized LPLOGCOLORSPACE; NT 4.0+ only - -/* Skipping GetICMProfile because NT 4.0+ only, error in Cygwin prototype */ +MCIDEVICEID qxemciGetDeviceID (const Extbyte * pszDevice); -#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef SetICMProfile -#define SetICMProfile error use qxeSetICMProfile or SetICMProfileA/SetICMProfileW -#endif -BOOL qxeSetICMProfile (HDC arg1, Extbyte * arg2); +#if !defined (MINGW) +#undef mciGetDeviceIDFromElementID +#define mciGetDeviceIDFromElementID error_missing_from_Win98se_version_of_ADVAPI32_dll +#endif /* !defined (MINGW) */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED -#undef EnumICMProfiles -#define EnumICMProfiles error use qxeEnumICMProfiles or EnumICMProfilesA/EnumICMProfilesW +#undef mciGetErrorString +#define mciGetErrorString error_use_qxemciGetErrorString_or_mciGetErrorStringA_and_mciGetErrorStringW #endif -int qxeEnumICMProfiles (HDC arg1, ICMENUMPROCW arg2, LPARAM arg3); - -/* Skipping UpdateICMRegKey because NT 4.0+ only, error in Cygwin prototype */ - -#undef wglUseFontBitmaps -#define wglUseFontBitmaps error causes link error - -#undef wglUseFontOutlines -#define wglUseFontOutlines error causes link error +BOOL qxemciGetErrorString (MCIERROR mcierr, Extbyte * pszText, UINT cchText); diff --text -u 'xemacs-21.5.18/src/intl-encap-win32.c' 'xemacs-21.5.19/src/intl-encap-win32.c' Index: ./src/intl-encap-win32.c --- ./src/intl-encap-win32.c Sat Sep 11 13:00:41 2004 +++ ./src/intl-encap-win32.c Tue Jan 25 08:34:00 2005 @@ -1,5 +1,5 @@ /* Unicode-encapsulation of Win32 library functions. - Copyright (C) 2000, 2001, 2002 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -38,118 +38,6 @@ int no_mswin_unicode_lib_calls; -/* The golden rules of writing Unicode-safe code: - --- There are no preprocessor games going on. - --- Do not set the UNICODE constant. - --- You need to change your code to call the Windows API prefixed with "qxe" - functions (when they exist) and use the ...W structs instead of the - generic ones. String arguments in the qxe functions are of type Extbyte - *. - --- You code is responsible for conversion of text arguments. We try to - handle everything else -- the argument differences, the copying back and - forth of structures, etc. Use Qmswindows_tstr and macros such as - C_STRING_TO_TSTR. You are also responsible for interpreting and - specifying string sizes, which have not been changed. Usually these are - in characters, meaning you need to divide by XETCHAR_SIZE. (But, some - functions want sizes in bytes, even with Unicode strings. Look in the - documentation.) Use XETEXT when specifying string constants, so that - they show up in Unicode as necessary. - --- If you need to process external strings (in general you should not do - this; do all your manipulations in internal format and convert at the - point of entry into or exit from the function), use the xet...() - functions. - -more specifically: - -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, and - also with types, where the generic types have names beginning with T -- - TCHAR, LPTSTR, etc.. 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 (you can force use of the A calls on NT, - e.g. for testing purposes, using the command- line switch -nuni aka - -no-unicode-lib-calls), 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. - -NOTE NOTE NOTE: As of August 2001, Microsoft (finally! See my nasty -comment above) released their own Unicode-encapsulation library, called -Microsoft Layer for Unicode on Windows 95/98/Me Systems. It tries to be -more transparent than we are, in that - --- its routines do ANSI/Unicode string translation, while we don't, for - efficiency (we already have to do internal/external conversion so it's - no extra burden to do the proper conversion directly rather than always - converting to Unicode and then doing a second conversion to ANSI as - necessary) - --- rather than requiring separately-named routines (qxeFooBar), they - physically override the existing routines at the link level. it also - appears that they do this BADLY, in that if you link with the MLU, you - get an application that runs ONLY on Win9x!!! (hint -- use - GetProcAddress()). there's still no way to create a single binary! - fucking losers. - --- they assume you compile with UNICODE defined, so there's no need for the - application to explicitly use ...W structures, as we require. - --- they also intercept windows procedures to deal with notify messages as - necessary, which we don't do yet. - --- they (of course) don't use Extbyte. - -at some point (especially when they fix the single-binary problem!), we -should consider switching. for the meantime, we'll stick with what i've -already written. perhaps we should think about adopting some of the -greater transparency they have; but i opted against transparency on -purpose, to make the code easier to follow for someone who's not familiar -with it. until our library is really complete and bug-free, we should -think twice before doing this. -*/ - /************************************************************************/ /* auto-generation */ @@ -258,9 +146,9 @@ yes OutputDebugString yes FindResource yes FindResourceEx -yes EnumResourceTypes -yes EnumResourceNames -yes EnumResourceLanguages +skip EnumResourceTypes different prototypes in VC6 and VC7 +skip EnumResourceNames different prototypes in VC6 and VC7 +skip EnumResourceLanguages different prototypes in VC6 and VC7 yes BeginUpdateResource yes UpdateResource yes EndUpdateResource @@ -909,7 +797,7 @@ yes ImmGetDescription yes ImmGetIMEFileName yes ImmGetCompositionString -yes ImmSetCompositionString +skip ImmSetCompositionString different prototypes in VC6 and VC7 yes ImmGetCandidateListCount yes ImmGetCandidateList yes ImmGetGuideLine @@ -1361,6 +1249,69 @@ #endif /* not CYGWIN */ +/********************************************************************************/ +/* would be encapsulatable but for header changes in different versions of VC++ */ +/********************************************************************************/ + +#if MSC_VERSION >= 1300 + +BOOL +qxeEnumResourceTypes (HMODULE hModule, ENUMRESTYPEPROCW lpEnumFunc, LONG lParam) +{ + if (XEUNICODE_P) + return EnumResourceTypesW (hModule, lpEnumFunc, lParam); + else + return EnumResourceTypesA (hModule, (ENUMRESTYPEPROCA) lpEnumFunc, lParam); +} + +BOOL +qxeEnumResourceNames (HMODULE hModule, const Extbyte * lpType, ENUMRESNAMEPROCW lpEnumFunc, LONG lParam) +{ + if (XEUNICODE_P) + return EnumResourceNamesW (hModule, (LPCWSTR) lpType, lpEnumFunc, lParam); + else + return EnumResourceNamesA (hModule, (LPCSTR) lpType, (ENUMRESNAMEPROCA) lpEnumFunc, lParam); +} + +BOOL +qxeEnumResourceLanguages (HMODULE hModule, const Extbyte * lpType, const Extbyte * lpName, ENUMRESLANGPROCW lpEnumFunc, LONG lParam) +{ + if (XEUNICODE_P) + return EnumResourceLanguagesW (hModule, (LPCWSTR) lpType, (LPCWSTR) lpName, lpEnumFunc, lParam); + else + return EnumResourceLanguagesA (hModule, (LPCSTR) lpType, (LPCSTR) lpName, (ENUMRESLANGPROCA) lpEnumFunc, lParam); +} + +#else + +BOOL +qxeEnumResourceTypes (HMODULE hModule, ENUMRESTYPEPROC lpEnumFunc, LONG lParam) +{ + if (XEUNICODE_P) + return EnumResourceTypesW (hModule, lpEnumFunc, lParam); + else + return EnumResourceTypesA (hModule, lpEnumFunc, lParam); +} + +BOOL +qxeEnumResourceNames (HMODULE hModule, const Extbyte * lpType, ENUMRESNAMEPROC lpEnumFunc, LONG lParam) +{ + if (XEUNICODE_P) + return EnumResourceNamesW (hModule, (LPCWSTR) lpType, lpEnumFunc, lParam); + else + return EnumResourceNamesA (hModule, (LPCSTR) lpType, lpEnumFunc, lParam); +} + +BOOL +qxeEnumResourceLanguages (HMODULE hModule, const Extbyte * lpType, const Extbyte * lpName, ENUMRESLANGPROC lpEnumFunc, LONG lParam) +{ + if (XEUNICODE_P) + return EnumResourceLanguagesW (hModule, (LPCWSTR) lpType, (LPCWSTR) lpName, lpEnumFunc, lParam); + else + return EnumResourceLanguagesA (hModule, (LPCSTR) lpType, (LPCSTR) lpName, lpEnumFunc, lParam); +} + +#endif /* MSC_VERSION >= 1300 */ /************************************************************************/ /* files */ @@ -2159,7 +2110,31 @@ return retval; } } - + +#if MSC_VERSION >= 1300 + +BOOL +qxeImmSetCompositionString (HIMC arg1, DWORD dwIndex, LPVOID lpComp, DWORD arg4, LPVOID lpRead, DWORD arg6) +{ + if (XEUNICODE_P) + return ImmSetCompositionStringW (arg1, dwIndex, lpComp, arg4, lpRead, arg6); + else + return ImmSetCompositionStringA (arg1, dwIndex, lpComp, arg4, lpRead, arg6); +} + +#else + +BOOL +qxeImmSetCompositionString (HIMC arg1, DWORD dwIndex, LPCVOID lpComp, DWORD arg4, LPCVOID lpRead, DWORD arg6) +{ + if (XEUNICODE_P) + return ImmSetCompositionStringW (arg1, dwIndex, lpComp, arg4, lpRead, arg6); + else + return ImmSetCompositionStringA (arg1, dwIndex, lpComp, arg4, lpRead, arg6); +} + +#endif /* MSC_VERSION >= 1300 */ + int qxeGetObject (HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject) { @@ -2513,7 +2488,9 @@ if (XEUNICODE_P) return RegisterClassW (&classnew); else - return RegisterClassA ((CONST WNDCLASSA *) &classnew); + /* The intermediate cast fools gcc into not outputting strict-aliasing + complaints */ + return RegisterClassA ((CONST WNDCLASSA *) (void *) &classnew); } BOOL @@ -2557,7 +2534,9 @@ if (XEUNICODE_P) return RegisterClassExW (&classnew); else - return RegisterClassExA ((CONST WNDCLASSEXA *) &classnew); + /* The intermediate cast fools gcc into not outputting strict-aliasing + complaints */ + return RegisterClassExA ((CONST WNDCLASSEXA *) (void *) &classnew); } diff --text -u 'xemacs-21.5.18/src/intl-win32.c' 'xemacs-21.5.19/src/intl-win32.c' Index: ./src/intl-win32.c --- ./src/intl-win32.c Fri Oct 15 02:26:24 2004 +++ ./src/intl-win32.c Tue Jan 25 08:34:00 2005 @@ -1,5 +1,5 @@ /* Win32 internationalization functions. - Copyright (C) 2000, 2001, 2002 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2004 Ben Wing. Copyright (C) 2000 IKEYAMA Tomonori. This file is part of XEmacs. @@ -53,6 +53,15 @@ # define NO_EXT_MULTIBYTE_FEATURES #endif + + +/* + +Detailed info on Microsoft Windows-Related Multilingual Issues: + + (Info-goto-node "(internals)Microsoft Windows-Related Multilingual Issues") +*/ + Lisp_Object Qmswindows_multibyte, Qmswindows_multibyte_to_unicode; Lisp_Object Qmswindows_tstr, Qmswindows_unicode; Lisp_Object Qmswindows_multibyte_system_default; @@ -73,74 +82,6 @@ /* Language/locale/code page conversion functions */ /************************************************************************/ -/* There are various different ways of representing the vague concept - of "language", and it can be very confusing. So: - - -- The C library has the concept of "locale", which is a - combination of language and country, and which controls the way - currency and dates are displayed, the encoding of data, etc. - - -- XEmacs has the concept of "language environment", more or less - like a locale; although currently in most cases it just refers to - the language, and no sub-language distinctions are - made. (Exceptions are with Chinese, which has different language - environments for Taiwan and mainland China, due to the different - encodings and writing systems.) - - -- Windows has a number of different language concepts: - - 1. There are "languages" and "sublanguages", which correspond to - the languages and countries of the C library -- e.g. LANG_ENGLISH - and SUBLANG_ENGLISH_US. These are identified by 8-bit integers, - called the "primary language identifier" and "sublanguage - identifier", respectively. These are combined into a 16-bit - integer or "language identifier" by MAKELANGID(). - - 2. The language identifier in turn is combined with a "sort - identifier" (and optionally a "sort version") to yield a 32-bit - integer called a "locale identifier" (type LCID), which identifies - locales -- the primary means of distinguishing language/regional - settings and similar to C library locales. - - 3. "Code pages" identify different text encodings (i.e. a set of - supported characters, an enumeration of those characters [i.e. an - association of character with number or number pair; there may be - disjoint ranges of numbers supported]), and a way of encoding a - stream of those characters into an 8-bit data stream). All of the - encodings are either one-byte or mixed one-byte/two-byte encodings, - all non-modal; in the mixed encodings, two-byte characters have the - first byte >= 128, although the second byte may or may not be - restricted to this range, depending on the encoding. Code pages - are similar to XEmacs "charsets"; the latter also define a set of - supported characters and an enumeration of those characters (but - code pages in additionally define an encoding, which charsets don't - do). Code pages often function in Windows like charsets in XEmacs. - - 4. Every Windows locale has a specific code page associated with - it; more than one locale can share a code page -- e.g. all the - Western European languages, including English, do. - - 5. Windows also has an "input locale identifier" (aka "keyboard - layout id") or HKL, which is a 32-bit integer composed of the - 16-bit language identifier and a 16-bit "device identifier", which - originally specified a particular keyboard layout (e.g. the locale - "US English" can have the QWERTY layout, the Dvorak layout, etc.), - but has been expanded to include speech-to-text converters and - other non-keyboard ways of inputting text. Note that both the HKL - and LCID share the language identifier in the lower 16 bits, and in - both cases a 0 in the upper 16 bits means "default" (sort order or - device), providing a way to convert between HKL's, LCID's, and - language identifiers (i.e. language/sublanguage pairs). The - default keyboard layout for a language is (as far as I can - determine) established using the Regional Settings control panel - applet, where you can add input locales as combinations of language - (actually language/sublanguage) and layout; presumably if you list - only one input locale with a particular language, the corresponding - layout is the default for that language. But what if you list more - than one? You can specify a single default input locale, but there - appears to be no way to do so on a per-language basis. -*/ - struct lang_to_string { int code; @@ -675,7 +616,7 @@ int i; for (i = 0; i < table_size; i++) - if (!strcmp ((char *) XSTRING_DATA (lang), table[i].string)) + if (!qxestrcmp_ascii (XSTRING_DATA (lang), table[i].string)) return table[i].code; return -1; } @@ -688,14 +629,14 @@ for (i = 0; i < table_size; i++) if (table[i].string && - !strcmp ((char *) XSTRING_DATA (lang), table[i].string)) + !qxestrcmp_ascii (XSTRING_DATA (lang), table[i].string)) return table[i].code; - if (!strcmp ((char *) XSTRING_DATA (lang), "NEUTRAL")) + if (!qxestrcmp_ascii (XSTRING_DATA (lang), "NEUTRAL")) return SUBLANG_NEUTRAL; - if (!strcmp ((char *) XSTRING_DATA (lang), "DEFAULT")) + if (!qxestrcmp_ascii (XSTRING_DATA (lang), "DEFAULT")) return SUBLANG_DEFAULT; - if (!strcmp ((char *) XSTRING_DATA (lang), "SYS_DEFAULT")) + if (!qxestrcmp_ascii (XSTRING_DATA (lang), "SYS_DEFAULT")) return SUBLANG_SYS_DEFAULT; return -1; @@ -1093,11 +1034,11 @@ } static DWORD -int_from_hex (Char_ASCII *s) +int_from_hex (Ascbyte *s) { DWORD val = 0; - static Char_ASCII hex[] = "0123456789abcdefABCDEF"; - Char_ASCII *p; + static Ascbyte hex[] = "0123456789abcdefABCDEF"; + Ascbyte *p; while (*s && (p = strchr (hex, *s)) != NULL) { @@ -1115,7 +1056,7 @@ static Lisp_Object Vmswindows_valid_locales; static BOOL CALLBACK -enum_locale_fn (Char_ASCII *localeNum) +enum_locale_fn (Ascbyte *localeNum) { DWORD id = int_from_hex (localeNum); Vmswindows_valid_locales = @@ -1485,7 +1426,7 @@ ()) { int num_layouts = GetKeyboardLayoutList (0, NULL); - HKL * layouts = (HKL *) ALLOCA (num_layouts * sizeof (HKL)); + HKL *layouts = alloca_array (HKL, num_layouts); Lisp_Object obj = Qnil; if (GetKeyboardLayoutList (num_layouts, layouts) == num_layouts) @@ -1682,7 +1623,7 @@ wcsdup (const wchar_t *str) { int len = wcslen (str) + 1; - void *val = xmalloc (len * sizeof (wchar_t)); + wchar_t *val = xnew_array (wchar_t, len); if (val == 0) return 0; return (wchar_t *) memcpy (val, str, len * sizeof (wchar_t)); @@ -1775,7 +1716,7 @@ case MULTIBYTE_SYSTEM_DEFAULT: locale = GetSystemDefaultLCID (); break; default: - abort (); locale = 0; + ABORT (); locale = 0; } switch (data->cp_type) @@ -1811,7 +1752,7 @@ return 0; #endif default: - abort (); return 0; + ABORT (); return 0; } #else /* not MULE */ return CP_ACP; @@ -1884,7 +1825,7 @@ case MULTIBYTE_OEM: return Qoem; case MULTIBYTE_EBCDIC: return Qebcdic; case MULTIBYTE_MAC: return Qmac; - default: abort (); + default: ABORT (); } } else if (EQ (prop, Qlocale)) @@ -1899,7 +1840,7 @@ case MULTIBYTE_SPECIFIED_CODE_PAGE: return Qnil; - default: abort (); + default: ABORT (); } } @@ -1924,6 +1865,10 @@ write_c_string (printcharfun, ")"); } +/* ----------------------------------------------------------------------- */ +/* Unicode/Multibyte converters */ +/* ----------------------------------------------------------------------- */ + /* Convert multibyte to Unicode according to the specified code page and return the value as a malloc()ed string. This currently exists because the TO_INTERNAL_FORMAT() mechanism -- the normal way to do @@ -1934,21 +1879,40 @@ called recursively merely when I'm doing a simple conversion operation? It turns out this can and does happen, consistently, as a result of calling QUIT -- it happens consistently for complicated - reasons outlined in event-msw.c, WM_KEYDOWN handling.) */ + reasons outlined in event-msw.c, WM_KEYDOWN handling.) + + NOTE: These functions are also used at startup. */ Extbyte * convert_multibyte_to_unicode_malloc (const Extbyte *src, Bytecount n, int cp, Bytecount *size_out) { - Bytecount nout = MultiByteToWideChar (cp, 0, src, n, 0, 0); + Charcount nout = MultiByteToWideChar (cp, MBTOWC_OPTIONS, src, n, 0, 0); Extbyte *outp = xnew_array (Extbyte, nout * sizeof (WCHAR)); - MultiByteToWideChar (cp, 0, src, n, (LPWSTR) outp, nout); + MultiByteToWideChar (cp, MBTOWC_OPTIONS, src, n, (LPWSTR) outp, nout); if (size_out) *size_out = nout * sizeof (WCHAR); return outp; } +Extbyte * +convert_unicode_to_multibyte_malloc (const Extbyte *src, Bytecount n, + int cp, Bytecount *size_out) +{ + Bytecount nout = WideCharToMultiByte (cp, WCTOMB_OPTIONS, (LPWSTR) src, + n / sizeof (WCHAR), + 0, 0, WCTOMB_INVALID_STRING, 0); + Extbyte *outp = xnew_array (Extbyte, nout); + + WideCharToMultiByte (cp, WCTOMB_OPTIONS, (LPWSTR) src, + n / sizeof (WCHAR), (LPSTR) outp, nout, + WCTOMB_INVALID_STRING, 0); + if (size_out) + *size_out = nout; + return outp; +} + /* Convert MS Windows multibyte to internal, with specified code page. See above for why this exists, and the TO_INTERNAL_FORMAT() macros aren't just used. */ @@ -1972,6 +1936,69 @@ return intdata; } +static void +unicode_multibyte_convert_now_damn_it (const void *src, Bytecount src_size, + int to_unicode, void **dst, + Bytecount *dst_size, int cp) +{ + if (to_unicode) + { + Charcount nout = MultiByteToWideChar (cp, MBTOWC_OPTIONS, (LPSTR) src, + src_size, 0, 0); + Extbyte *outp = (Extbyte *) stack_like_malloc (nout * sizeof (WCHAR)); + + MultiByteToWideChar (cp, MBTOWC_OPTIONS, (LPSTR) src, src_size, + (LPWSTR) outp, nout); + *dst = (void *) outp; + *dst_size = nout * sizeof (WCHAR); + } + else + { + Bytecount nout = WideCharToMultiByte (cp, WCTOMB_OPTIONS, (LPWSTR) src, + src_size / sizeof (WCHAR), + 0, 0, WCTOMB_INVALID_STRING, 0); + Extbyte *outp = (Extbyte *) stack_like_malloc (nout); + + WideCharToMultiByte (cp, WCTOMB_OPTIONS, (LPWSTR) src, + src_size / sizeof (WCHAR), (LPSTR) outp, nout, + WCTOMB_INVALID_STRING, 0); + *dst = (void *) outp; + *dst_size = nout; + } +} + +Bytecount +unicode_multibyte_convert_size (const char *srctext, const void *src, + Bytecount src_size, int to_unicode, int cp) +{ + alloca_convert_vals vals; + + assert (find_pos_of_existing_active_alloca_convert (srctext) < 0); + + vals.srctext = srctext; + + unicode_multibyte_convert_now_damn_it (src, src_size, to_unicode, &vals.dst, + &vals.dst_size, cp); + + Dynarr_add (active_alloca_convert, vals); + return vals.dst_size; +} + +void * +unicode_multibyte_convert_copy_data (const char *srctext, void *alloca_data) +{ + alloca_convert_vals *vals; + int i = find_pos_of_existing_active_alloca_convert (srctext); + + assert (i >= 0); + vals = Dynarr_atp (active_alloca_convert, i); + assert (alloca_data); + memcpy (alloca_data, vals->dst, vals->dst_size); + stack_like_free (vals->dst); + Dynarr_delete (active_alloca_convert, i); + return alloca_data; +} + /* Convert multibyte to Unicode according to the specified code page and append the results onto the specified Dynarr. See above. */ @@ -1979,15 +2006,33 @@ convert_multibyte_to_unicode_dynarr (const Extbyte *src, Bytecount n, int cp, unsigned_char_dynarr *dst) { - Bytecount nout = MultiByteToWideChar (cp, 0, src, n, 0, 0); + Charcount nout = MultiByteToWideChar (cp, MBTOWC_OPTIONS, src, n, 0, 0); void *outp; Dynarr_add_many (dst, 0, nout * sizeof (WCHAR)); /* dynarr's buffer may be realloc()ed by call above, so access it after */ outp = Dynarr_atp (dst, Dynarr_length (dst) - nout * sizeof (WCHAR)); - MultiByteToWideChar (cp, 0, src, n, (LPWSTR) outp, nout); + MultiByteToWideChar (cp, MBTOWC_OPTIONS, src, n, (LPWSTR) outp, nout); } +void +convert_unicode_to_multibyte_dynarr (const Extbyte *src, Bytecount n, + int cp, unsigned_char_dynarr *dst) +{ + Bytecount nout = WideCharToMultiByte (cp, WCTOMB_OPTIONS, (LPWSTR) src, + n / sizeof (WCHAR), + 0, 0, WCTOMB_INVALID_STRING, 0); + void *outp; + + Dynarr_add_many (dst, 0, nout); + /* dynarr's buffer may be realloc()ed by call above, so access it after */ + outp = Dynarr_atp (dst, Dynarr_length (dst) - nout); + WideCharToMultiByte (cp, WCTOMB_OPTIONS, (LPWSTR) src, + n / sizeof (WCHAR), (LPSTR) outp, nout, + WCTOMB_INVALID_STRING, 0); +} + + /* Convert MS Windows multibyte to Unicode. */ static Bytecount @@ -2054,20 +2099,8 @@ else data->partial_byte_present = 0; - { - int nout = WideCharToMultiByte (data->cp, WC_COMPOSITECHECK, - (LPWSTR) new_src, n / sizeof (WCHAR), - 0, 0, "~", 0); - void *outp; - - Dynarr_add_many (dst, 0, nout); - /* dynarr's buffer may be realloc()ed by call above, so access it - after */ - outp = Dynarr_atp (dst, Dynarr_length (dst) - nout); - WideCharToMultiByte (data->cp, WC_COMPOSITECHECK, (LPWSTR) new_src, - n / sizeof (WCHAR), - (LPSTR) outp, nout, "~", 0); - } + convert_unicode_to_multibyte_dynarr ((Extbyte *) new_src, n, data->cp, + dst); } return orign; } @@ -2113,7 +2146,7 @@ Bytecount orign = n; /* should never be called; is preprocessed away in the canonicalize method */ - abort (); + ABORT (); return orign; } diff --text -u 'xemacs-21.5.18/src/keymap.c' 'xemacs-21.5.19/src/keymap.c' Index: ./src/keymap.c --- ./src/keymap.c Tue Sep 21 04:19:50 2004 +++ ./src/keymap.c Tue Jan 25 08:34:01 2005 @@ -472,7 +472,7 @@ if ((modifiers & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_META | XEMACS_MOD_SUPER | XEMACS_MOD_HYPER | XEMACS_MOD_ALT | XEMACS_MOD_SHIFT)) != 0) - abort (); + ABORT (); k = XKEYMAP (keymap); @@ -547,7 +547,7 @@ Lisp_Object *prev; if (UNBOUNDP (keys)) - abort (); + ABORT (); for (prev = &new_keys, tail = new_keys; ; @@ -1320,13 +1320,13 @@ accept these as aliases for the "real" names? */ (XSTRING_LENGTH (XSYMBOL (*keysym)->name) <= 3 && - (!qxestrcmp_c (name, "LFD") || - !qxestrcmp_c (name, "TAB") || - !qxestrcmp_c (name, "RET") || - !qxestrcmp_c (name, "ESC") || - !qxestrcmp_c (name, "DEL") || - !qxestrcmp_c (name, "SPC") || - !qxestrcmp_c (name, "BS"))) + (!qxestrcmp_ascii (name, "LFD") || + !qxestrcmp_ascii (name, "TAB") || + !qxestrcmp_ascii (name, "RET") || + !qxestrcmp_ascii (name, "ESC") || + !qxestrcmp_ascii (name, "DEL") || + !qxestrcmp_ascii (name, "SPC") || + !qxestrcmp_ascii (name, "BS"))) #endif /* unused */ ) invalid_argument @@ -1338,7 +1338,7 @@ otherwise have the same problem as above. (Gag!) We silently accept these as aliases for the "real" names. */ - else if (!qxestrncmp_c (name, "kp_", 3)) + else if (!qxestrncmp_ascii (name, "kp_", 3)) { /* Likewise, the obsolete keysym binding of kp_.* should not lose. */ DECLARE_EISTRING (temp); @@ -1757,7 +1757,7 @@ else { new_keys = Qnil; - abort (); + ABORT (); } if (EQ (keys, new_keys)) @@ -3134,10 +3134,10 @@ key.modifiers = modifiers; if (NILP (cmd)) - abort (); + ABORT (); cmd = get_keymap (cmd, 0, 1); if (!KEYMAPP (cmd)) - abort (); + ABORT (); vec = make_vector (XVECTOR_LENGTH (thisseq) + 1, Qnil); len = XVECTOR_LENGTH (thisseq); @@ -3335,26 +3335,26 @@ LIST_LOOP (rest, key) { Lisp_Object keysym = XCAR (rest); - if (EQ (keysym, Qcontrol)) eicat_c (bufp, "C-"); - else if (EQ (keysym, Qctrl)) eicat_c (bufp, "C-"); - else if (EQ (keysym, Qmeta)) eicat_c (bufp, "M-"); - else if (EQ (keysym, Qsuper)) eicat_c (bufp, "S-"); - else if (EQ (keysym, Qhyper)) eicat_c (bufp, "H-"); - else if (EQ (keysym, Qalt)) eicat_c (bufp, "A-"); - else if (EQ (keysym, Qshift)) eicat_c (bufp, "Sh-"); + if (EQ (keysym, Qcontrol)) eicat_ascii (bufp, "C-"); + else if (EQ (keysym, Qctrl)) eicat_ascii (bufp, "C-"); + else if (EQ (keysym, Qmeta)) eicat_ascii (bufp, "M-"); + else if (EQ (keysym, Qsuper)) eicat_ascii (bufp, "S-"); + else if (EQ (keysym, Qhyper)) eicat_ascii (bufp, "H-"); + else if (EQ (keysym, Qalt)) eicat_ascii (bufp, "A-"); + else if (EQ (keysym, Qshift)) eicat_ascii (bufp, "Sh-"); else if (CHAR_OR_CHAR_INTP (keysym)) eicat_ch (bufp, XCHAR_OR_CHAR_INT (keysym)); else { CHECK_SYMBOL (keysym); #if 0 /* This is bogus */ - if (EQ (keysym, QKlinefeed)) eicat_c (bufp, "LFD"); - else if (EQ (keysym, QKtab)) eicat_c (bufp, "TAB"); - else if (EQ (keysym, QKreturn)) eicat_c (bufp, "RET"); - else if (EQ (keysym, QKescape)) eicat_c (bufp, "ESC"); - else if (EQ (keysym, QKdelete)) eicat_c (bufp, "DEL"); - else if (EQ (keysym, QKspace)) eicat_c (bufp, "SPC"); - else if (EQ (keysym, QKbackspace)) eicat_c (bufp, "BS"); + if (EQ (keysym, QKlinefeed)) eicat_ascii (bufp, "LFD"); + else if (EQ (keysym, QKtab)) eicat_ascii (bufp, "TAB"); + else if (EQ (keysym, QKreturn)) eicat_ascii (bufp, "RET"); + else if (EQ (keysym, QKescape)) eicat_ascii (bufp, "ESC"); + else if (EQ (keysym, QKdelete)) eicat_ascii (bufp, "DEL"); + else if (EQ (keysym, QKspace)) eicat_ascii (bufp, "SPC"); + else if (EQ (keysym, QKbackspace)) eicat_ascii (bufp, "BS"); else #endif eicat_lstr (bufp, XSYMBOL (keysym)->name); @@ -3567,7 +3567,7 @@ XSET_EVENT_KEY_MODIFIERS (event, KEY_DATA_MODIFIERS (&keys[i])); format_event_object (buf, event, 1); if (i < count - 1) - eicat_c (buf, " "); + eicat_ascii (buf, " "); } Fdeallocate_event (event); } @@ -3661,7 +3661,7 @@ /* OK, the key is for real */ if (target_buffer) { - if (!firstonly) abort (); + if (!firstonly) ABORT (); format_raw_keys (so_far, keys_count + 1, target_buffer); return make_int (1); } diff --text -u 'xemacs-21.5.18/src/libsst.c' 'xemacs-21.5.19/src/libsst.c' Index: ./src/libsst.c --- ./src/libsst.c Wed Mar 13 17:52:50 2002 +++ ./src/libsst.c Fri Nov 5 08:06:39 2004 @@ -147,7 +147,7 @@ /* These are tables of values to be loaded into various gain registers. */ -static UChar_Binary ger_table[][2] = { +static Binbyte ger_table[][2] = { 0xaa, 0xaa, /* -10db */ 0x79, 0xac, 0x41, 0x99, @@ -180,7 +180,7 @@ }; -static UChar_Binary gr_gx_table[][2] = { +static Binbyte gr_gx_table[][2] = { 0x8b, 0x7c, /* -18db */ 0x8b, 0x35, 0x8b, 0x24, @@ -330,7 +330,7 @@ Extbyte buf [255]; struct audio_ioctl ai; int dval1, dval2, tval, rval; - UChar_Binary oldmmr2, newmmr2; + Binbyte oldmmr2, newmmr2; if ( dhz1 == 0 ) dval1 = 0; diff --text -u 'xemacs-21.5.18/src/linuxplay.c' 'xemacs-21.5.19/src/linuxplay.c' Index: ./src/linuxplay.c --- ./src/linuxplay.c Wed Sep 15 05:26:46 2004 +++ ./src/linuxplay.c Fri Nov 5 08:06:39 2004 @@ -72,7 +72,7 @@ static int mix_fd; static int audio_vol; static int audio_fd; -static Char_ASCII *audio_dev = "/dev/dsp"; +static Ascbyte *audio_dev = "/dev/dsp"; /* Intercept SIGINT and SIGHUP in order to close the audio and mixer devices before terminating sound output; this requires reliable @@ -267,7 +267,7 @@ Returns 1 on succes. 0 otherwise. */ static int -linux_play_data_or_file(int fd, UChar_Binary *data, +linux_play_data_or_file(int fd, Binbyte *data, int length, int volume) { size_t (*parsesndfile)(void **dayta,size_t *sz,void **outbuf); @@ -276,7 +276,7 @@ int fmt,speed,tracks; void *pptr, *optr, *cptr, *sptr; int wrtn,rrtn,crtn,prtn; - UChar_Binary sndbuf[SNDBUFSZ]; + Binbyte sndbuf[SNDBUFSZ]; /* We need to read at least the header information before we can start doing anything */ @@ -388,7 +388,7 @@ /* Call "linux_play_data_or_file" with the appropriate parameters for playing pre-loaded data */ int -play_sound_data (UChar_Binary *data, int length, int volume) +play_sound_data (Binbyte *data, int length, int volume) { return linux_play_data_or_file(-1,data,length,volume); } diff --text -u 'xemacs-21.5.18/src/lisp.h' 'xemacs-21.5.19/src/lisp.h' Index: ./src/lisp.h --- ./src/lisp.h Tue Sep 14 23:32:50 2004 +++ ./src/lisp.h Fri Feb 4 01:30:37 2005 @@ -1,7 +1,7 @@ /* Fundamental definitions for XEmacs Lisp interpreter. Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc. Copyright (C) 1993-1996 Richard Mlynarik. - Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2004, 2005 Ben Wing. This file is part of XEmacs. @@ -57,6 +57,40 @@ /* general definitions */ /************************************************************************/ +/* Conventions in comments: + + "Mule-izing" is the process of going through a file and eliminating + assumptions that the internal format (Ibyte * text) is the same as the + external format used by library routines. Mule-ization should also + include replacing *ALL* raw references to `char' or `unsigned char' with + one of the self-documenting types created below. How exactly to do the + conversion, and how to write correctly Mule-ized code, is described in + the internals manual. Files that say "This file is Mule-ized" have + been reviewed at some point; that's not to say that incorrect code hasn't + crept in, though. + + "Unicode-splitting" is the process of fixing a file so that it will + handle external text in Unicode under Microsoft Windows, as appropriate. + ("splitting" because it needs to handle either Unicode or variable-width + multibyte depending on the OS -- NT or 9x). See intl-win32.c. + + #### is a way of marking problems of any sort. + + !!#### marks places that are not properly Mule-ized. + + &&#### marks places that need to be fixed in order for the "8-bit mule" + conversion to work correctly, i.e. in order to support multiple different + buffer formats under Mule, including a fixed 8-bit format. + + ^^#### marks places that need to be fixed in order to eliminate the + assumption that Ibyte * text is composed of 1-byte units (e.g. UTF-16 + is composed of 2-byte units and might be a possible format to consider + for Ibyte * text). + + %%#### marks places that need work for KKCC (the new garbage collector). + + */ + /* -------------------------- include files --------------------- */ /* We include the following generally useful header files so that you @@ -133,37 +167,11 @@ #define trapping_problems_checking_assert_with_message(assertion, msg) #endif -/* ------------------------ definition of EMACS_INT ------------------- */ - -/* EMACS_INT is the underlying integral type into which a Lisp_Object must fit. - In particular, it must be large enough to contain a pointer. - config.h can override this, e.g. to use `long long' for bigger lisp ints. - - #### In point of fact, it would NOT be a good idea for config.h to mess - with EMACS_INT. A lot of code makes the basic assumption that EMACS_INT - is the size of a pointer. */ - -#ifndef SIZEOF_EMACS_INT -# define SIZEOF_EMACS_INT SIZEOF_VOID_P -#endif - -#ifndef EMACS_INT -# if SIZEOF_EMACS_INT == SIZEOF_LONG -# define EMACS_INT long -# elif SIZEOF_EMACS_INT == SIZEOF_INT -# define EMACS_INT int -# elif SIZEOF_EMACS_INT == SIZEOF_LONG_LONG -# define EMACS_INT long long -# else -# error Unable to determine suitable type for EMACS_INT -# endif -#endif - -#ifndef EMACS_UINT -# define EMACS_UINT unsigned EMACS_INT -#endif +/************************************************************************/ +/** Definitions of basic types **/ +/************************************************************************/ -#define BITS_PER_EMACS_INT (SIZEOF_EMACS_INT * BITS_PER_CHAR) +/* ------------- generic 8/16/32/64/128-bit integral types ------------ */ #if SIZEOF_SHORT == 2 #define INT_16_BIT short @@ -223,23 +231,99 @@ #define EFFICIENT_UINT_128_BIT UINT_128_BIT #endif -/* ------------------------ basic char/int typedefs ------------------- */ +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#elif defined (HAVE_INTPTR_T_IN_SYS_TYPES_H) +/* included elsewhere */ +#elif SIZEOF_VOID_P == SIZEOF_INT +typedef int intptr_t; +typedef unsigned int uintptr_t; +#elif SIZEOF_VOID_P == SIZEOF_LONG +typedef long intptr_t; +typedef unsigned long uintptr_t; +#elif defined (SIZEOF_LONG_LONG) && SIZEOF_VOID_P == SIZEOF_LONG_LONG +typedef long long intptr_t; +typedef unsigned long long uintptr_t; +#else +/* Just pray. May break, may not. */ +typedef long intptr_t; +typedef unsigned long uintptr_t; +#endif + +/* ---------------------- definition of EMACS_INT --------------------- */ -/* The definitions we put here use typedefs to attribute specific meaning - to types that by themselves are pretty general. Stuff pointed to by a - char * or unsigned char * will nearly always be one of four types: - a) pointer to internally-formatted text; b) pointer to text in some - external format, which can be defined as all formats other than the - internal one; c) pure ASCII text; d) binary data that is not meant to - be interpreted as text. [A fifth possible type "e) a general pointer - to memory" should be replaced with void *.] Using these more specific - types rather than the general ones helps avoid the confusions that - occur when the semantics of a char * argument being studied are unclear. +/* EMACS_INT is the underlying integral type into which a Lisp_Object must fit. + In particular, it must be large enough to contain a pointer. + config.h can override this, e.g. to use `long long' for bigger lisp ints. + + #### In point of fact, it would NOT be a good idea for config.h to mess + with EMACS_INT. A lot of code makes the basic assumption that EMACS_INT + is the size of a pointer. */ - Note that these typedefs are purely for documentation purposes; from +#ifndef SIZEOF_EMACS_INT +# define SIZEOF_EMACS_INT SIZEOF_VOID_P +#endif + +#ifndef EMACS_INT +# if SIZEOF_EMACS_INT == SIZEOF_LONG +# define EMACS_INT long +# elif SIZEOF_EMACS_INT == SIZEOF_INT +# define EMACS_INT int +# elif SIZEOF_EMACS_INT == SIZEOF_LONG_LONG +# define EMACS_INT long long +# else +# error Unable to determine suitable type for EMACS_INT +# endif +#endif + +#ifndef EMACS_UINT +# define EMACS_UINT unsigned EMACS_INT +#endif + +#define BITS_PER_EMACS_INT (SIZEOF_EMACS_INT * BITS_PER_CHAR) + +/* -------------------------- basic byte typedefs --------------------- */ + +/* The definitions we put here and in the next section use typedefs to + attribute specific meaning to types that by themselves are pretty + general. + + REMEMBER! These typedefs are purely for documentation purposes; from the C code's perspective, they are exactly equivalent to `char *', `unsigned char *', etc., so you can freely use them with library - functions declared as such. */ + functions declared as such. + + (See also "Byte/Character Types" in text.c) + + The basic semantics for `char': + + a) [Ibyte] pointer to internally-formatted text + b) [Extbyte] pointer to text in some external format, which can be + defined as all formats other than the internal one + c) [Ascbyte] pure ASCII text + d) [Binbyte] binary data that is not meant to be interpreted as text + e) [Rawbyte] general data in memory, where we don't care about whether + it's text or binary + f) [Boolbyte] a zero or a one + g) [Bitbyte] a byte used for bit fields + h) [Chbyte] null-semantics `char *'; used when casting an argument to + an external API where the the other types may not be + appropriate + + + Prefixing codes: + + C = plain char, when the base type is unsigned + U = unsigned + S = signed + + Ideally, XEmacs code should NEVER directly use `char' or any type + derived from it. This is for Mule-cleanliness. If you find yourself + wanting or needing to use `char' and one of the above six semantics does + not apply, add a new type of semantics; don't use `char' directly. + + See text.c under "Byte Types", and following sections. +*/ /* The data representing the text in a buffer is logically a set of Ibytes, declared as follows. */ @@ -251,9 +335,10 @@ are function arguments whose values are most commonly literal strings, or where you have to apply a stdlib string function to internal data. - In general, you should avoid this where possible and use Ibyte instead, - for consistency. For example, the new Mule workspace contains - Ibyte versions of the stdlib string functions. */ + In general, you should avoid this where possible and use Ascbyte if the + text is just ASCII (e.g. string literals) or otherwise Ibyte, for + consistency. For example, the new Mule workspace contains Ibyte + versions of the stdlib string functions. */ typedef char CIbyte; @@ -266,16 +351,51 @@ typedef char Extbyte; typedef unsigned char UExtbyte; -/* A byte in a string in binary format: */ -typedef char Char_Binary; -typedef signed char SChar_Binary; -typedef unsigned char UChar_Binary; +#define EXTTEXT_ZTERM_SIZE (sizeof (Extbyte)) /* A byte in a string in entirely US-ASCII format: (Nothing outside the range 00 - 7F) */ -typedef char Char_ASCII; -typedef unsigned char UChar_ASCII; +typedef char Ascbyte; +typedef unsigned char UAscbyte; + +/* A generic memory pointer, no text or binary semantics assumed. + In general, there should be no manipulation of the memory pointed to + by these pointers other than just copying it around. */ + +typedef unsigned char Rawbyte; +typedef char CRawbyte; + +/* A byte in a string in binary (not meant as text) format: */ + +typedef unsigned char Binbyte; +typedef char CBinbyte; +typedef signed char SBinbyte; + +/* A byte used to represent a boolean value: 0 or 1. + Normally use plain Boolint, and only use Boolbyte to save space. */ + +typedef char Boolbyte; + +/* A byte composed of bitfields. Hardly ever used. */ + +typedef unsigned char Bitbyte; + +/* A no-semantics `char'. Used (pretty-much) ONLY for casting arguments to + functions accepting a `char *', `unsigned char *', etc. where the other + types don't exactly apply and what you are logically concerned with is + the type of the function's argument and not its semantics. + + DO NOT DO NOT DO NOT DO NOT use this as a sloppy replacement for one of + the other types. If you're not using this as part of casting an + argument to a function call, and you're not Ben Wing, you're using it + wrong. Go find another one of the types. */ + +typedef char Chbyte; +typedef unsigned char UChbyte; +typedef signed char SChbyte; + +/* ------------------------ other text-related typedefs ------------------- */ /* To the user, a buffer is made up of characters. In the non-Mule world, characters and Ibytes are equivalent, restricted to the range 0 - 255. @@ -309,6 +429,39 @@ typedef int Raw_Ichar; +/* Internal text as a series of textual units (8-bit bytes in the old + "Mule" encoding -- still the standard internal encoding -- and in UTF-8, + but 16-bit bytes in UTF-16 and 32-bit bytes in UTF-32). See text.c. */ + +#ifdef UTF16_IBYTE_FORMAT +#define NON_ASCII_INTERNAL_FORMAT +typedef unsigned short Itext; +#else +typedef Ibyte Itext; +#endif +typedef EMACS_INT Textcount; + +#define ITEXT_SIZE (sizeof (Itext)) +/* Use this to emphasize that we are adding space for the zero-terminator */ +#define ITEXT_ZTERM_SIZE ITEXT_SIZE + +/* Wexttext is wchar_t on WIN32_NATIVE (and perhaps other systems that + support wchar_t's in library functions), and Extbyte otherwise. This is + used whenever we have to do any sort of manipulation of + externally-encoded strings -- generally a very bad idea, and unsafe, but + in some cases we have no choice (especially at startup, and esp. prior + to pdump, where we haven't loaded the Unicode tables necessary for + conversion under Windows). On platforms where the external encoding may + be Unicode (i.e. Windows), we always do our manipulations in Unicode, + converting to and from multibyte if necessary -- otherwise we'd have to + conditionalize on Unicode vs. multibyte all over the place, which is + just a nightmare. */ +#ifdef WIN32_NATIVE +#define WEXTTEXT_IS_WIDE +typedef wchar_t Wexttext; +#else +typedef Extbyte Wexttext; +#endif #if !defined (__cplusplus) || !defined (CPLUSPLUS_INTEGRAL_CLASSES_NOT_YET) @@ -363,8 +516,6 @@ we don't want by creating overloaded versions of them and declaring them private. */ -#undef this - class Bytecount; class Bytebpos; class Bytexpos; @@ -789,33 +940,14 @@ { return Bytecount (x - y); } #endif -#define this c_this - #endif /* __cplusplus */ /* Counts of elements */ typedef EMACS_INT Elemcount; /* Hash codes */ typedef unsigned long Hashcode; - -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#elif defined(HAVE_INTPTR_T_IN_SYS_TYPES_H) -/* included elsewhere */ -#elif SIZEOF_VOID_P == SIZEOF_INT -typedef int intptr_t; -typedef unsigned int uintptr_t; -#elif SIZEOF_VOID_P == SIZEOF_LONG -typedef long intptr_t; -typedef unsigned long uintptr_t; -#elif defined(SIZEOF_LONG_LONG) && SIZEOF_VOID_P == SIZEOF_LONG_LONG -typedef long long intptr_t; -typedef unsigned long long uintptr_t; -#else -/* Just pray. May break, may not. */ -typedef long intptr_t; -typedef unsigned long uintptr_t; -#endif +/* Booleans */ +typedef int Boolint; /* ------------------------ basic compiler defines ------------------- */ @@ -904,76 +1036,59 @@ from error-checking macros. If we're not tricky, we just get the file and line of the inline function, which is not very useful. */ -#ifdef USE_ASSERTIONS /* Highly dubious kludge */ /* (thanks, Jamie, I feel better now -- ben) */ -MODULE_API void assert_failed (const char *, int, const char *); -# define abort() (assert_failed (__FILE__, __LINE__, "abort()")) +MODULE_API void assert_failed (const Ascbyte *, int, const Ascbyte *); +#define ABORT() (assert_failed (__FILE__, __LINE__, "ABORT()")) + +#ifdef USE_ASSERTIONS # define assert(x) ((x) ? (void) 0 : assert_failed (__FILE__, __LINE__, #x)) # define assert_with_message(x, msg) \ ((x) ? (void) 0 : assert_failed (__FILE__, __LINE__, msg)) # define assert_at_line(x, file, line) \ ((x) ? (void) 0 : assert_failed (file, line, #x)) +#elif defined (DEBUG_XEMACS) +# define assert(x) ((x) ? (void) 0 : (void) ABORT ()) +# define assert_with_message(x, msg) ((x) ? (void) 0 : (void) ABORT ()) +# define assert_at_line(x, file, line) assert (x) #else -# ifdef DEBUG_XEMACS -# define assert(x) ((x) ? (void) 0 : (void) abort ()) -# define assert_with_message(x, msg) ((x) ? (void) 0 : (void) abort ()) -# define assert_at_line(x, file, line) assert (x) -# else -# define assert(x) ((void) 0) -# define assert_with_message(x, msg) -# define assert_at_line(x, file, line) assert (x) -# endif +# define assert(x) ((void) 0) +# define assert_with_message(x, msg) +# define assert_at_line(x, file, line) assert (x) #endif -/* EMACS_INT is the underlying integral type into which a Lisp_Object must fit. - In particular, it must be large enough to contain a pointer. - config.h can override this, e.g. to use `long long' for bigger lisp ints. - - #### In point of fact, it would NOT be a good idea for config.h to mess - with EMACS_INT. A lot of code makes the basic assumption that EMACS_INT - is the size of a pointer. */ - -#ifndef SIZEOF_EMACS_INT -# define SIZEOF_EMACS_INT SIZEOF_VOID_P -#endif +/************************************************************************/ +/** Memory allocation **/ +/************************************************************************/ /* ------------------------ simple memory allocation ------------------- */ -/* Memory allocation */ -void malloc_warning (const char *); +/* Basic memory allocation and freeing functions */ +void malloc_warning (const Ascbyte *); MODULE_API void *xmalloc (Bytecount size) ATTRIBUTE_MALLOC; MODULE_API void *xmalloc_and_zero (Bytecount size) ATTRIBUTE_MALLOC; MODULE_API void *xrealloc (void *, Bytecount size) ATTRIBUTE_MALLOC; -MODULE_API char *xstrdup (const char *) ATTRIBUTE_MALLOC; -/* generally useful */ -#define countof(x) ((int) (sizeof(x)/sizeof((x)[0]))) -#define xnew(type) ((type *) xmalloc (sizeof (type))) -#define xnew_array(type, len) ((type *) xmalloc ((len) * sizeof (type))) -#define xnew_and_zero(type) ((type *) xmalloc_and_zero (sizeof (type))) -#define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue))) -#define xnew_array_and_zero(type, len) ((type *) xmalloc_and_zero ((len) * sizeof (type))) -#define XREALLOC_ARRAY(ptr, type, len) ((void) (ptr = (type *) xrealloc (ptr, (len) * sizeof (type)))) -#define alloca_new(type) ((type *) ALLOCA (sizeof (type))) -#define alloca_array(type, len) ((type *) ALLOCA ((len) * sizeof (type))) - -MODULE_API void *xemacs_c_alloca (unsigned int size) ATTRIBUTE_MALLOC; +MODULE_API Chbyte *xstrdup (const Chbyte *) ATTRIBUTE_MALLOC; -MODULE_API int record_unwind_protect_freeing (void *ptr); +/* Basic free function */ -DECLARE_INLINE_HEADER ( -void * -xmalloc_and_record_unwind (Bytecount size) -) -{ - void *ptr = xmalloc (size); - record_unwind_protect_freeing (ptr); - return ptr; -} +MODULE_API void xfree_1 (void *); +#ifdef ERROR_CHECK_MALLOC +/* This used to use a temporary variable, which both avoided the multiple + evaluation and obviated the need for the TYPE argument. But that triggered + complaints under strict aliasing. #### There should be a better way. */ +#define xfree(lvalue, type) do \ +{ \ + xfree_1 (lvalue); \ + VOIDP_CAST (lvalue) = (void *) 0xDEADBEEF; \ +} while (0) +#else +#define xfree(lvalue,type) xfree_1 (lvalue) +#endif /* ERROR_CHECK_MALLOC */ -/* Stack allocation. +/* ------------------------ stack allocation -------------------------- */ - Allocating excessively large blocks on the stack can cause crashes. +/* Allocating excessively large blocks on the stack can cause crashes. We provide MALLOC_OR_ALLOCA() below for places where it's likely that large amounts will be allocated; it mallocs the block if it's too big. Unfortunately, that requires a call to unbind_to() at the end of the @@ -1047,6 +1162,20 @@ #define ALLOCA_FUNCALL_OK(size) ALLOCA (size) #endif +MODULE_API void *xemacs_c_alloca (unsigned int size) ATTRIBUTE_MALLOC; + +MODULE_API int record_unwind_protect_freeing (void *ptr); + +DECLARE_INLINE_HEADER ( +void * +xmalloc_and_record_unwind (Bytecount size) +) +{ + void *ptr = xmalloc (size); + record_unwind_protect_freeing (ptr); + return ptr; +} + /* WARNING: If you use this, you must unbind_to() at the end of your function! */ @@ -1058,6 +1187,46 @@ (need_to_check_c_alloca ? xemacs_c_alloca (0) : 0, \ alloca (__temp_alloca_size__))) +/* -------------- convenience functions for memory allocation ------------- */ + +#define countof(x) ((int) (sizeof(x)/sizeof((x)[0]))) +#define xnew(type) ((type *) xmalloc (sizeof (type))) +#define xnew_array(type, len) ((type *) xmalloc ((len) * sizeof (type))) +#define xnew_and_zero(type) ((type *) xmalloc_and_zero (sizeof (type))) +#define xzero(lvalue) ((void) memset (&(lvalue), '\0', sizeof (lvalue))) +#define xnew_array_and_zero(type, len) ((type *) xmalloc_and_zero ((len) * sizeof (type))) + +#define alloca_new(type) ((type *) ALLOCA (sizeof (type))) +#define alloca_array(type, len) ((type *) ALLOCA ((len) * sizeof (type))) + +#define alloca_itexts(num) alloca_array (Itext, num) +#define alloca_ibytes(num) alloca_array (Ibyte, num) +#define alloca_extbytes(num) alloca_array (Extbyte, num) +#define alloca_rawbytes(num) alloca_array (Rawbyte, num) +#define alloca_binbytes(num) alloca_array (Binbyte, num) +#define alloca_ascbytes(num) alloca_array (Ascbyte, num) +#define xmalloc_itexts(num) xnew_array (Itext, num) +#define xnew_ibytes(num) xnew_array (Ibyte, num) +#define xnew_extbytes(num) xnew_array (Extbyte, num) +#define xnew_rawbytes(num) xnew_array (Rawbyte, num) +#define xnew_binbytes(num) xnew_array (Binbyte, num) +#define xnew_ascbytes(num) xnew_array (Ascbyte, num) + +/* Make an alloca'd copy of a Ibyte * */ +#define IBYTE_STRING_TO_ALLOCA(p, lval) \ +do { \ + Ibyte **_bsta_ = (Ibyte **) &(lval); \ + const Ibyte *_bsta_2 = (p); \ + Bytecount _bsta_3 = qxestrlen (_bsta_2); \ + *_bsta_ = alloca_ibytes (1 + _bsta_3); \ + memcpy (*_bsta_, _bsta_2, 1 + _bsta_3); \ +} while (0) + +/* ----------------- convenience functions for reallocation --------------- */ + +#define XREALLOC_ARRAY(ptr, type, len) \ + ((void) (ptr = (type *) xrealloc (ptr, (len) * sizeof (type)))) + /* also generally useful if you want to avoid arbitrary size limits but don't need a full dynamic array. Assumes that BASEVAR points to a malloced array of TYPE objects (or possibly a NULL pointer, @@ -1078,17 +1247,6 @@ } \ } while (0) -MODULE_API void xfree_1 (void *); -#ifdef ERROR_CHECK_MALLOC -#define xfree(lvalue,type) do \ -{ \ - xfree_1 (lvalue); \ - lvalue = (type) 0xDEADBEEF; \ -} while (0) -#else -#define xfree(lvalue,type) xfree_1 (lvalue) -#endif /* ERROR_CHECK_MALLOC */ - /* ------------------------ dynamic arrays ------------------- */ #ifdef ERROR_CHECK_STRUCTURES @@ -1114,7 +1272,7 @@ } Dynarr; MODULE_API void *Dynarr_newf (int elsize); -MODULE_API void Dynarr_resize (void *dy, int size); +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); @@ -1131,7 +1289,7 @@ #ifdef ERROR_CHECK_STRUCTURES DECLARE_INLINE_HEADER ( Dynarr * -Dynarr_verify_1 (void *d, const char *file, int line) +Dynarr_verify_1 (void *d, const Ascbyte *file, int line) ) { Dynarr *dy = (Dynarr *) d; @@ -1142,7 +1300,7 @@ DECLARE_INLINE_HEADER ( Dynarr * -Dynarr_verify_mod_1 (void *d, const char *file, int line) +Dynarr_verify_mod_1 (void *d, const Ascbyte *file, int line) ) { Dynarr *dy = (Dynarr *) d; @@ -1216,7 +1374,12 @@ Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats); #endif -/* Counts of bytes or chars */ +void *stack_like_malloc (Bytecount size); +void stack_like_free (void *val); + +/************************************************************************/ +/** Definitions of more complex types **/ +/************************************************************************/ /* Note that the simplest typedefs are near the top of this file. */ @@ -1671,22 +1834,13 @@ macros will hit an assertion failure if the structure is ill-formed; the external-list macros will signal an error in this case, either a malformed-list error or a circular-list error. - - Note also that the simplest external list iterator, EXTERNAL_LIST_LOOP, - does *NOT* check for circularities. Therefore, make sure you call - QUIT each iteration or so. However, it's probably easier just to use - EXTERNAL_LIST_LOOP_2, which is easier to use in any case. */ -/* LIST_LOOP and EXTERNAL_LIST_LOOP are the simplest macros. They don't - require brace surrounding, and iterate through a list, which may or may - not known to be syntactically correct. EXTERNAL_LIST_LOOP is for those - not known to be correct, and it detects and signals a malformed list - error when encountering a problem. Circularities, however, are not - handled, and cause looping forever, so make sure to include a QUIT. - These functions also accept two args, TAIL (set progressively to each - cons starting with the first), and LIST, the list to iterate over. - TAIL needs to be defined by the program. +/* LIST_LOOP is a simple, old-fashioned macro. It doesn't require brace + surrounding, and iterates through a list, which may or may not known to + be syntactically correct. It accepts two args, TAIL (set progressively + to each cons starting with the first), and LIST, the list to iterate + over. TAIL needs to be defined by the caller. In each iteration, you can retrieve the current list item using XCAR (tail), or destructively modify the list using XSETCAR (tail, @@ -1697,12 +1851,6 @@ !NILP (tail); \ tail = XCDR (tail)) -#define EXTERNAL_LIST_LOOP(tail, list) \ - for (tail = list; !NILP (tail); tail = XCDR (tail)) \ - if (!CONSP (tail)) \ - signal_malformed_list_error (list); \ - else - /* The following macros are the "core" macros for list traversal. *** ALL OF THESE MACROS MUST BE DECLARED INSIDE BRACES -- SEE ABOVE. *** @@ -1757,6 +1905,22 @@ PRIVATE_EXTERNAL_LIST_LOOP_6 (elt, list, len_##elt, hare_##elt, \ tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH) + +#define GC_EXTERNAL_LIST_LOOP_2(elt, list) \ +do { \ + XGCDECL3 (elt); \ + Lisp_Object elt, hare_##elt, tortoise_##elt; \ + EMACS_INT len_##elt; \ + XGCPRO3 (elt, elt, hare_##elt, tortoise_##elt); \ + PRIVATE_EXTERNAL_LIST_LOOP_6 (elt, list, len_##elt, hare_##elt, \ + tortoise_##elt, \ + CIRCULAR_LIST_SUSPICION_LENGTH) + +#define END_GC_EXTERNAL_LIST_LOOP(elt) \ + XUNGCPRO (elt); \ +} \ +while (0) + #define EXTERNAL_LIST_LOOP_3(elt, list, tail) \ Lisp_Object elt, tail, tortoise_##elt; \ EMACS_INT len_##elt; \ @@ -1814,7 +1978,7 @@ /* For a list that's known to be in valid list format, where we may be deleting the current element out of the list -- - will abort() if the list is not in valid format */ + will ABORT() if the list is not in valid format */ #define LIST_LOOP_DELETING(consvar, nextconsvar, list) \ for (consvar = list; \ !NILP (consvar) ? (nextconsvar = XCDR (consvar), 1) :0; \ @@ -2036,30 +2200,29 @@ ((void) signal_circular_property_list_error (list)) : \ ((void) 0))))) -/* For a property list (alternating keywords/values) that may not be - in valid list format -- will signal an error if the list is not in - valid format. CONSVAR is used to keep track of the iterations - without modifying PLIST. - - We have to be tricky to still keep the same C format.*/ -#define EXTERNAL_PROPERTY_LIST_LOOP(tail, key, value, plist) \ +#define PRIVATE_PROPERTY_LIST_LOOP_4(tail, key, value, plist) \ for (tail = plist; \ - (CONSP (tail) && CONSP (XCDR (tail)) ? \ - (key = XCAR (tail), value = XCAR (XCDR (tail))) : \ - (key = Qunbound, value = Qunbound)), \ - !NILP (tail); \ - tail = XCDR (XCDR (tail))) \ - if (UNBOUNDP (key)) \ - Fsignal (Qmalformed_property_list, list1 (plist)); \ - else - -#define PROPERTY_LIST_LOOP(tail, key, value, plist) \ - for (tail = plist; \ - NILP (tail) ? 0 : \ - (key = XCAR (tail), tail = XCDR (tail), \ - value = XCAR (tail), tail = XCDR (tail), 1); \ + NILP (tail) ? 0 : \ + (key = XCAR (tail), tail = XCDR (tail), \ + value = XCAR (tail), tail = XCDR (tail), 1); \ ) +#define PROPERTY_LIST_LOOP_3(key, value, plist) \ + Lisp_Object key, value, tail_##key; \ + PRIVATE_PROPERTY_LIST_LOOP_4 (tail_##key, key, value, plist) + +#define GC_PROPERTY_LIST_LOOP_3(key, value, plist) \ +do { \ + XGCDECL3 (key); \ + Lisp_Object key, value, tail_##key; \ + XGCPRO3 (key, key, value, tail_##key); \ + PRIVATE_PROPERTY_LIST_LOOP_4 (tail_##key, key, value, plist) + +#define END_GC_PROPERTY_LIST_LOOP(key) \ + XUNGCPRO (key); \ +} \ +while (0) + /* Return 1 if LIST is properly acyclic and nil-terminated, else 0. */ DECLARE_INLINE_HEADER ( int @@ -2374,7 +2537,7 @@ #define CONCHECK_MARKER(x) CONCHECK_RECORD (x, marker) /* The second check was looking for GCed markers still in use */ -/* if (INTP (XMARKER (x)->lheader.next.v)) abort (); */ +/* if (INTP (XMARKER (x)->lheader.next.v)) ABORT (); */ #define marker_next(m) ((m)->next) #define marker_prev(m) ((m)->prev) @@ -2387,7 +2550,7 @@ DECLARE_INLINE_HEADER ( Ichar -XCHAR_1 (Lisp_Object obj, const char *file, int line) +XCHAR_1 (Lisp_Object obj, const Ascbyte *file, int line) ) { assert_at_line (CHARP (obj), file, line); @@ -2455,7 +2618,7 @@ DECLARE_INLINE_HEADER ( EMACS_INT -XINT_1 (Lisp_Object obj, const char *file, int line) +XINT_1 (Lisp_Object obj, const Ascbyte *file, int line) ) { assert_at_line (INTP (obj), file, line); @@ -2464,7 +2627,7 @@ DECLARE_INLINE_HEADER ( EMACS_INT -XCHAR_OR_INT_1 (Lisp_Object obj, const char *file, int line) +XCHAR_OR_INT_1 (Lisp_Object obj, const Ascbyte *file, int line) ) { assert_at_line (INTP (obj) || CHARP (obj), file, line); @@ -2959,10 +3122,9 @@ #define HASH9(a,b,c,d,e,f,g,h,i) (GOOD_HASH * HASH8 (a,b,c,d,e,f,g,h) + (i)) #define LISP_HASH(obj) ((unsigned long) LISP_TO_VOID (obj)) -unsigned long string_hash (const char *xv); -unsigned long memory_hash (const void *xv, Bytecount size); -unsigned long internal_hash (Lisp_Object obj, int depth); -unsigned long internal_array_hash (Lisp_Object *arr, int size, int depth); +Hashcode memory_hash (const void *xv, Bytecount size); +Hashcode internal_hash (Lisp_Object obj, int depth); +Hashcode internal_array_hash (Lisp_Object *arr, int size, int depth); /************************************************************************/ @@ -3069,9 +3231,7 @@ gcpro (const gcpro& g) : next (g.next), var (g.var), nvars (g.nvars) { } gcpro& operator= (const gcpro& g) { next = g.next; var = g.var; nvars = g.nvars; -#undef this return *this;} -#define this c_this ~gcpro () { assert (!next); } #endif /* defined (__cplusplus) && defined (ERROR_CHECK_GC) */ }; @@ -3095,114 +3255,93 @@ BEGIN_C_DECLS +#define XGCDECL1(x) struct gcpro x##cpro1 +#define XGCDECL2(x) struct gcpro x##cpro1, x##cpro2 +#define XGCDECL3(x) struct gcpro x##cpro1, x##cpro2, x##cpro3 +#define XGCDECL4(x) struct gcpro x##cpro1, x##cpro2, x##cpro3, x##cpro4 +#define XGCDECL5(x) struct gcpro x##cpro1, x##cpro2, x##cpro3, x##cpro4, x##cpro5 + #ifdef DEBUG_GCPRO -MODULE_API void debug_gcpro1 (char *, int, struct gcpro *, Lisp_Object *); -MODULE_API void debug_gcpro2 (char *, int, struct gcpro *, struct gcpro *, +MODULE_API void debug_gcpro1 (Ascbyte *, int, struct gcpro *, Lisp_Object *); +MODULE_API void debug_gcpro2 (Ascbyte *, int, struct gcpro *, struct gcpro *, Lisp_Object *, Lisp_Object *); -MODULE_API void debug_gcpro3 (char *, int, struct gcpro *, struct gcpro *, +MODULE_API void debug_gcpro3 (Ascbyte *, int, struct gcpro *, struct gcpro *, struct gcpro *, Lisp_Object *, Lisp_Object *, Lisp_Object *); -MODULE_API void debug_gcpro4 (char *, int, struct gcpro *, struct gcpro *, +MODULE_API void debug_gcpro4 (Ascbyte *, int, struct gcpro *, struct gcpro *, struct gcpro *, struct gcpro *, Lisp_Object *, Lisp_Object *, Lisp_Object *, Lisp_Object *); -MODULE_API void debug_gcpro5 (char *, int, struct gcpro *, struct gcpro *, +MODULE_API void debug_gcpro5 (Ascbyte *, int, struct gcpro *, struct gcpro *, struct gcpro *, struct gcpro *, struct gcpro *, Lisp_Object *, Lisp_Object *, Lisp_Object *, Lisp_Object *, Lisp_Object *); -MODULE_API void debug_ungcpro(char *, int, struct gcpro *); +MODULE_API void debug_ungcpro(Ascbyte *, int, struct gcpro *); -#define GCPRO1(v) \ - debug_gcpro1 (__FILE__, __LINE__,&gcpro1,&v) -#define GCPRO2(v1,v2) \ - debug_gcpro2 (__FILE__, __LINE__,&gcpro1,&gcpro2,&v1,&v2) -#define GCPRO3(v1,v2,v3) \ - debug_gcpro3 (__FILE__, __LINE__,&gcpro1,&gcpro2,&gcpro3,&v1,&v2,&v3) -#define GCPRO4(v1,v2,v3,v4) \ - debug_gcpro4 (__FILE__, __LINE__,&gcpro1,&gcpro2,&gcpro3,&gcpro4,\ +#define XGCPRO1(x,v) \ + debug_gcpro1 (__FILE__, __LINE__,&x##cpro1,&v) +#define XGCPRO2(x,v1,v2) \ + debug_gcpro2 (__FILE__, __LINE__,&x##cpro1,&x##cpro2,&v1,&v2) +#define XGCPRO3(x,v1,v2,v3) \ + debug_gcpro3 (__FILE__, __LINE__,&x##cpro1,&x##cpro2,&x##cpro3, \ + &v1,&v2,&v3) +#define XGCPRO4(x,v1,v2,v3,v4) \ + debug_gcpro4 (__FILE__, __LINE__,&x##cpro1,&x##cpro2,&x##cpro3, \ + &x##cpro4, \ &v1,&v2,&v3,&v4) -#define GCPRO5(v1,v2,v3,v4,v5) \ - debug_gcpro5 (__FILE__, __LINE__,&gcpro1,&gcpro2,&gcpro3,&gcpro4,&gcpro5,\ +#define XGCPRO5(x,v1,v2,v3,v4,v5) \ + debug_gcpro5 (__FILE__, __LINE__,&x##cpro1,&x##cpro2,&x##cpro3, \ + &x##cpro4,&x##cpro5, \ &v1,&v2,&v3,&v4,&v5) -#define UNGCPRO \ - debug_ungcpro(__FILE__, __LINE__,&gcpro1) - -#define NGCPRO1(v) \ - debug_gcpro1 (__FILE__, __LINE__,&ngcpro1,&v) -#define NGCPRO2(v1,v2) \ - debug_gcpro2 (__FILE__, __LINE__,&ngcpro1,&ngcpro2,&v1,&v2) -#define NGCPRO3(v1,v2,v3) \ - debug_gcpro3 (__FILE__, __LINE__,&ngcpro1,&ngcpro2,&ngcpro3,&v1,&v2,&v3) -#define NGCPRO4(v1,v2,v3,v4) \ - debug_gcpro4 (__FILE__, __LINE__,&ngcpro1,&ngcpro2,&ngcpro3,&ngcpro4,\ - &v1,&v2,&v3,&v4) -#define NGCPRO5(v1,v2,v3,v4,v5) \ - debug_gcpro5 (__FILE__, __LINE__,&ngcpro1,&ngcpro2,&ngcpro3,&ngcpro4,\ - &ngcpro5,&v1,&v2,&v3,&v4,&v5) -#define NUNGCPRO \ - debug_ungcpro(__FILE__, __LINE__,&ngcpro1) - -#define NNGCPRO1(v) \ - debug_gcpro1 (__FILE__, __LINE__,&nngcpro1,&v) -#define NNGCPRO2(v1,v2) \ - debug_gcpro2 (__FILE__, __LINE__,&nngcpro1,&nngcpro2,&v1,&v2) -#define NNGCPRO3(v1,v2,v3) \ - debug_gcpro3 (__FILE__, __LINE__,&nngcpro1,&nngcpro2,&nngcpro3,&v1,&v2,&v3) -#define NNGCPRO4(v1,v2,v3,v4) \ - debug_gcpro4 (__FILE__, __LINE__,&nngcpro1,&nngcpro2,&nngcpro3,&nngcpro4,\ - &v1,&v2,&v3,&v4) -#define NNGCPRO5(v1,v2,v3,v4,v5) \ - debug_gcpro5 (__FILE__, __LINE__,&nngcpro1,&nngcpro2,&nngcpro3,&nngcpro4,\ - &nngcpro5,&v1,&v2,&v3,&v4,&v5) -#define NNUNGCPRO \ - debug_ungcpro(__FILE__, __LINE__,&nngcpro1) +#define XUNGCPRO(x) \ + debug_ungcpro(__FILE__, __LINE__,&x##cpro1) #else /* ! DEBUG_GCPRO */ -#define GCPRO1(var1) ((void) ( \ - gcpro1.next = gcprolist, gcpro1.var = &var1, gcpro1.nvars = 1, \ - gcprolist = &gcpro1 )) - -#define GCPRO2(var1, var2) ((void) ( \ - gcpro1.next = gcprolist, gcpro1.var = &var1, gcpro1.nvars = 1, \ - gcpro2.next = &gcpro1, gcpro2.var = &var2, gcpro2.nvars = 1, \ - gcprolist = &gcpro2 )) - -#define GCPRO3(var1, var2, var3) ((void) ( \ - gcpro1.next = gcprolist, gcpro1.var = &var1, gcpro1.nvars = 1, \ - gcpro2.next = &gcpro1, gcpro2.var = &var2, gcpro2.nvars = 1, \ - gcpro3.next = &gcpro2, gcpro3.var = &var3, gcpro3.nvars = 1, \ - gcprolist = &gcpro3 )) - -#define GCPRO4(var1, var2, var3, var4) ((void) ( \ - gcpro1.next = gcprolist, gcpro1.var = &var1, gcpro1.nvars = 1, \ - gcpro2.next = &gcpro1, gcpro2.var = &var2, gcpro2.nvars = 1, \ - gcpro3.next = &gcpro2, gcpro3.var = &var3, gcpro3.nvars = 1, \ - gcpro4.next = &gcpro3, gcpro4.var = &var4, gcpro4.nvars = 1, \ - gcprolist = &gcpro4 )) - -#define GCPRO5(var1, var2, var3, var4, var5) ((void) ( \ - gcpro1.next = gcprolist, gcpro1.var = &var1, gcpro1.nvars = 1, \ - gcpro2.next = &gcpro1, gcpro2.var = &var2, gcpro2.nvars = 1, \ - gcpro3.next = &gcpro2, gcpro3.var = &var3, gcpro3.nvars = 1, \ - gcpro4.next = &gcpro3, gcpro4.var = &var4, gcpro4.nvars = 1, \ - gcpro5.next = &gcpro4, gcpro5.var = &var5, gcpro5.nvars = 1, \ - gcprolist = &gcpro5 )) - -#define GCPRO1_ARRAY(array, n) ((void) ( \ - gcpro1.next = gcprolist, gcpro1.var = array, gcpro1.nvars = n, \ - gcprolist = &gcpro1 )) - -#define GCPRO2_ARRAY(array1, n1, array2, n2) ((void) ( \ - gcpro1.next = gcprolist, gcpro1.var = array1, gcpro1.nvars = n1, \ - gcpro2.next = &gcpro1, gcpro2.var = array2, gcpro2.nvars = n2, \ - gcprolist = &gcpro2 )) - -#define GCPRO3_ARRAY(array1, n1, array2, n2, array3, n3) ((void) ( \ - gcpro1.next = gcprolist, gcpro1.var = array1, gcpro1.nvars = n1, \ - gcpro2.next = &gcpro1, gcpro2.var = array2, gcpro2.nvars = n2, \ - gcpro3.next = &gcpro2, gcpro3.var = array3, gcpro3.nvars = n3, \ - gcprolist = &gcpro3 )) +#define XGCPRO1(x, var1) ((void) ( \ + x##cpro1.next = gcprolist, x##cpro1.var = &var1, x##cpro1.nvars = 1, \ + gcprolist = &x##cpro1 )) + +#define XGCPRO2(x, var1, var2) ((void) ( \ + x##cpro1.next = gcprolist, x##cpro1.var = &var1, x##cpro1.nvars = 1, \ + x##cpro2.next = &x##cpro1, x##cpro2.var = &var2, x##cpro2.nvars = 1, \ + gcprolist = &x##cpro2 )) + +#define XGCPRO3(x, var1, var2, var3) ((void) ( \ + x##cpro1.next = gcprolist, x##cpro1.var = &var1, x##cpro1.nvars = 1, \ + x##cpro2.next = &x##cpro1, x##cpro2.var = &var2, x##cpro2.nvars = 1, \ + x##cpro3.next = &x##cpro2, x##cpro3.var = &var3, x##cpro3.nvars = 1, \ + gcprolist = &x##cpro3 )) + +#define XGCPRO4(x, var1, var2, var3, var4) ((void) ( \ + x##cpro1.next = gcprolist, x##cpro1.var = &var1, x##cpro1.nvars = 1, \ + x##cpro2.next = &x##cpro1, x##cpro2.var = &var2, x##cpro2.nvars = 1, \ + x##cpro3.next = &x##cpro2, x##cpro3.var = &var3, x##cpro3.nvars = 1, \ + x##cpro4.next = &x##cpro3, x##cpro4.var = &var4, x##cpro4.nvars = 1, \ + gcprolist = &x##cpro4 )) + +#define XGCPRO5(x, var1, var2, var3, var4, var5) ((void) ( \ + x##cpro1.next = gcprolist, x##cpro1.var = &var1, x##cpro1.nvars = 1, \ + x##cpro2.next = &x##cpro1, x##cpro2.var = &var2, x##cpro2.nvars = 1, \ + x##cpro3.next = &x##cpro2, x##cpro3.var = &var3, x##cpro3.nvars = 1, \ + x##cpro4.next = &x##cpro3, x##cpro4.var = &var4, x##cpro4.nvars = 1, \ + x##cpro5.next = &x##cpro4, x##cpro5.var = &var5, x##cpro5.nvars = 1, \ + gcprolist = &x##cpro5 )) + +#define XGCPRO1_ARRAY(x, array, n) ((void) ( \ + x##cpro1.next = gcprolist, x##cpro1.var = array, x##cpro1.nvars = n, \ + gcprolist = &x##cpro1 )) + +#define XGCPRO2_ARRAY(x, array1, n1, array2, n2) ((void) ( \ + x##cpro1.next = gcprolist, x##cpro1.var = array1, x##cpro1.nvars = n1, \ + x##cpro2.next = &x##cpro1, x##cpro2.var = array2, x##cpro2.nvars = n2, \ + gcprolist = &x##cpro2 )) + +#define XGCPRO3_ARRAY(x, array1, n1, array2, n2, array3, n3) ((void) ( \ + x##cpro1.next = gcprolist, x##cpro1.var = array1, x##cpro1.nvars = n1, \ + x##cpro2.next = &x##cpro1, x##cpro2.var = array2, x##cpro2.nvars = n2, \ + x##cpro3.next = &x##cpro2, x##cpro3.var = array3, x##cpro3.nvars = n3, \ + gcprolist = &x##cpro3 )) #if defined (__cplusplus) && defined (ERROR_CHECK_GC) /* We need to reset each gcpro to avoid triggering the assert() in @@ -3226,105 +3365,63 @@ #define UNWIND_GCPRO_TO(val) (gcprolist = (val)) #endif /* defined (__cplusplus) && defined (ERROR_CHECK_GC) */ -#define UNGCPRO_1(gcpro1) UNWIND_GCPRO_TO (gcpro1.next) +#define XUNGCPRO(x) UNWIND_GCPRO_TO (x##cpro1.next) -#define UNGCPRO UNGCPRO_1 (gcpro1) +#endif /* ! DEBUG_GCPRO */ -#define NGCPRO1(var1) ((void) ( \ - ngcpro1.next = gcprolist, ngcpro1.var = &var1, ngcpro1.nvars = 1, \ - gcprolist = &ngcpro1 )) - -#define NGCPRO2(var1, var2) ((void) ( \ - ngcpro1.next = gcprolist, ngcpro1.var = &var1, ngcpro1.nvars = 1, \ - ngcpro2.next = &ngcpro1, ngcpro2.var = &var2, ngcpro2.nvars = 1, \ - gcprolist = &ngcpro2 )) - -#define NGCPRO3(var1, var2, var3) ((void) ( \ - ngcpro1.next = gcprolist, ngcpro1.var = &var1, ngcpro1.nvars = 1, \ - ngcpro2.next = &ngcpro1, ngcpro2.var = &var2, ngcpro2.nvars = 1, \ - ngcpro3.next = &ngcpro2, ngcpro3.var = &var3, ngcpro3.nvars = 1, \ - gcprolist = &ngcpro3 )) - -#define NGCPRO4(var1, var2, var3, var4) ((void) ( \ - ngcpro1.next = gcprolist, ngcpro1.var = &var1, ngcpro1.nvars = 1, \ - ngcpro2.next = &ngcpro1, ngcpro2.var = &var2, ngcpro2.nvars = 1, \ - ngcpro3.next = &ngcpro2, ngcpro3.var = &var3, ngcpro3.nvars = 1, \ - ngcpro4.next = &ngcpro3, ngcpro4.var = &var4, ngcpro4.nvars = 1, \ - gcprolist = &ngcpro4 )) - -#define NGCPRO5(var1, var2, var3, var4, var5) ((void) ( \ - ngcpro1.next = gcprolist, ngcpro1.var = &var1, ngcpro1.nvars = 1, \ - ngcpro2.next = &ngcpro1, ngcpro2.var = &var2, ngcpro2.nvars = 1, \ - ngcpro3.next = &ngcpro2, ngcpro3.var = &var3, ngcpro3.nvars = 1, \ - ngcpro4.next = &ngcpro3, ngcpro4.var = &var4, ngcpro4.nvars = 1, \ - ngcpro5.next = &ngcpro4, ngcpro5.var = &var5, ngcpro5.nvars = 1, \ - gcprolist = &ngcpro5 )) - -#define NGCPRO1_ARRAY(array, n) ((void) ( \ - ngcpro1.next = gcprolist, ngcpro1.var = array, ngcpro1.nvars = n, \ - gcprolist = &ngcpro1 )) - -#define NGCPRO2_ARRAY(array1, n1, array2, n2) ((void) ( \ - ngcpro1.next = gcprolist, ngcpro1.var = array1, ngcpro1.nvars = n1, \ - ngcpro2.next = &ngcpro1, ngcpro2.var = array2, ngcpro2.nvars = n2, \ - gcprolist = &ngcpro2 )) - -#define NGCPRO3_ARRAY(array1, n1, array2, n2, array3, n3) ((void) ( \ - ngcpro1.next = gcprolist, ngcpro1.var = array1, ngcpro1.nvars = n1, \ - ngcpro2.next = &ngcpro1, ngcpro2.var = array2, ngcpro2.nvars = n2, \ - ngcpro3.next = &ngcpro2, ngcpro3.var = array3, ngcpro3.nvars = n3, \ - gcprolist = &ngcpro3 )) - -#define NUNGCPRO UNGCPRO_1 (ngcpro1) - -#define NNGCPRO1(var1) ((void) ( \ - nngcpro1.next = gcprolist, nngcpro1.var = &var1, nngcpro1.nvars = 1, \ - gcprolist = &nngcpro1 )) - -#define NNGCPRO2(var1, var2) ((void) ( \ - nngcpro1.next = gcprolist, nngcpro1.var = &var1, nngcpro1.nvars = 1, \ - nngcpro2.next = &nngcpro1, nngcpro2.var = &var2, nngcpro2.nvars = 1, \ - gcprolist = &nngcpro2 )) - -#define NNGCPRO3(var1, var2, var3) ((void) ( \ - nngcpro1.next = gcprolist, nngcpro1.var = &var1, nngcpro1.nvars = 1, \ - nngcpro2.next = &nngcpro1, nngcpro2.var = &var2, nngcpro2.nvars = 1, \ - nngcpro3.next = &nngcpro2, nngcpro3.var = &var3, nngcpro3.nvars = 1, \ - gcprolist = &nngcpro3 )) - -#define NNGCPRO4(var1, var2, var3, var4) ((void) ( \ - nngcpro1.next = gcprolist, nngcpro1.var = &var1, nngcpro1.nvars = 1, \ - nngcpro2.next = &nngcpro1, nngcpro2.var = &var2, nngcpro2.nvars = 1, \ - nngcpro3.next = &nngcpro2, nngcpro3.var = &var3, nngcpro3.nvars = 1, \ - nngcpro4.next = &nngcpro3, nngcpro4.var = &var4, nngcpro4.nvars = 1, \ - gcprolist = &nngcpro4 )) - -#define NNGCPRO5(var1, var2, var3, var4, var5) ((void) ( \ - nngcpro1.next = gcprolist, nngcpro1.var = &var1, nngcpro1.nvars = 1, \ - nngcpro2.next = &nngcpro1, nngcpro2.var = &var2, nngcpro2.nvars = 1, \ - nngcpro3.next = &nngcpro2, nngcpro3.var = &var3, nngcpro3.nvars = 1, \ - nngcpro4.next = &nngcpro3, nngcpro4.var = &var4, nngcpro4.nvars = 1, \ - nngcpro5.next = &nngcpro4, nngcpro5.var = &var5, nngcpro5.nvars = 1, \ - gcprolist = &nngcpro5 )) - -#define NNGCPRO1_ARRAY(array, n) ((void) ( \ - nngcpro1.next = gcprolist, nngcpro1.var = array, nngcpro1.nvars = n, \ - gcprolist = &nngcpro1 )) - -#define NNGCPRO2_ARRAY(array1, n1, array2, n2) ((void) ( \ - nngcpro1.next = gcprolist, nngcpro1.var = array1, nngcpro1.nvars = n1, \ - nngcpro2.next = &nngcpro1, nngcpro2.var = array2, nngcpro2.nvars = n2, \ - gcprolist = &nngcpro2 )) - -#define NNGCPRO3_ARRAY(array1, n1, array2, n2, array3, n3) ((void) ( \ - nngcpro1.next = gcprolist, nngcpro1.var = array1, nngcpro1.nvars = n1, \ - nngcpro2.next = &nngcpro1, nngcpro2.var = array2, nngcpro2.nvars = n2, \ - nngcpro3.next = &nngcpro2, nngcpro3.var = array3, nngcpro3.nvars = n3, \ - gcprolist = &nngcpro3 )) +#define GCDECL1 XGCDECL1 (g) +#define GCDECL2 XGCDECL2 (g) +#define GCDECL3 XGCDECL3 (g) +#define GCDECL4 XGCDECL4 (g) +#define GCDECL5 XGCDECL5 (g) + +#define GCPRO1(a) XGCPRO1 (g,a) +#define GCPRO2(a,b) XGCPRO2 (g,a,b) +#define GCPRO3(a,b,c) XGCPRO3 (g,a,b,c) +#define GCPRO4(a,b,c,d) XGCPRO4 (g,a,b,c,d) +#define GCPRO5(a,b,c,d,e) XGCPRO5 (g,a,b,c,d,e) + +#define GCPRO1_ARRAY(a1,n1) XGCPRO1_ARRAY(g,a1,n1) +#define GCPRO2_ARRAY(a1,n1,a2,n2) XGCPRO2_ARRAY (g,a1,n1,a2,n2) +#define GCPRO3_ARRAY(a1,n1,a2,n2,a3,n3) XGCPRO3_ARRAY (g,a1,n1,a2,n2,a3,n3) + +#define UNGCPRO XUNGCPRO (g) + +#define NGCDECL1 XGCDECL1 (ng) +#define NGCDECL2 XGCDECL2 (ng) +#define NGCDECL3 XGCDECL3 (ng) +#define NGCDECL4 XGCDECL4 (ng) +#define NGCDECL5 XGCDECL5 (ng) + +#define NGCPRO1(a) XGCPRO1 (ng,a) +#define NGCPRO2(a,b) XGCPRO2 (ng,a,b) +#define NGCPRO3(a,b,c) XGCPRO3 (ng,a,b,c) +#define NGCPRO4(a,b,c,d) XGCPRO4 (ng,a,b,c,d) +#define NGCPRO5(a,b,c,d,e) XGCPRO5 (ng,a,b,c,d,e) + +#define NGCPRO1_ARRAY(a1,n1) XGCPRO1_ARRAY(ng,a1,n1) +#define NGCPRO2_ARRAY(a1,n1,a2,n2) XGCPRO2_ARRAY (ng,a1,n1,a2,n2) +#define NGCPRO3_ARRAY(a1,n1,a2,n2,a3,n3) XGCPRO3_ARRAY (ng,a1,n1,a2,n2,a3,n3) + +#define NUNGCPRO XUNGCPRO (ng) + +#define NNGCDECL1 XGCDECL1 (nng) +#define NNGCDECL2 XGCDECL2 (nng) +#define NNGCDECL3 XGCDECL3 (nng) +#define NNGCDECL4 XGCDECL4 (nng) +#define NNGCDECL5 XGCDECL5 (nng) + +#define NNGCPRO1(a) XGCPRO1 (nng,a) +#define NNGCPRO2(a,b) XGCPRO2 (nng,a,b) +#define NNGCPRO3(a,b,c) XGCPRO3 (nng,a,b,c) +#define NNGCPRO4(a,b,c,d) XGCPRO4 (nng,a,b,c,d) +#define NNGCPRO5(a,b,c,d,e) XGCPRO5 (nng,a,b,c,d,e) + +#define NNGCPRO1_ARRAY(a1,n1) XGCPRO1_ARRAY(nng,a1,n1) +#define NNGCPRO2_ARRAY(a1,n1,a2,n2) XGCPRO2_ARRAY (nng,a1,n1,a2,n2) +#define NNGCPRO3_ARRAY(a1,n1,a2,n2,a3,n3) XGCPRO3_ARRAY (nng,a1,n1,a2,n2,a3,n3) -#define NNUNGCPRO UNGCPRO_1 (nngcpro1) - -#endif /* ! DEBUG_GCPRO */ +#define NNUNGCPRO XUNGCPRO (nng) /* Evaluate expr, UNGCPRO, and then return the value of expr. */ #define RETURN_UNGCPRO(expr) do \ @@ -3360,13 +3457,13 @@ /* Help debug crashes gc-marking a staticpro'ed object. */ -MODULE_API void staticpro_1 (Lisp_Object *, char *); -MODULE_API void staticpro_nodump_1 (Lisp_Object *, char *); +MODULE_API void staticpro_1 (Lisp_Object *, Ascbyte *); +MODULE_API void staticpro_nodump_1 (Lisp_Object *, Ascbyte *); #define staticpro(ptr) staticpro_1 (ptr, #ptr) #define staticpro_nodump(ptr) staticpro_nodump_1 (ptr, #ptr) #ifdef HAVE_SHLIB -MODULE_API void unstaticpro_nodump_1 (Lisp_Object *, char *); +MODULE_API void unstaticpro_nodump_1 (Lisp_Object *, Ascbyte *); #define unstaticpro_nodump(ptr) unstaticpro_nodump_1 (ptr, #ptr) #endif @@ -3747,15 +3844,15 @@ EXFUN (Fforce_debugging_signal, 1); SIGTYPE fatal_error_signal (int); -Lisp_Object make_arg_list (int, Extbyte **); -void make_argc_argv (Lisp_Object, int *, Extbyte ***); -void free_argc_argv (Extbyte **); +Lisp_Object make_arg_list (int, Wexttext **); +void make_argc_argv (Lisp_Object, int *, Wexttext ***); +void free_argc_argv (Wexttext **); Lisp_Object split_external_path (const Extbyte *path); Lisp_Object split_env_path (const CIbyte *evarname, const Ibyte *default_); /* Nonzero means don't do interactive redisplay and don't change tty modes */ extern int noninteractive, noninteractive1; -extern int inhibit_non_essential_printing_operations; +extern int inhibit_non_essential_conversion_operations; extern int preparing_for_armageddon; extern Fixnum emacs_priority; extern int suppress_early_error_handler_backtrace; @@ -3998,32 +4095,32 @@ Lisp_Object arg); int set_trapping_problems_flags (int flags); Lisp_Object call_trapping_problems (Lisp_Object warning_class, - const char *warning_string, + const Ascbyte *warning_string, int flags, struct call_trapping_problems_result *problem, Lisp_Object (*fun) (void *), void *arg); Lisp_Object va_call_trapping_problems (Lisp_Object warning_class, - const char *warning_string, + const Ascbyte *warning_string, int flags, struct call_trapping_problems_result *problem, lisp_fn_t fun, int nargs, ...); -Lisp_Object call0_trapping_problems (const char *, Lisp_Object, int); -Lisp_Object call1_trapping_problems (const char *, Lisp_Object, Lisp_Object, +Lisp_Object call0_trapping_problems (const Ascbyte *, Lisp_Object, int); +Lisp_Object call1_trapping_problems (const Ascbyte *, Lisp_Object, Lisp_Object, int); -Lisp_Object call2_trapping_problems (const char *, Lisp_Object, Lisp_Object, +Lisp_Object call2_trapping_problems (const Ascbyte *, Lisp_Object, Lisp_Object, Lisp_Object, int); -Lisp_Object call3_trapping_problems (const char *, Lisp_Object, Lisp_Object, +Lisp_Object call3_trapping_problems (const Ascbyte *, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int); -Lisp_Object call4_trapping_problems (const char *, Lisp_Object, Lisp_Object, +Lisp_Object call4_trapping_problems (const Ascbyte *, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int); -Lisp_Object call5_trapping_problems (const char *, Lisp_Object, Lisp_Object, +Lisp_Object call5_trapping_problems (const Ascbyte *, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, int); -Lisp_Object eval_in_buffer_trapping_problems (const char *, struct buffer *, +Lisp_Object eval_in_buffer_trapping_problems (const Ascbyte *, struct buffer *, Lisp_Object, int); Lisp_Object run_hook_trapping_problems (Lisp_Object, Lisp_Object, int); Lisp_Object safe_run_hook_trapping_problems (Lisp_Object, Lisp_Object, int); @@ -4054,6 +4151,7 @@ int proper_redisplay_wrapping_in_place (void); Lisp_Object internal_catch (Lisp_Object, Lisp_Object (*) (Lisp_Object), Lisp_Object, int * volatile, + Lisp_Object * volatile, Lisp_Object * volatile); Lisp_Object condition_case_1 (Lisp_Object, Lisp_Object (*) (Lisp_Object), @@ -4201,6 +4299,8 @@ Lisp_Object lisp_strerror (int); Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); int internal_delete_file (Lisp_Object); +Ibyte *find_end_of_directory_component (const Ibyte *path, + Bytecount len); /* Defined in filelock.c */ EXFUN (Funlock_buffer, 0); @@ -4288,7 +4388,7 @@ Lisp_Object, int, Error_Behavior); int external_remprop (Lisp_Object *, Lisp_Object, int, Error_Behavior); int internal_equal_trapping_problems (Lisp_Object warning_class, - const char *warning_string, + const Ascbyte *warning_string, int flags, struct call_trapping_problems_result *p, int retval, @@ -4305,8 +4405,8 @@ void check_losing_bytecode (const char *, Lisp_Object); Lisp_Object add_suffix_to_symbol (Lisp_Object symbol, - const Char_ASCII *ascii_string); -Lisp_Object add_prefix_to_symbol (const Char_ASCII *ascii_string, + const Ascbyte *ascii_string); +Lisp_Object add_prefix_to_symbol (const Ascbyte *ascii_string, Lisp_Object symbol); /* Defined in free-hook.c */ @@ -4327,9 +4427,9 @@ extern Lisp_Object Q_resource_type, Q_resource_id; /* Defined in gui.c */ -DECLARE_DOESNT_RETURN (gui_error (const char *reason, +DECLARE_DOESNT_RETURN (gui_error (const Ascbyte *reason, Lisp_Object frob)); -DECLARE_DOESNT_RETURN (gui_error_2 (const char *reason, +DECLARE_DOESNT_RETURN (gui_error_2 (const Ascbyte *reason, Lisp_Object frob0, Lisp_Object frob1)); /* Defined in indent.c */ EXFUN (Findent_to, 3); @@ -4506,9 +4606,14 @@ /* Defined in rangetab.c */ EXFUN (Fclear_range_table, 1); EXFUN (Fget_range_table, 3); -EXFUN (Fmake_range_table, 0); +EXFUN (Fmake_range_table, 1); EXFUN (Fput_range_table, 4); +extern Lisp_Object Qstart_closed_end_open; +extern Lisp_Object Qstart_open_end_open; +extern Lisp_Object Qstart_closed_end_closed; +extern Lisp_Object Qstart_open_end_closed; + void put_range_table (Lisp_Object, EMACS_INT, EMACS_INT, Lisp_Object); int unified_range_table_bytes_needed (Lisp_Object); int unified_range_table_bytes_used (void *); @@ -4555,7 +4660,7 @@ EXFUN (Fding, 3); void init_device_sound (struct device *); -DECLARE_DOESNT_RETURN (report_sound_error (const Char_ASCII *, Lisp_Object)); +DECLARE_DOESNT_RETURN (report_sound_error (const Ascbyte *, Lisp_Object)); /* Defined in specifier.c */ EXFUN (Fadd_spec_to_specifier, 5); @@ -4758,12 +4863,12 @@ DECLARE_INLINE_HEADER (Ibyte *qxestrdup (const Ibyte *s)) { - return (Ibyte *) xstrdup ((const char *) s); + return (Ibyte *) xstrdup ((const Chbyte *) s); } DECLARE_INLINE_HEADER (Bytecount qxestrlen (const Ibyte *s)) { - return strlen ((const char *) s); + return strlen ((const Chbyte *) s); } DECLARE_INLINE_HEADER (Charcount qxestrcharlen (const Ibyte *s)) @@ -4774,177 +4879,186 @@ DECLARE_INLINE_HEADER (int qxestrcmp (const Ibyte *s1, const Ibyte *s2)) { - return strcmp ((const char *) s1, (const char *) s2); + return strcmp ((const Chbyte *) s1, (const Chbyte *) s2); } -DECLARE_INLINE_HEADER (int qxestrcmp_c (const Ibyte *s1, - const char *s2)) +DECLARE_INLINE_HEADER (int qxestrcmp_ascii (const Ibyte *s1, + const Ascbyte *s2)) { - return strcmp ((const char *) s1, s2); + return strcmp ((const Chbyte *) s1, s2); } DECLARE_INLINE_HEADER (int qxestrncmp (const Ibyte *string1, const Ibyte *string2, Bytecount count)) { - return strncmp ((const char *) string1, (const char *) string2, + return strncmp ((const Chbyte *) string1, (const Chbyte *) string2, (size_t) count); } -DECLARE_INLINE_HEADER (int qxestrncmp_c (const Ibyte *string1, - const char *string2, - Bytecount count)) +DECLARE_INLINE_HEADER (int qxestrncmp_ascii (const Ibyte *string1, + const Ascbyte *string2, + Bytecount count)) { - return strncmp ((const char *) string1, string2, (size_t) count); + return strncmp ((const Chbyte *) string1, string2, (size_t) count); } DECLARE_INLINE_HEADER (Ibyte *qxestrcpy (Ibyte *strDest, - const Ibyte *strSource)) + const Ibyte *strSource)) { - return (Ibyte *) strcpy ((char *) strDest, (const char *) strSource); + return (Ibyte *) strcpy ((Chbyte *) strDest, (const Chbyte *) strSource); } -DECLARE_INLINE_HEADER (Ibyte *qxestrcpy_c (Ibyte *strDest, - const char *strSource)) +DECLARE_INLINE_HEADER (Ibyte *qxestrcpy_ascii (Ibyte *strDest, + const Ascbyte *strSource)) { - return (Ibyte *) strcpy ((char *) strDest, strSource); + return (Ibyte *) strcpy ((Chbyte *) strDest, strSource); } DECLARE_INLINE_HEADER (Ibyte *qxestrncpy (Ibyte *strDest, - const Ibyte *strSource, - Bytecount count)) + const Ibyte *strSource, + Bytecount count)) { - return (Ibyte *) strncpy ((char *) strDest, (const char *) strSource, + return (Ibyte *) strncpy ((Chbyte *) strDest, (const Chbyte *) strSource, (size_t) count); } -DECLARE_INLINE_HEADER (Ibyte *qxestrncpy_c (Ibyte *strDest, - const char *strSource, - Bytecount count)) +DECLARE_INLINE_HEADER (Ibyte *qxestrncpy_ascii (Ibyte *strDest, + const Ascbyte *strSource, + Bytecount count)) { - return (Ibyte *) strncpy ((char *) strDest, strSource, (size_t) count); + return (Ibyte *) strncpy ((Chbyte *) strDest, strSource, (size_t) count); } DECLARE_INLINE_HEADER (Ibyte *qxestrcat (Ibyte *strDest, - const Ibyte *strSource)) + const Ibyte *strSource)) { - return (Ibyte *) strcat ((char *) strDest, (const char *) strSource); + return (Ibyte *) strcat ((Chbyte *) strDest, (const Chbyte *) strSource); } -DECLARE_INLINE_HEADER (Ibyte *qxestrcat_c (Ibyte *strDest, - const char *strSource)) +DECLARE_INLINE_HEADER (Ibyte *qxestrcat_ascii (Ibyte *strDest, + const Ascbyte *strSource)) { - return (Ibyte *) strcat ((char *) strDest, strSource); + return (Ibyte *) strcat ((Chbyte *) strDest, strSource); } DECLARE_INLINE_HEADER (Ibyte *qxestrncat (Ibyte *strDest, - const Ibyte *strSource, - Bytecount count)) + const Ibyte *strSource, + Bytecount count)) { - return (Ibyte *) strncat ((char *) strDest, (const char *) strSource, + return (Ibyte *) strncat ((Chbyte *) strDest, (const Chbyte *) strSource, (size_t) count); } -DECLARE_INLINE_HEADER (Ibyte *qxestrncat_c (Ibyte *strDest, - const char *strSource, - Bytecount count)) +DECLARE_INLINE_HEADER (Ibyte *qxestrncat_ascii (Ibyte *strDest, + const Ascbyte *strSource, + Bytecount count)) { - return (Ibyte *) strncat ((char *) strDest, strSource, (size_t) count); + return (Ibyte *) strncat ((Chbyte *) strDest, strSource, (size_t) count); } DECLARE_INLINE_HEADER (Ibyte *qxestrchr (const Ibyte *s, Ichar c)) { assert (c >= 0 && c <= 255); - return (Ibyte *) strchr ((const char *) s, c); + return (Ibyte *) strchr ((const Chbyte *) s, c); } DECLARE_INLINE_HEADER (Ibyte *qxestrrchr (const Ibyte *s, Ichar c)) { assert (c >= 0 && c <= 255); - return (Ibyte *) strrchr ((const char *) s, c); + return (Ibyte *) strrchr ((const Chbyte *) s, c); } DECLARE_INLINE_HEADER (Ibyte *qxestrstr (const Ibyte *string1, - const Ibyte *string2)) + const Ibyte *string2)) { - return (Ibyte *) strstr ((const char *) string1, (const char *) string2); + return (Ibyte *) strstr ((const Chbyte *) string1, (const Chbyte *) string2); } DECLARE_INLINE_HEADER (Bytecount qxestrcspn (const Ibyte *string, const CIbyte *strCharSet)) { - return (Bytecount) strcspn ((const char *) string, strCharSet); + return (Bytecount) strcspn ((const Chbyte *) string, strCharSet); } DECLARE_INLINE_HEADER (Bytecount qxestrspn (const Ibyte *string, const CIbyte *strCharSet)) { - return (Bytecount) strspn ((const char *) string, strCharSet); + return (Bytecount) strspn ((const Chbyte *) string, strCharSet); } DECLARE_INLINE_HEADER (Ibyte *qxestrpbrk (const Ibyte *string, - const CIbyte *strCharSet)) + const CIbyte *strCharSet)) { - return (Ibyte *) strpbrk ((const char *) string, strCharSet); + return (Ibyte *) strpbrk ((const Chbyte *) string, strCharSet); } DECLARE_INLINE_HEADER (Ibyte *qxestrtok (Ibyte *strToken, - const CIbyte *strDelimit)) + const CIbyte *strDelimit)) { - return (Ibyte *) strtok ((char *) strToken, strDelimit); + return (Ibyte *) strtok ((Chbyte *) strToken, strDelimit); } DECLARE_INLINE_HEADER (double qxestrtod (const Ibyte *nptr, Ibyte **endptr)) { - return strtod ((const char *) nptr, (char **) endptr); + return strtod ((const Chbyte *) nptr, (Chbyte **) endptr); } DECLARE_INLINE_HEADER (long qxestrtol (const Ibyte *nptr, Ibyte **endptr, int base)) { - return strtol ((const char *) nptr, (char **) endptr, base); + return strtol ((const Chbyte *) nptr, (Chbyte **) endptr, base); } DECLARE_INLINE_HEADER (unsigned long qxestrtoul (const Ibyte *nptr, Ibyte **endptr, int base)) { - return strtoul ((const char *) nptr, (char **) endptr, base); + return strtoul ((const Chbyte *) nptr, (Chbyte **) endptr, base); } DECLARE_INLINE_HEADER (int qxeatoi (const Ibyte *string)) { - return atoi ((const char *) string); + return atoi ((const Chbyte *) string); } DECLARE_INLINE_HEADER (Ibyte *qxestrupr (Ibyte *s)) { - return (Ibyte *) strupr ((char *) s); + return (Ibyte *) strupr ((Chbyte *) s); } DECLARE_INLINE_HEADER (Ibyte *qxestrlwr (Ibyte *s)) { - return (Ibyte *) strlwr ((char *) s); + return (Ibyte *) strlwr ((Chbyte *) s); } int qxesprintf (Ibyte *buffer, const CIbyte *format, ...) PRINTF_ARGS (2, 3); +DECLARE_INLINE_HEADER (int qxesscanf_ascii_1 (Ibyte *buffer, + const Ascbyte *format, + void *ptr)) +{ + /* #### DAMNIT! No vsscanf! */ + return sscanf ((Chbyte *) buffer, format, ptr); +} + /* Do not use POSIX locale routines. Not Mule-correct. */ #define qxestrcoll DO NOT USE. #define qxestrxfrm DO NOT USE. int qxestrcasecmp (const Ibyte *s1, const Ibyte *s2); -int qxestrcasecmp_c (const Ibyte *s1, const Char_ASCII *s2); +int qxestrcasecmp_ascii (const Ibyte *s1, const Ascbyte *s2); int qxestrcasecmp_i18n (const Ibyte *s1, const Ibyte *s2); -int ascii_strcasecmp (const Char_ASCII *s1, const Char_ASCII *s2); +int ascii_strcasecmp (const Ascbyte *s1, const Ascbyte *s2); int lisp_strcasecmp (Lisp_Object s1, Lisp_Object s2); int lisp_strcasecmp_i18n (Lisp_Object s1, Lisp_Object s2); int qxestrncasecmp (const Ibyte *s1, const Ibyte *s2, Bytecount len); -int qxestrncasecmp_c (const Ibyte *s1, const Char_ASCII *s2, Bytecount len); +int qxestrncasecmp_ascii (const Ibyte *s1, const Ascbyte *s2, + Bytecount len); int qxestrncasecmp_i18n (const Ibyte *s1, const Ibyte *s2, Bytecount len); -int ascii_strncasecmp (const Char_ASCII *s1, const Char_ASCII *s2, +int ascii_strncasecmp (const Ascbyte *s1, const Ascbyte *s2, Bytecount len); int qxememcmp (const Ibyte *s1, const Ibyte *s2, Bytecount len); int qxememcmp4 (const Ibyte *s1, Bytecount len1, @@ -4970,6 +5084,23 @@ Charbpos end, Bytebpos byte_start, Bytebpos byte_end); +typedef struct +{ + const char *srctext; + void *dst; + Bytecount dst_size; +} alloca_convert_vals; + +typedef struct +{ + Dynarr_declare (alloca_convert_vals); +} alloca_convert_vals_dynarr; + +extern alloca_convert_vals_dynarr *active_alloca_convert; + +MODULE_API int find_pos_of_existing_active_alloca_convert (const char * + srctext); + /* Defined in unicode.c */ extern const struct sized_memory_description to_unicode_description; extern const struct sized_memory_description from_unicode_description; @@ -5157,8 +5288,7 @@ extern Lisp_Object Vinvocation_directory, Vinvocation_name; extern Lisp_Object Vlast_command, Vlast_command_char; extern Lisp_Object Vlast_command_event, Vlast_input_event; -extern Lisp_Object Vload_file_name_internal; -extern Lisp_Object Vload_file_name_internal_the_purecopy, Vload_history; +extern Lisp_Object Vload_file_name_internal, Vload_history; extern Lisp_Object Vload_path, Vmark_even_if_inactive, Vmenubar_configuration; extern Lisp_Object Vminibuf_preprompt, Vminibuf_prompt, Vminibuffer_zero; extern Lisp_Object Vmodule_directory, Vmswindows_downcase_file_names; diff --text -u 'xemacs-21.5.18/src/lread.c' 'xemacs-21.5.19/src/lread.c' Index: ./src/lread.c --- ./src/lread.c Tue Sep 21 04:19:50 2004 +++ ./src/lread.c Fri Feb 4 20:57:29 2005 @@ -59,8 +59,8 @@ #endif Lisp_Object Qvariable_domain; /* I18N3 */ Lisp_Object Vvalues, Vstandard_input, Vafter_load_alist; -Lisp_Object Qcurrent_load_list; -Lisp_Object Qload, Qload_file_name, Qload_internal, Qfset; +Lisp_Object Vload_suppress_alist; +Lisp_Object Qload, Qload_internal, Qfset; /* Hash-table that maps directory names to hashes of their contents. */ static Lisp_Object Vlocate_file_hash_table; @@ -118,8 +118,6 @@ our #$ checks are reliable. */ Lisp_Object Vload_file_name_internal; -Lisp_Object Vload_file_name_internal_the_purecopy; - /* Function to use for reading, in `load' and friends. */ Lisp_Object Vload_read_function; @@ -340,6 +338,52 @@ return Qnil; } +/* Check if NONRELOC/RELOC (an absolute filename) is suppressed according + to load-suppress-alist. */ +static int +check_if_suppressed (Ibyte *nonreloc, Lisp_Object reloc) +{ + Bytecount len; + + if (!NILP (reloc)) + { + nonreloc = XSTRING_DATA (reloc); + len = XSTRING_LENGTH (reloc); + } + else + len = qxestrlen (nonreloc); + + if (len >= 4 && !qxestrcmp_ascii (nonreloc + len - 4, ".elc")) + len -= 4; + else if (len >= 3 && !qxestrcmp_ascii (nonreloc + len - 3, ".el")) + len -= 3; + + { + EXTERNAL_LIST_LOOP_2 (acons, Vload_suppress_alist) + { + if (CONSP (acons) && STRINGP (XCAR (acons))) + { + Lisp_Object name = XCAR (acons); + if (XSTRING_LENGTH (name) == len && + !memcmp (XSTRING_DATA (name), nonreloc, len)) + { + struct gcpro gcpro1; + Lisp_Object val; + + GCPRO1 (reloc); + val = Feval (XCDR (acons)); + UNGCPRO; + + if (!NILP (val)) + return 1; + } + } + } + } + + return 0; +} + /* The plague is coming. Ring around the rosy, pocket full of posy, @@ -564,7 +608,7 @@ } } - foundstr = (Ibyte *) ALLOCA (XSTRING_LENGTH (found) + 1); + foundstr = alloca_ibytes (XSTRING_LENGTH (found) + 1); qxestrcpy (foundstr, XSTRING_DATA (found)); foundlen = qxestrlen (foundstr); @@ -689,12 +733,11 @@ internal_bind_lisp_object (&Vload_descriptor_list, Fcons (make_int (fd), Vload_descriptor_list)); internal_bind_lisp_object (&Vload_file_name_internal, found); - internal_bind_lisp_object (&Vload_file_name_internal_the_purecopy, Qnil); /* this is not a simple internal_bind. */ record_unwind_protect (load_force_doc_string_unwind, Vload_force_doc_string_list); Vload_force_doc_string_list = Qnil; - specbind (Qload_file_name, found); + internal_bind_lisp_object (&Vload_file_name, found); #ifdef I18N3 /* set it to nil; a call to #'domain will set it. */ internal_bind_lisp_object (&Vfile_domain, Qnil); @@ -799,10 +842,9 @@ return R_OK; else if (CONSP (mode)) { - Lisp_Object tail; int mask = 0; - EXTERNAL_LIST_LOOP (tail, mode) - mask |= decode_mode_1 (XCAR (tail)); + EXTERNAL_LIST_LOOP_2 (elt, mode) + mask |= decode_mode_1 (elt); return mask; } else @@ -819,6 +861,9 @@ requirements. Allowed symbols are `exists', `executable', `writable', and `readable'. If MODE is nil, it defaults to `readable'. +Filenames are checked against `load-suppress-alist' to determine if they +should be ignored. + `locate-file' keeps hash tables of the directories it searches through, in order to speed things up. It tries valiantly to not get confused in the face of a changing and unpredictable environment, but can occasionally @@ -835,9 +880,8 @@ if (LISTP (suffixes)) { - Lisp_Object tail; - EXTERNAL_LIST_LOOP (tail, suffixes) - CHECK_STRING (XCAR (tail)); + EXTERNAL_LIST_LOOP_2 (elt, suffixes) + CHECK_STRING (elt); } else CHECK_STRING (suffixes); @@ -921,7 +965,7 @@ max = XSTRING_LENGTH (suffixes); fn_len = XSTRING_LENGTH (filename); - fn = (Ibyte *) ALLOCA (max + fn_len + 1); + fn = alloca_ibytes (max + fn_len + 1); memcpy (fn, XSTRING_DATA (filename), fn_len); /* Loop over suffixes. */ @@ -1026,11 +1070,14 @@ if (closure->fd >= 0) { - /* We succeeded; return this descriptor and filename. */ - if (closure->storeptr) - *closure->storeptr = build_intstring (fn); + if (!check_if_suppressed (fn, Qnil)) + { + /* We succeeded; return this descriptor and filename. */ + if (closure->storeptr) + *closure->storeptr = build_intstring (fn); - return 1; + return 1; + } } } /* Keep mapping. */ @@ -1095,9 +1142,9 @@ /* This function can GC */ int absolute = !NILP (Ffile_name_absolute_p (str)); - EXTERNAL_LIST_LOOP (path, path) + EXTERNAL_LIST_LOOP_2 (elt, path) { - int val = locate_file_in_directory (XCAR (path), str, suffixes, storeptr, + int val = locate_file_in_directory (elt, str, suffixes, storeptr, mode); if (val >= 0) return val; @@ -1160,10 +1207,9 @@ Fclrhash (Vlocate_file_hash_table); else { - Lisp_Object pathtail; - EXTERNAL_LIST_LOOP (pathtail, path) + EXTERNAL_LIST_LOOP_2 (elt, path) { - Lisp_Object pathel = Fexpand_file_name (XCAR (pathtail), Qnil); + Lisp_Object pathel = Fexpand_file_name (elt, Qnil); Fremhash (pathel, Vlocate_file_hash_table); } } @@ -1181,7 +1227,7 @@ just look for one for which access(file,MODE) succeeds. In this case, returns a nonnegative value on success. On failure, returns -1. - If STOREPTR is nonzero, it points to a slot where the name of + If STOREPTR is non-nil, it points to a slot where the name of the file actually found should be stored as a Lisp string. Nil is stored there on failure. @@ -1193,7 +1239,7 @@ { /* This function can GC */ Lisp_Object suffixtab = Qnil; - Lisp_Object pathtail, pathel_expanded; + Lisp_Object pathel_expanded; int val; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; @@ -1216,56 +1262,56 @@ suffixtab = locate_file_construct_suffixed_files (str, suffixes); - EXTERNAL_LIST_LOOP (pathtail, path) - { - Lisp_Object pathel = XCAR (pathtail); - Lisp_Object hash_table; - Lisp_Object tail; - int found = 0; - - /* If this path element is relative, we have to look by hand. */ - if (NILP (pathel) || NILP (Ffile_name_absolute_p (pathel))) - { - val = locate_file_in_directory (pathel, str, suffixes, storeptr, - mode); - if (val >= 0) - { - UNGCPRO; - return val; - } - continue; - } - - pathel_expanded = Fexpand_file_name (pathel, Qnil); - hash_table = locate_file_find_directory_hash_table (pathel_expanded); + { + EXTERNAL_LIST_LOOP_2 (pathel, path) + { + Lisp_Object hash_table; + int found = 0; - if (!NILP (hash_table)) - { - /* Loop over suffixes. */ - LIST_LOOP (tail, suffixtab) - if (!NILP (Fgethash (XCAR (tail), hash_table, Qnil))) + /* If this path element is relative, we have to look by hand. */ + if (NILP (pathel) || NILP (Ffile_name_absolute_p (pathel))) + { + val = locate_file_in_directory (pathel, str, suffixes, storeptr, + mode); + if (val >= 0) { - found = 1; - break; + UNGCPRO; + return val; } - } + continue; + } - if (found) - { - /* This is a likely candidate. Look by hand in this directory - so we don't get thrown off if someone byte-compiles a file. */ - val = locate_file_in_directory (pathel, str, suffixes, storeptr, - mode); - if (val >= 0) - { - UNGCPRO; - return val; - } + pathel_expanded = Fexpand_file_name (pathel, Qnil); + hash_table = locate_file_find_directory_hash_table (pathel_expanded); - /* Hmm ... the file isn't actually there. (Or possibly it's - a directory ...) So refresh our hashing. */ - locate_file_refresh_hashing (pathel_expanded); - } + if (!NILP (hash_table)) + { + /* Loop over suffixes. */ + LIST_LOOP_2 (elt, suffixtab) + if (!NILP (Fgethash (elt, hash_table, Qnil))) + { + found = 1; + break; + } + } + + if (found) + { + /* This is a likely candidate. Look by hand in this directory + so we don't get thrown off if someone byte-compiles a file. */ + val = locate_file_in_directory (pathel, str, suffixes, storeptr, + mode); + if (val >= 0) + { + UNGCPRO; + return val; + } + + /* Hmm ... the file isn't actually there. (Or possibly it's + a directory ...) So refresh our hashing. */ + locate_file_refresh_hashing (pathel_expanded); + } + } } /* File is probably not there, but check the hard way just in case. */ @@ -1380,7 +1426,7 @@ READCHARFUN (which can be a stream) to Lisp. --hniksic */ /*specbind (Qstandard_input, readcharfun);*/ - specbind (Qcurrent_load_list, Qnil); + internal_bind_lisp_object (&Vcurrent_load_list, Qnil); #ifdef COMPILED_FUNCTION_ANNOTATION_HACK Vcurrent_compiled_function_annotation = Qnil; @@ -1842,7 +1888,7 @@ else if (sizeof (long) == sizeof (EMACS_INT)) number = atol (read_buffer); else - abort (); + ABORT (); return make_int (number); } #else @@ -3075,9 +3121,7 @@ DEFSYMBOL (Qstandard_input); DEFSYMBOL (Qread_char); - DEFSYMBOL (Qcurrent_load_list); DEFSYMBOL (Qload); - DEFSYMBOL (Qload_file_name); DEFSYMBOL (Qload_internal); DEFSYMBOL (Qfset); @@ -3111,8 +3155,6 @@ void vars_of_lread (void) { - reinit_vars_of_lread (); - DEFVAR_LISP ("values", &Vvalues /* List of values of all expressions which were read, evaluated and printed. Order is reverse chronological. @@ -3146,6 +3188,16 @@ Non-nil iff inside of `load'. */ ); + DEFVAR_LISP ("load-suppress-alist", &Vload_suppress_alist /* +An alist of expressions controlling whether particular files can be loaded. +Each element looks like (FILENAME EXPR). +FILENAME should be a full pathname, but without the .el suffix. +When `load' is run and is about to load the specified file, it evaluates +the form to determine if the file can be loaded. +This variable is normally initialized automatically. +*/ ); + Vload_suppress_alist = Qnil; + DEFVAR_LISP ("after-load-alist", &Vafter_load_alist /* An alist of expressions to be evalled when particular files are loaded. Each element looks like (FILENAME FORMS...). @@ -3260,9 +3312,6 @@ Vload_file_name_internal = Qnil; staticpro (&Vload_file_name_internal); - Vload_file_name_internal_the_purecopy = Qnil; - staticpro (&Vload_file_name_internal_the_purecopy); - #ifdef COMPILED_FUNCTION_ANNOTATION_HACK Vcurrent_compiled_function_annotation = Qnil; staticpro (&Vcurrent_compiled_function_annotation); diff --text -u 'xemacs-21.5.18/src/lrecord.h' 'xemacs-21.5.19/src/lrecord.h' Index: ./src/lrecord.h --- ./src/lrecord.h Tue Apr 6 07:49:56 2004 +++ ./src/lrecord.h Fri Feb 4 01:14:07 2005 @@ -1,6 +1,6 @@ /* The "lrecord" structure (header of a compound lisp object). Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. - Copyright (C) 1996, 2001, 2002 Ben Wing. + Copyright (C) 1996, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -21,6 +21,8 @@ /* Synched up with: Not in FSF. */ +/* This file has been Mule-ized, Ben Wing, 10-13-04. */ + #ifndef INCLUDED_lrecord_h_ #define INCLUDED_lrecord_h_ @@ -227,7 +229,7 @@ struct lrecord_implementation { - const char *name; + const Ascbyte *name; /* information for the dumper: is the object dumpable and should it be dumped. */ @@ -274,7 +276,7 @@ hash to the same value in order for hash tables to work properly. This means that `hash' can be NULL only if the `equal' method is also NULL. */ - unsigned long (*hash) (Lisp_Object, int); + Hashcode (*hash) (Lisp_Object, int); /* Data layout description for your object. See long comment below. */ const struct memory_description *description; @@ -394,7 +396,7 @@ objects, referenced in the DEFINE_*LRECORD_*IMPLEMENTATION*() call; (b) descriptions of global objects to be dumped, registered by dump_add_root_block(); (c) descriptions of global pointers to - non-Lisp_Object heap objects, registered by dump_add_root_struct_ptr(). + non-Lisp_Object heap objects, registered by dump_add_root_block_ptr(). The descriptions need to tell pdump which elements of your structure are Lisp_Objects or structure pointers, plus the descriptions in turn of the non-Lisp_Object structures pointed to. If these structures are you own @@ -446,9 +448,9 @@ does not need to be given here) and global objects, where the size is an argument to the call to dump_add_root_block(). sized_memory_descriptions are used for pointers and arrays in - memory_descriptions and for calls to dump_add_root_struct_ptr(). (#### + memory_descriptions and for calls to dump_add_root_block_ptr(). (#### It is not obvious why this is so in the latter case. Probably, calls to - dump_add_root_struct_ptr() should use plain memory_descriptions and have + dump_add_root_block_ptr() should use plain memory_descriptions and have the size be an argument to the call.) NOTE: Anywhere that a sized_memory_description occurs inside of a plain @@ -497,13 +499,13 @@ ...; } - You'd use XD_STRUCT_PTR, something like: + You'd use XD_BLOCK_PTR, something like: static const struct memory_description foo_description[] = { ... { XD_INT, offsetof (Lisp_Foo, count) }, - { XD_STRUCT_PTR, offsetof (Lisp_Foo, objects), - XD_INDIRECT (0, 0), &lisp_object_description }, + { XD_BLOCK_PTR, offsetof (Lisp_Foo, objects), + XD_INDIRECT (0, 0), { &lisp_object_description } }, ... }; @@ -519,7 +521,7 @@ lisp_object_description_1 }; - Another example of XD_STRUCT_PTR: + Another example of XD_BLOCK_PTR: typedef struct htentry { @@ -557,8 +559,8 @@ const struct memory_description hash_table_description[] = { { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) }, - { XD_STRUCT_PTR, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (0, 1), - &htentry_description }, + { XD_BLOCK_PTR, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (0, 1), + { &htentry_description } }, { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, { XD_END } }; @@ -577,8 +579,8 @@ const struct memory_description specifier_description[] = { ... - { XD_STRUCT_ARRAY, offset (Lisp_Specifier, data), 1, - specifier_extra_description_map }, + { XD_BLOCK_ARRAY, offset (Lisp_Specifier, data), 1, + { specifier_extra_description_map } }, ... { XD_END } }; @@ -627,7 +629,7 @@ An array of Lisp objects or (equivalently) pointers to lrecords. The parameter (i.e. third element) is the count. This would be declared as Lisp_Object foo[666]. For something declared as Lisp_Object *foo, - use XD_STRUCT_PTR, whose description parameter is a sized_memory_description + use XD_BLOCK_PTR, whose description parameter is a sized_memory_description consisting of only XD_LISP_OBJECT and XD_END. XD_LO_LINK @@ -646,35 +648,51 @@ Pointer to undumpable data. Must be NULL when dumping. - XD_STRUCT_PTR + XD_OPAQUE_PTR_CONVERTIBLE + + Pointer to data which is not directly dumpable but can be converted + to a dumpable, opaque external representation. The parameter is + a pointer to an opaque_convert_functions struct. + + XD_OPAQUE_DATA_CONVERTIBLE + + Data which is not directly dumpable but can be converted to a + dumpable, opaque external representation. The parameter is a + pointer to an opaque_convert_functions struct. + + XD_BLOCK_PTR Pointer to block of described memory. (This is misnamed: It is NOT necessarily a pointer to a struct foo.) Parameters are number of contiguous blocks and sized_memory_description. - XD_STRUCT_ARRAY + XD_BLOCK_ARRAY Array of blocks of described memory. Parameters are number of - structures and sized_memory_description. This differs from XD_STRUCT_PTR + structures and sized_memory_description. This differs from XD_BLOCK_PTR in that the parameter is declared as struct foo[666] instead of struct *foo. In other words, the block of memory holding the structures is within the containing structure, rather than being elsewhere, with a pointer in the containing structure. NOTE NOTE NOTE: Be sure that you understand the difference between - XD_STRUCT_PTR and XD_STRUCT_ARRAY: + XD_BLOCK_PTR and XD_BLOCK_ARRAY: - struct foo bar[666], i.e. 666 inline struct foos - --> XD_STRUCT_ARRAY, argument 666, pointing to a description of + --> XD_BLOCK_ARRAY, argument 666, pointing to a description of struct foo - struct foo *bar, i.e. pointer to a block of 666 struct foos - --> XD_STRUCT_PTR, argument 666, pointing to a description of + --> XD_BLOCK_PTR, argument 666, pointing to a description of struct foo - struct foo *bar[666], i.e. 666 pointers to separate blocks of struct foos - --> XD_STRUCT_ARRAY, argument 666, pointing to a description of + --> XD_BLOCK_ARRAY, argument 666, pointing to a description of a single pointer to struct foo; the description is a single - XD_STRUCT_PTR, argument 1, which in turn points to a description + XD_BLOCK_PTR, argument 1, which in turn points to a description of struct foo. + NOTE also that an XD_BLOCK_PTR of 666 foos is equivalent to an + XD_BLOCK_PTR of 1 bar, where the description of `bar' is an + XD_BLOCK_ARRAY of 666 foos. + XD_OPAQUE_DATA_PTR Pointer to dumpable opaque data. Parameter is the size of the data. @@ -693,9 +711,9 @@ parameter of the XD_UNION descriptor to determine if this description applies to the union data, and XD_INDIRECT references refer to the containing object and description. Note that the description applies - "inline" to the union data, like XD_STRUCT_ARRAY and not XD_STRUCT_PTR. + "inline" to the union data, like XD_BLOCK_ARRAY and not XD_BLOCK_PTR. If the union data is a pointer to different types of structures, each - element in the memory_description should be an XD_STRUCT_PTR. See + element in the memory_description should be an XD_BLOCK_PTR. See unicode.c, redisplay.c and objects.c for examples of XD_UNION. XD_UNION_DYNAMIC_SIZE @@ -705,7 +723,7 @@ of the union constant. That is, an object with plain XD_UNION typically has the union declared as `union foo' or as `void *', where an object with XD_UNION_DYNAMIC_SIZE typically has the union as the last element, - and declared as something like char foo[1]. With plain XD_UNION, the + and declared as something like Rawbyte foo[1]. With plain XD_UNION, the object is (usually) of fixed size and always contains enough space for the data associated with all possible union constants, and thus the union constant can potentially change during the lifetime of the object. With @@ -723,13 +741,14 @@ associated with the currently specified (and unchangeable) union constant. - XD_C_STRING + XD_ASCII_STRING - Pointer to a C string. + Pointer to a C string, purely ASCII. XD_DOC_STRING - Pointer to a doc string (C string if positive, opaque value if negative) + Pointer to a doc string (C string in pure ASCII if positive, + opaque value if negative) XD_INT_RESET @@ -779,12 +798,14 @@ XD_LISP_OBJECT, XD_LO_LINK, XD_OPAQUE_PTR, - XD_STRUCT_PTR, - XD_STRUCT_ARRAY, + XD_OPAQUE_PTR_CONVERTIBLE, + XD_OPAQUE_DATA_CONVERTIBLE, XD_OPAQUE_DATA_PTR, + XD_BLOCK_PTR, + XD_BLOCK_ARRAY, XD_UNION, XD_UNION_DYNAMIC_SIZE, - XD_C_STRING, + XD_ASCII_STRING, XD_DOC_STRING, XD_INT_RESET, XD_BYTECOUNT, @@ -840,12 +861,21 @@ #endif }; +union memory_contents_description +{ + /* The first element is used by static initializers only. We always read + from one of the other two pointers. */ + const void *write_only; + const struct sized_memory_description *descr; + const struct opaque_convert_functions *funcs; +}; + struct memory_description { enum memory_description_type type; Bytecount offset; EMACS_INT data1; - const struct sized_memory_description *data2; + union memory_contents_description data2; /* Indicates which subsystems process this entry, plus (potentially) other flags that apply to this entry. */ int flags; @@ -857,6 +887,36 @@ const struct memory_description *description; }; + +struct opaque_convert_functions +{ + /* Used by XD_OPAQUE_PTR_CONVERTIBLE and + XD_OPAQUE_DATA_CONVERTIBLE */ + + /* Converter to external representation, for those objects from + external libraries that can't be directly dumped as opaque data + because they contain pointers. This is called at dump time to + convert to an opaque, pointer-less representation. + + This function must put a pointer to the opaque result in *data + and its size in *size. */ + void (*convert)(const void *object, void **data, Bytecount *size); + + /* Post-conversion cleanup. Optional (null if not provided). + + When provided it will be called post-dumping to free any storage + allocated for the conversion results. */ + void (*convert_free)(const void *object, void *data, Bytecount size); + + /* De-conversion. + + At reload time, rebuilds the object from the converted form. + "object" is 0 for the PTR case, return is ignored in the DATA + case. */ + void *(*deconvert)(void *object, void *data, Bytecount size); + +}; + extern const struct sized_memory_description lisp_object_description; #define XD_INDIRECT(val, delta) (-1 - (Bytecount) ((val) | ((delta) << 8))) @@ -866,11 +926,10 @@ #define XD_INDIRECT_DELTA(code) ((-1 - (code)) >> 8) #define XD_DYNARR_DESC(base_type, sub_desc) \ - { XD_STRUCT_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), sub_desc }, \ + { XD_BLOCK_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), {sub_desc} },\ { XD_INT, offsetof (base_type, cur) }, \ { XD_INT_RESET, offsetof (base_type, max), XD_INDIRECT(1, 0) } \ - /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size. DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies. */ @@ -1154,7 +1213,7 @@ extern const struct lrecord_implementation lrecord_##c_name; \ DECLARE_INLINE_HEADER ( \ structtype * \ -error_check_##c_name (Lisp_Object obj, const char *file, int line) \ +error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ ) \ { \ assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ @@ -1166,7 +1225,7 @@ extern MODULE_API const struct lrecord_implementation lrecord_##c_name; \ DECLARE_INLINE_HEADER ( \ structtype * \ -error_check_##c_name (Lisp_Object obj, const char *file, int line) \ +error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ ) \ { \ assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ @@ -1179,7 +1238,7 @@ extern struct lrecord_implementation lrecord_##c_name; \ DECLARE_INLINE_HEADER ( \ structtype * \ -error_check_##c_name (Lisp_Object obj, const char *file, int line) \ +error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ ) \ { \ assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ @@ -1190,7 +1249,7 @@ # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ DECLARE_INLINE_HEADER ( \ structtype * \ -error_check_##c_name (Lisp_Object obj, const char *file, int line) \ +error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ ) \ { \ assert_at_line (XTYPE (obj) == type_enum, file, line); \ @@ -1205,7 +1264,7 @@ DECLARE_INLINE_HEADER ( Lisp_Object -wrap_record_1 (const void *ptr, enum lrecord_type ty, const char *file, +wrap_record_1 (const void *ptr, enum lrecord_type ty, const Ascbyte *file, int line) ) { @@ -1402,14 +1461,14 @@ overwrite the header information. */ #define copy_sized_lcrecord(dst, src, size) \ - memcpy ((char *) (dst) + sizeof (struct lcrecord_header), \ - (char *) (src) + sizeof (struct lcrecord_header), \ + memcpy ((Rawbyte *) (dst) + sizeof (struct lcrecord_header), \ + (Rawbyte *) (src) + sizeof (struct lcrecord_header), \ (size) - sizeof (struct lcrecord_header)) #define copy_lcrecord(dst, src) copy_sized_lcrecord (dst, src, sizeof (*(dst))) #define zero_sized_lcrecord(lcr, size) \ - memset ((char *) (lcr) + sizeof (struct lcrecord_header), 0, \ + memset ((Rawbyte *) (lcr) + sizeof (struct lcrecord_header), 0, \ (size) - sizeof (struct lcrecord_header)) #define zero_lcrecord(lcr) zero_sized_lcrecord (lcr, sizeof (*(lcr))) @@ -1439,13 +1498,26 @@ /* Dumping */ /************************************************************************/ -/* dump_add_root_struct_ptr (&var, &desc) dumps the structure pointed to by +/* dump_add_root_block_ptr (&var, &desc) dumps the structure pointed to by `var'. This is for a single relocatable pointer located in the data - segment (i.e. the block pointed to is in the heap). */ + segment (i.e. the block pointed to is in the heap). + + If the structure pointed to is not a `struct' but an array, you should + set the size field of the sized_memory_description to 0, and use + XD_BLOCK_ARRAY in the inner memory_description. + + NOTE that a "root struct pointer" could also be described using + dump_add_root_block(), with SIZE == sizeof (void *), and a description + containing a single XD_BLOCK_PTR entry, offset 0, size 1, with a + structure description the same as the value passed to + dump_add_root_block_ptr(). That would require an extra level of + description, though, as compared to using dump_add_root_block_ptr(), + and thus this function is generally more convenient. + */ #ifdef PDUMP -void dump_add_root_struct_ptr (void *, const struct sized_memory_description *); +void dump_add_root_block_ptr (void *, const struct sized_memory_description *); #else -#define dump_add_root_struct_ptr(varaddr,descaddr) DO_NOTHING +#define dump_add_root_block_ptr(varaddr, descaddr) DO_NOTHING #endif /* dump_add_opaque (&var, size) dumps the opaque static structure `var'. @@ -1465,7 +1537,7 @@ void dump_add_root_block (const void *ptraddress, Bytecount size, const struct memory_description *desc); #else -#define dump_add_root_block(ptraddress,desc) DO_NOTHING +#define dump_add_root_block(ptraddress, size, desc) DO_NOTHING #endif /* Call dump_add_opaque_int (&int_var) to dump `int_var', of type `int'. */ @@ -1512,8 +1584,8 @@ #ifdef PDUMP #include "dumper.h" -#define DUMPEDP(adr) ((((char *) (adr)) < pdump_end) && \ - (((char *) (adr)) >= pdump_start)) +#define DUMPEDP(adr) ((((Rawbyte *) (adr)) < pdump_end) && \ + (((Rawbyte *) (adr)) >= pdump_start)) #else #define DUMPEDP(adr) 0 #endif @@ -1534,9 +1606,15 @@ const void *idata); const struct sized_memory_description *lispdesc_indirect_description_1 (const void *obj, const struct sized_memory_description *sdesc); -Bytecount lispdesc_structure_size (const void *obj, - const struct sized_memory_description * - sdesc); +Bytecount lispdesc_block_size_1 (const void *obj, Bytecount size, + const struct memory_description *desc); + +DECLARE_INLINE_HEADER ( +Bytecount lispdesc_block_size (const void *obj, + const struct sized_memory_description *sdesc)) +{ + return lispdesc_block_size_1 (obj, sdesc->size, sdesc->description); +} DECLARE_INLINE_HEADER ( EMACS_INT @@ -1579,7 +1657,7 @@ EMACS_INT variant = lispdesc_indirect_count (desc1->data1, desc, data); desc1 = - lispdesc_indirect_description (data, desc1->data2)->description; + lispdesc_indirect_description (data, desc1->data2.descr)->description; for (count = 0; desc1[count].type != XD_END; count++) { diff --text -u 'xemacs-21.5.18/src/lstream.c' 'xemacs-21.5.19/src/lstream.c' Index: ./src/lstream.c --- ./src/lstream.c Tue Sep 21 04:19:50 2004 +++ ./src/lstream.c Fri Feb 4 01:14:07 2005 @@ -134,10 +134,10 @@ static const struct memory_description lstream_description[] = { - { XD_STRUCT_PTR, offsetof (Lstream, imp), 1, - &lstream_implementation_description }, - { XD_STRUCT_ARRAY, offsetof (Lstream, data), 1, - lstream_extra_description_map }, + { XD_BLOCK_PTR, offsetof (Lstream, imp), 1, + { &lstream_implementation_description } }, + { XD_BLOCK_ARRAY, offsetof (Lstream, data), 1, + { lstream_extra_description_map } }, { XD_END } }; @@ -300,7 +300,7 @@ } } - abort (); + ABORT (); } #define Lstream_internal_error(reason, lstr) \ @@ -371,7 +371,7 @@ EWOULDBLOCK error. */ break; else if (num_written > size) - abort (); + ABORT (); else if (num_written > 0) { data += num_written; @@ -385,7 +385,7 @@ } } - if (lstr->imp->flusher) + if (!error_occurred && lstr->imp->flusher) error_occurred = (lstr->imp->flusher) (lstr) < 0; if (data == orig_data && error_occurred) @@ -1637,7 +1637,7 @@ static Lisp_Object make_lisp_buffer_stream_1 (struct buffer *buf, Charbpos start, Charbpos end, - int flags, const Char_ASCII *mode) + int flags, const Ascbyte *mode) { Lstream *lstr; struct lisp_buffer_stream *str; @@ -1646,7 +1646,7 @@ /* Make sure the luser didn't pass "w" in. */ if (!strcmp (mode, "w")) - abort (); + ABORT (); if (flags & LSTR_IGNORE_ACCESSIBLE) { @@ -1867,6 +1867,4 @@ vars_of_lstream (void) { INIT_LRECORD_IMPLEMENTATION (lstream); - - reinit_vars_of_lstream (); } diff --text -u 'xemacs-21.5.18/src/m/7300.h' 'xemacs-21.5.19/src/m/7300.h' Index: ./src/m/7300.h --- ./src/m/7300.h Mon May 14 13:52:27 2001 +++ ./src/m/7300.h Fri Nov 5 08:07:51 2004 @@ -51,13 +51,9 @@ #ifdef __GNUC__ -#define HAVE_ALLOCA - #else #define SWITCH_ENUM_BUG -#define C_ALLOCA -#define STACK_DIRECTION -1 #endif diff --text -u 'xemacs-21.5.18/src/m/acorn.h' 'xemacs-21.5.19/src/m/acorn.h' Index: ./src/m/acorn.h --- ./src/m/acorn.h Sat Mar 1 16:25:39 2003 +++ ./src/m/acorn.h Fri Nov 5 08:07:51 2004 @@ -63,26 +63,12 @@ #define ADJUST_EXEC_HEADER {hdr.a_magic &= ~MF_SQUEEZED;} -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - #ifdef __GNUC__ -/* Use builtin alloca. Also be sure that no other ones are tried out. */ -#define alloca __builtin_alloca -#define HAVE_ALLOCA - /* Keep gcc/RISCiX happy - it uses __gccmain where other versions of gcc use __main, because of a library routine name clash. */ #define __main __gccmain -#else -#define C_ALLOCA -#undef HAVE_ALLOCA #endif /* __GNUC__ */ /* Define NO_REMAP if memory segmentation makes it not work well @@ -124,9 +110,6 @@ #undef SYSTEM_MALLOC -/* For the portable alloca */ -#define STACK_DIRECTION -1 - #ifdef NO_REMAP /* CRT0_O is defined in s/riscix1-1.h or s/riscix1-2.h, as appropriate. */ #define START_FILES "pre-crt0.o CRT0_O" diff --text -u 'xemacs-21.5.18/src/m/alliant-2800.h' 'xemacs-21.5.19/src/m/alliant-2800.h' Index: ./src/m/alliant-2800.h --- ./src/m/alliant-2800.h Sat Mar 1 16:25:39 2003 +++ ./src/m/alliant-2800.h Fri Nov 5 08:07:51 2004 @@ -53,16 +53,6 @@ #define UNEXEC "unexfx2800.o" #define LIBS_MACHINE "-lalliant" -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#undef C_ALLOCA -#define HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/alliant.h' 'xemacs-21.5.19/src/m/alliant.h' Index: ./src/m/alliant.h --- ./src/m/alliant.h Sat Mar 1 16:25:39 2003 +++ ./src/m/alliant.h Fri Nov 5 08:07:51 2004 @@ -39,21 +39,6 @@ #undef LOAD_AVE_TYPE #undef LOAD_AVE_CVT -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#undef C_ALLOCA -#define HAVE_ALLOCA - -#ifdef ALLIANT_1 -#define C_ALLOCA -#undef HAVE_ALLOCA -#endif /* ALLIANT_1 */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/altos.h' 'xemacs-21.5.19/src/m/altos.h' Index: ./src/m/altos.h --- ./src/m/altos.h Sat Mar 1 16:25:39 2003 +++ ./src/m/altos.h Fri Nov 5 08:07:51 2004 @@ -26,18 +26,9 @@ #define LIB_STANDARD "-lc" -#ifdef __GNUC__ -#define alloca __builtin_alloca -#define HAVE_ALLOCA -#else -#define C_ALLOCA /* we have -lPW and alloca but it's broken! - <vsedev!ron> */ -#endif - #define SWITCH_ENUM_BUG #define NO_REMAP -#define STACK_DIRECTION -1 #undef TERMINFO diff --text -u 'xemacs-21.5.18/src/m/amdahl.h' 'xemacs-21.5.19/src/m/amdahl.h' Index: ./src/m/amdahl.h --- ./src/m/amdahl.h Sat Mar 1 16:25:39 2003 +++ ./src/m/amdahl.h Fri Nov 5 08:07:52 2004 @@ -49,20 +49,6 @@ /*#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0)*/ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -/*#define HAVE_ALLOCA */ - -#ifdef HAVE_ALLOCA -#define LIB_STANDARD "-lPW -lc" -#endif - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -105,9 +91,6 @@ #define SEGSIZ 0x10000 /* Should this not be defined elsewhere ? */ #define SEGMENT_MASK (SEGSIZ - 1) -/* Tell alloca.c which direction stack grows. */ -#define STACK_DIRECTION -1 - /* Compensate for error in signal.h. */ #if NSIG==19 #undef NSIG diff --text -u 'xemacs-21.5.18/src/m/apollo.h' 'xemacs-21.5.19/src/m/apollo.h' Index: ./src/m/apollo.h --- ./src/m/apollo.h Fri Apr 13 03:24:33 2001 +++ ./src/m/apollo.h Fri Nov 5 08:07:52 2004 @@ -39,10 +39,6 @@ /* Do not define LOAD_AVE_TYPE or LOAD_AVE_CVT since there is no /dev/kmem */ -/* Define HAVE_ALLOCA because we use the system's version of alloca. */ - -#define HAVE_ALLOCA - /* Prevent -lg from being used for debugging. Not needed. */ #define LIBS_DEBUG diff --text -u 'xemacs-21.5.18/src/m/att3b.h' 'xemacs-21.5.19/src/m/att3b.h' Index: ./src/m/att3b.h --- ./src/m/att3b.h Sat Mar 1 16:25:39 2003 +++ ./src/m/att3b.h Fri Nov 5 08:07:52 2004 @@ -37,17 +37,9 @@ /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - /* SysV has alloca in the PW library */ #define LIB_STANDARD "-lPW -lc" -#define HAVE_ALLOCA /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section @@ -98,9 +90,6 @@ #define TEXT_START 0 -/* For alloca.c (not actually used, since HAVE_ALLOCA) */ -#define STACK_DIRECTION 1 - /* (short) negative-int doesn't sign-extend correctly */ #define SHORT_CAST_BUG diff --text -u 'xemacs-21.5.18/src/m/aviion.h' 'xemacs-21.5.19/src/m/aviion.h' Index: ./src/m/aviion.h --- ./src/m/aviion.h Sat Mar 1 16:25:39 2003 +++ ./src/m/aviion.h Fri Nov 5 08:07:53 2004 @@ -37,17 +37,6 @@ /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -#define HAVE_ALLOCA -#define alloca(x) __builtin_alloca(x) - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/celerity.h' 'xemacs-21.5.19/src/m/celerity.h' Index: ./src/m/celerity.h --- ./src/m/celerity.h Fri Apr 13 03:24:33 2001 +++ ./src/m/celerity.h Fri Nov 5 08:07:53 2004 @@ -39,9 +39,5 @@ #define LD_SWITCH_MACHINE "-k100000" -/* alloca is provided by the system. */ - -#define HAVE_ALLOCA - /* (short) negative-int doesn't sign-extend correctly */ #define SHORT_CAST_BUG diff --text -u 'xemacs-21.5.18/src/m/clipper.h' 'xemacs-21.5.19/src/m/clipper.h' Index: ./src/m/clipper.h --- ./src/m/clipper.h Sat Mar 1 16:25:39 2003 +++ ./src/m/clipper.h Fri Nov 5 08:07:53 2004 @@ -40,15 +40,6 @@ #define LOAD_AVE_CVT(x) ((int) ((x) * 100.0)) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/cnvrgnt.h' 'xemacs-21.5.19/src/m/cnvrgnt.h' Index: ./src/m/cnvrgnt.h --- ./src/m/cnvrgnt.h Sat Mar 1 16:25:39 2003 +++ ./src/m/cnvrgnt.h Fri Nov 5 08:07:53 2004 @@ -34,16 +34,6 @@ #define LOAD_AVE_CVT(x) ((int) ((x) * 100.0)) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -#undef HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -55,10 +45,6 @@ #define SWITCH_ENUM_BUG -/* grows towards lower addresses. */ - -#define STACK_DIRECTION -1 - /* some errno.h's don't actually allocate the variable itself. Cause crt0.c to define errno. */ diff --text -u 'xemacs-21.5.18/src/m/convex.h' 'xemacs-21.5.19/src/m/convex.h' Index: ./src/m/convex.h --- ./src/m/convex.h Sat Mar 1 16:25:39 2003 +++ ./src/m/convex.h Fri Nov 5 08:07:53 2004 @@ -50,16 +50,6 @@ #define LOAD_AVE_CVT(x) (int) ((x) * 100.0) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -#define HAVE_ALLOCA - /* Must use the system's termcap. It does special things. */ #define LIBS_TERMCAP "-ltermcap" diff --text -u 'xemacs-21.5.18/src/m/cydra5.h' 'xemacs-21.5.19/src/m/cydra5.h' Index: ./src/m/cydra5.h --- ./src/m/cydra5.h Sat Mar 1 16:25:39 2003 +++ ./src/m/cydra5.h Fri Nov 5 08:07:54 2004 @@ -37,16 +37,6 @@ #define LOAD_AVE_CVT(x) x -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -#undef HAVE_ALLOCA - #define DATA_START 0x20000000 /* Define NO_REMAP if memory segmentation makes it not work well @@ -57,9 +47,6 @@ #define NO_REMAP #define LIBS_MACHINE "-lsocket -lnsl" -/* Stack grows downward in memory. */ -#define STACK_DIRECTION -1 - /* The data section in a coff file must be aligned in the file. */ #define DATA_SECTION_ALIGNMENT 0xFFF diff --text -u 'xemacs-21.5.18/src/m/delta.h' 'xemacs-21.5.19/src/m/delta.h' Index: ./src/m/delta.h --- ./src/m/delta.h Sat Mar 1 16:25:39 2003 +++ ./src/m/delta.h Fri Nov 5 08:07:54 2004 @@ -42,16 +42,6 @@ /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -/* #define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -86,11 +76,6 @@ # define LIBX11_SYSTEM "-lnls -lnsl_s" #endif /* HAVE_X_WINDOWS */ -#ifdef __GNUC__ - /* Use builtin alloca. Also be sure that no other ones are tried out. */ -# define alloca __builtin_alloca -# define HAVE_ALLOCA - /* We are assuming here that the `true' GNU gcc has not been installed, and we are using the gnucc provided by Motorola. No support exists for compiling with GNU gcc, as I do not have it on diff --text -u 'xemacs-21.5.18/src/m/delta88k.h' 'xemacs-21.5.19/src/m/delta88k.h' Index: ./src/m/delta88k.h --- ./src/m/delta88k.h Sat Mar 1 16:25:39 2003 +++ ./src/m/delta88k.h Fri Nov 5 08:07:54 2004 @@ -51,25 +51,6 @@ #define NO_REMAP -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* BEM: Distributed asm alloca doesn't work. Don't know about libPW.a. - C ALLOCA is safe and fast enough for now. */ - -#ifdef __GNUC__ -#define HAVE_ALLOCA /* ... and be sure that no other ones are tried out. */ -#undef C_ALLOCA -#else /* not __GNUC__ */ -#undef HAVE_ALLOCA -#define C_ALLOCA /* Use the alloca() supplied in alloca.c. */ -#define STACK_DIRECTION -1 /* The stack grows towards lower addresses. */ -#endif /* __GNUC__ */ - /* * we have the wrong name for networking libs */ diff --text -u 'xemacs-21.5.18/src/m/dpx2.h' 'xemacs-21.5.19/src/m/dpx2.h' Index: ./src/m/dpx2.h --- ./src/m/dpx2.h Sat Mar 1 16:25:39 2003 +++ ./src/m/dpx2.h Fri Nov 5 08:07:54 2004 @@ -49,16 +49,6 @@ #define FSCALE 1000.0 #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -/* #define HAVE_ALLOCA /**/ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -133,12 +123,6 @@ #define TEXT_START 0 -/* - * Define the direction of stack growth. - */ - -#define STACK_DIRECTION -1 - /* on bos2.00.45 there is a bug that makes the F_SETOWN fcntl() call enters in an infinite loop. Avoid calling it */ #define F_SETOWN_BUG diff --text -u 'xemacs-21.5.18/src/m/elxsi.h' 'xemacs-21.5.19/src/m/elxsi.h' Index: ./src/m/elxsi.h --- ./src/m/elxsi.h Sat Mar 1 16:25:39 2003 +++ ./src/m/elxsi.h Fri Nov 5 08:07:54 2004 @@ -50,16 +50,6 @@ #define LOAD_AVE_CVT(x) (int) ((x) * 100.0) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -/*#define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/ews4800r.h' 'xemacs-21.5.19/src/m/ews4800r.h' Index: ./src/m/ews4800r.h --- ./src/m/ews4800r.h Sat Mar 1 16:25:39 2003 +++ ./src/m/ews4800r.h Fri Nov 5 08:07:55 2004 @@ -36,19 +36,6 @@ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / 256.0) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#ifdef __GNUC__ -#define HAVE_ALLOCA -#else -#define C_ALLOCA -#endif - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/gould.h' 'xemacs-21.5.19/src/m/gould.h' Index: ./src/m/gould.h --- ./src/m/gould.h Sat Mar 1 16:25:39 2003 +++ ./src/m/gould.h Fri Nov 5 08:07:55 2004 @@ -65,16 +65,6 @@ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -#define STACK_DIRECTION -1 /* grows towards lower addresses on Gould UTX/32 */ - /* No need to extend the user stack. */ /* If this is a 2.1 system, COFF will be predefined by cpp. If it's */ diff --text -u 'xemacs-21.5.18/src/m/hp300bsd.h' 'xemacs-21.5.19/src/m/hp300bsd.h' Index: ./src/m/hp300bsd.h --- ./src/m/hp300bsd.h Fri Apr 13 03:24:34 2001 +++ ./src/m/hp300bsd.h Fri Nov 5 08:07:55 2004 @@ -34,7 +34,5 @@ #define CRT0_DUMMIES one_dummy, -#define HAVE_ALLOCA - #define LOAD_AVE_TYPE long #define LOAD_AVE_CVT(x) ((int) (((double) (x)) / 2048.0 * 100.0)) diff --text -u 'xemacs-21.5.18/src/m/hp800.h' 'xemacs-21.5.19/src/m/hp800.h' Index: ./src/m/hp800.h --- ./src/m/hp800.h Sat Mar 1 16:25:39 2003 +++ ./src/m/hp800.h Fri Nov 5 08:07:55 2004 @@ -50,21 +50,6 @@ #define LOAD_AVE_CVT(x) ((int) (x * 100.0)) - -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* lemacs change: define HAVE_ALLOCA if gcc is being used */ -#ifdef __GNUC__ -#define HAVE_ALLOCA -#else -#define C_ALLOCA -#endif - /* the data segment on this machine always starts at address 0x40000000. */ #ifdef DATA_START @@ -77,8 +62,6 @@ #define DATA_START 0x40000000 #define TEXT_START 0x00000000 -#define STACK_DIRECTION 1 - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/hp9000s300.h' 'xemacs-21.5.19/src/m/hp9000s300.h' Index: ./src/m/hp9000s300.h --- ./src/m/hp9000s300.h Sat Mar 1 16:25:39 2003 +++ ./src/m/hp9000s300.h Fri Nov 5 08:07:56 2004 @@ -64,8 +64,6 @@ #define CRT0_DUMMIES bogus_a6, -#define HAVE_ALLOCA - #ifndef __GNUC__ #define LIBS_DEBUG /* don't have -lg that works */ #define C_DEBUG_SWITCH /* don't support -g */ @@ -94,10 +92,6 @@ #define LOAD_AVE_CVT(x) ((int) ((x) * 100.0)) -#ifdef __GNUC__ -#define HAVE_ALLOCA -#endif - /* This library is needed with -g, on the 200/300 only. */ #if !defined(__GNUC__) || defined(__HPUX_ASM__) diff --text -u 'xemacs-21.5.18/src/m/i860.h' 'xemacs-21.5.19/src/m/i860.h' Index: ./src/m/i860.h --- ./src/m/i860.h Sat Mar 1 16:25:39 2003 +++ ./src/m/i860.h Fri Nov 5 08:07:56 2004 @@ -39,16 +39,6 @@ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -/* #define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/ibmps2-aix.h' 'xemacs-21.5.19/src/m/ibmps2-aix.h' Index: ./src/m/ibmps2-aix.h --- ./src/m/ibmps2-aix.h Sat Mar 1 16:25:39 2003 +++ ./src/m/ibmps2-aix.h Fri Nov 5 08:07:56 2004 @@ -99,15 +99,7 @@ /* Here override various assumptions in ymakefile */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - #ifdef __GNUC__ -#define HAVE_ALLOCA #define alloca(n) __builtin_alloca(n) #if __GNUC__ < 2 #define LIB_STANDARD "/usr/local/lib/gcc-gnulib -lbsd -lrts -lc " @@ -116,8 +108,6 @@ /* tranle says that -fstrength-reduce does not help. */ #define C_DEBUG_SWITCH #else -#define C_ALLOCA -#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */ #define LIBS_MACHINE "-lbsd -lrts" #endif diff --text -u 'xemacs-21.5.18/src/m/ibmrs6000.h' 'xemacs-21.5.19/src/m/ibmrs6000.h' Index: ./src/m/ibmrs6000.h --- ./src/m/ibmrs6000.h Sat Mar 1 16:25:39 2003 +++ ./src/m/ibmrs6000.h Fri Nov 5 08:07:56 2004 @@ -62,19 +62,6 @@ #undef ADDR_CORRECT #define ADDR_CORRECT(x) ((int)(x)) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* Note: aix3-2.h defines HAVE_ALLOCA; aix3-1.h doesn't. */ -#ifndef HAVE_ALLOCA -#define C_ALLOCA -#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */ -#endif - /* Specify the font for X to use. This used to be Rom14.500; that's nice on the X server shipped with the RS/6000, but it's not available on other servers. */ diff --text -u 'xemacs-21.5.18/src/m/ibmrt-aix.h' 'xemacs-21.5.19/src/m/ibmrt-aix.h' Index: ./src/m/ibmrt-aix.h --- ./src/m/ibmrt-aix.h Sat Mar 1 16:25:39 2003 +++ ./src/m/ibmrt-aix.h Fri Nov 5 08:07:56 2004 @@ -56,16 +56,6 @@ #define A_TEXT_SEEK(HDR) (N_TXTOFF (hdr) + sizeof (hdr)) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -#define STACK_DIRECTION -1 /* tell alloca.c which way it grows */ - /* AIX has PTYs, so define here, along with macros needed to make them work. */ #define PTY_ITERATION for (i=0; i<256; i++) diff --text -u 'xemacs-21.5.18/src/m/ibmrt.h' 'xemacs-21.5.19/src/m/ibmrt.h' Index: ./src/m/ibmrt.h --- ./src/m/ibmrt.h Sat Mar 1 16:25:39 2003 +++ ./src/m/ibmrt.h Fri Nov 5 08:07:56 2004 @@ -43,14 +43,6 @@ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define HAVE_ALLOCA #define DATA_START 0x10000000 diff --text -u 'xemacs-21.5.18/src/m/intel386.h' 'xemacs-21.5.19/src/m/intel386.h' Index: ./src/m/intel386.h --- ./src/m/intel386.h Sat Mar 1 16:25:39 2003 +++ ./src/m/intel386.h Fri Nov 5 08:07:56 2004 @@ -115,8 +115,6 @@ #define NO_REMAP -#define STACK_DIRECTION -1 - /* Since cannot purify, use standard Xenix 386 startup code. */ #define START_FILES "/lib/386/Sseg.o pre-crt0.o /lib/386/Scrt0.o" @@ -144,11 +142,3 @@ #define SEGMENT_MASK ((SEGMENT_SIZE)-1) #endif - -#ifdef __GNUC__ -/* GCC's alloca() is semi-broken. See lisp.h. - - This brokenness has been confirmed under both Linux and NetBSD. - It may also exist on non-Intel architectures. */ -#define BROKEN_ALLOCA_IN_FUNCTION_CALLS -#endif diff --text -u 'xemacs-21.5.18/src/m/iris4d.h' 'xemacs-21.5.19/src/m/iris4d.h' Index: ./src/m/iris4d.h --- ./src/m/iris4d.h Sat Mar 1 16:25:39 2003 +++ ./src/m/iris4d.h Fri Nov 5 08:07:57 2004 @@ -49,16 +49,6 @@ #define KERNEL_FILE "/unix" #endif -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ /* Sjoerd.Mullender@cwi.nl says no need. */ -/* #define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -109,8 +99,3 @@ #undef FIRST_PTY_LETTER #define FIRST_PTY_LETTER 'q' - -/* Define STACK_DIRECTION for alloca.c */ - -#undef STACK_DIRECTION -#define STACK_DIRECTION -1 diff --text -u 'xemacs-21.5.18/src/m/iris5d.h' 'xemacs-21.5.19/src/m/iris5d.h' Index: ./src/m/iris5d.h --- ./src/m/iris5d.h Sat Mar 1 16:25:39 2003 +++ ./src/m/iris5d.h Fri Nov 5 08:07:57 2004 @@ -50,16 +50,6 @@ #undef KERNEL_FILE #define KERNEL_FILE "/unix" -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -/* #define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -112,9 +102,6 @@ #undef FIRST_PTY_LETTER #define FIRST_PTY_LETTER 'q' -/* Define STACK_DIRECTION for alloca.c */ - -#define STACK_DIRECTION -1 #ifndef __GNUC__ /* Turn off some "helpful" error checks for type mismatches diff --text -u 'xemacs-21.5.18/src/m/iris6d.h' 'xemacs-21.5.19/src/m/iris6d.h' Index: ./src/m/iris6d.h --- ./src/m/iris6d.h Sat Mar 1 16:25:39 2003 +++ ./src/m/iris6d.h Fri Nov 5 08:07:57 2004 @@ -49,16 +49,6 @@ #define KERNEL_FILE "/unix" #endif -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ /* Sjoerd.Mullender@cwi.nl says no need. */ -/* #define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -109,8 +99,3 @@ #undef FIRST_PTY_LETTER #define FIRST_PTY_LETTER 'q' - -/* Define STACK_DIRECTION for alloca.c */ - -#undef STACK_DIRECTION -#define STACK_DIRECTION -1 diff --text -u 'xemacs-21.5.18/src/m/irist.h' 'xemacs-21.5.19/src/m/irist.h' Index: ./src/m/irist.h --- ./src/m/irist.h Sat Mar 1 16:25:39 2003 +++ ./src/m/irist.h Fri Nov 5 08:07:58 2004 @@ -76,16 +76,6 @@ #define FSCALE 1.0 #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -#define HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/isi-ov.h' 'xemacs-21.5.19/src/m/isi-ov.h' Index: ./src/m/isi-ov.h --- ./src/m/isi-ov.h Fri Apr 13 03:24:35 2001 +++ ./src/m/isi-ov.h Fri Nov 5 08:07:58 2004 @@ -71,7 +71,6 @@ /* A few changes for the newer systems. */ #ifdef BSD4_3 -#define HAVE_ALLOCA /* The following line affects crt0.c. */ #undef m68k diff --text -u 'xemacs-21.5.18/src/m/luna88k.h' 'xemacs-21.5.19/src/m/luna88k.h' Index: ./src/m/luna88k.h --- ./src/m/luna88k.h Fri Apr 13 03:24:36 2001 +++ ./src/m/luna88k.h Fri Nov 5 08:07:58 2004 @@ -55,12 +55,6 @@ #define A_TEXT_OFFSET(HDR) sizeof(HDR) #define A_TEXT_SEEK(HDR) sizeof(HDR) -/* Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - At least, gcc for 88000 supports inline alloca. */ - -#define HAVE_ALLOCA - /* Memory management mechanism is different on Mach, so emacs-supplied malloc.c does not work. */ diff --text -u 'xemacs-21.5.18/src/m/m68k.h' 'xemacs-21.5.19/src/m/m68k.h' Index: ./src/m/m68k.h --- ./src/m/m68k.h Sat Mar 1 16:25:39 2003 +++ ./src/m/m68k.h Fri Nov 5 08:07:58 2004 @@ -33,9 +33,4 @@ #define TEXT_START 0 #endif -/* If compiling with GCC, let GCC implement alloca. */ -#if defined(__GNUC__) && !defined(alloca) -#define alloca(n) __builtin_alloca(n) -#define HAVE_ALLOCA -#endif #define ASSERT_VALID_POINTER(pnt) (assert ((((int) pnt) & 1) == 0)) diff --text -u 'xemacs-21.5.18/src/m/masscomp.h' 'xemacs-21.5.19/src/m/masscomp.h' Index: ./src/m/masscomp.h --- ./src/m/masscomp.h Sat Mar 1 16:25:39 2003 +++ ./src/m/masscomp.h Fri Nov 5 08:07:58 2004 @@ -39,25 +39,6 @@ #define LOAD_AVE_CVT(x) ((int) ((x) * 100.0)) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* On return from a subroutine, the 68020 compiler restores old contents of - register variables relative to sp, so alloca() screws up such routines. - The following definitions should work on all Masscomps. On the MC-5500 - (a 68000) one can #undef C_ALLOCA and #define HAVE_ALLOCA. */ -#ifdef mc500 -#undef C_ALLOCA -#define HAVE_ALLOCA -#else -#define C_ALLOCA -#undef HAVE_ALLOCA -#endif - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/mg1.h' 'xemacs-21.5.19/src/m/mg1.h' Index: ./src/m/mg1.h --- ./src/m/mg1.h Sat Mar 1 16:25:39 2003 +++ ./src/m/mg1.h Fri Nov 5 08:07:58 2004 @@ -50,16 +50,6 @@ #define FSCALE 1000.0 #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ -/* hmmmm... again not sure. so copied sequent.h again! */ -#undef C_ALLOCA -#undef HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/mips-nec.h' 'xemacs-21.5.19/src/m/mips-nec.h' Index: ./src/m/mips-nec.h --- ./src/m/mips-nec.h Sat Mar 1 16:25:39 2003 +++ ./src/m/mips-nec.h Fri Nov 5 08:07:59 2004 @@ -57,19 +57,6 @@ #undef KERNEL_FILE #define KERNEL_FILE "/unix" -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#ifdef __GNUC__ -#define HAVE_ALLOCA -#else -#define C_ALLOCA -#endif - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/mips-siemens.h' 'xemacs-21.5.19/src/m/mips-siemens.h' Index: ./src/m/mips-siemens.h --- ./src/m/mips-siemens.h Sat Mar 1 16:25:39 2003 +++ ./src/m/mips-siemens.h Fri Nov 5 08:07:59 2004 @@ -57,19 +57,6 @@ #undef KERNEL_FILE #define KERNEL_FILE "/unix" -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#ifdef __GNUC__ -#define HAVE_ALLOCA -#else -#define C_ALLOCA -#endif - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/mips.h' 'xemacs-21.5.19/src/m/mips.h' Index: ./src/m/mips.h --- ./src/m/mips.h Sat Mar 1 16:25:39 2003 +++ ./src/m/mips.h Fri Nov 5 08:07:59 2004 @@ -52,19 +52,6 @@ #define KERNEL_FILE "/unix" #endif /* ! linux */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#ifdef __GNUC__ -#define HAVE_ALLOCA -#else -#define C_ALLOCA -#endif - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/news.h' 'xemacs-21.5.19/src/m/news.h' Index: ./src/m/news.h --- ./src/m/news.h Sun Jun 22 05:04:29 1997 +++ ./src/m/news.h Fri Nov 5 08:07:59 2004 @@ -40,10 +40,6 @@ #define CRT0_DUMMIES one_dummy, #endif -/* The News machine has alloca. */ - -#define HAVE_ALLOCA - /* Data type of load average, as read out of kmem. */ #define LOAD_AVE_TYPE double diff --text -u 'xemacs-21.5.18/src/m/nh3000.h' 'xemacs-21.5.19/src/m/nh3000.h' Index: ./src/m/nh3000.h --- ./src/m/nh3000.h Sat Mar 1 16:25:39 2003 +++ ./src/m/nh3000.h Fri Nov 5 08:07:59 2004 @@ -47,16 +47,6 @@ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -#define HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/nh4000.h' 'xemacs-21.5.19/src/m/nh4000.h' Index: ./src/m/nh4000.h --- ./src/m/nh4000.h Sat Mar 1 16:25:39 2003 +++ ./src/m/nh4000.h Fri Nov 5 08:07:59 2004 @@ -46,16 +46,6 @@ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -#define HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/ns32000.h' 'xemacs-21.5.19/src/m/ns32000.h' Index: ./src/m/ns32000.h --- ./src/m/ns32000.h Sat Mar 1 16:25:39 2003 +++ ./src/m/ns32000.h Fri Nov 5 08:08:00 2004 @@ -37,18 +37,6 @@ /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -#ifdef __NetBSD__ -#define HAVE_ALLOCA -#endif - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -58,8 +46,6 @@ #define TEXT_START 0 -#define STACK_DIRECTION -1 - #ifndef __NetBSD__ #define EXEC_MAGIC 0410 diff --text -u 'xemacs-21.5.18/src/m/orion105.h' 'xemacs-21.5.19/src/m/orion105.h' Index: ./src/m/orion105.h --- ./src/m/orion105.h Fri Apr 13 03:24:37 2001 +++ ./src/m/orion105.h Fri Nov 5 08:08:00 2004 @@ -38,8 +38,6 @@ #endif #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -#define HAVE_ALLOCA - /* Here is where programs actually start running */ #define TEXT_START 0x8000 #define LD_TEXT_START_ADDR 8000 diff --text -u 'xemacs-21.5.18/src/m/pfa50.h' 'xemacs-21.5.19/src/m/pfa50.h' Index: ./src/m/pfa50.h --- ./src/m/pfa50.h Mon May 14 13:52:28 2001 +++ ./src/m/pfa50.h Fri Nov 5 08:08:00 2004 @@ -50,7 +50,6 @@ /* SX/A has alloca in the PW library. */ #define LIB_STANDARD "-lPW -lc" -#define HAVE_ALLOCA /* SX/A uses terminfo and lib/curses */ diff --text -u 'xemacs-21.5.18/src/m/plexus.h' 'xemacs-21.5.19/src/m/plexus.h' Index: ./src/m/plexus.h --- ./src/m/plexus.h Sat Mar 1 16:25:39 2003 +++ ./src/m/plexus.h Fri Nov 5 08:08:00 2004 @@ -39,16 +39,6 @@ #undef LOAD_AVE_CVT -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#undef C_ALLOCA -#define HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/pmax.h' 'xemacs-21.5.19/src/m/pmax.h' Index: ./src/m/pmax.h --- ./src/m/pmax.h Fri Apr 13 03:24:37 2001 +++ ./src/m/pmax.h Fri Nov 5 08:08:00 2004 @@ -48,11 +48,6 @@ and it causes hanging in read_process_output. */ #define BROKEN_O_NONBLOCK -#if defined (OSF1) || defined (MACH) -#undef C_ALLOCA -#define HAVE_ALLOCA -#endif - /* mcc@timessqr.gc.cuny.edu says this makes Emacs work with DECnet. */ #ifdef HAVE_LIBDNET #define LIBS_MACHINE "-ldnet" diff --text -u 'xemacs-21.5.18/src/m/powerpc.h' 'xemacs-21.5.19/src/m/powerpc.h' Index: ./src/m/powerpc.h --- ./src/m/powerpc.h Sat Mar 1 16:25:39 2003 +++ ./src/m/powerpc.h Fri Nov 5 08:08:00 2004 @@ -68,15 +68,6 @@ #undef ADDR_CORRECT #define ADDR_CORRECT(x) ((int)(x)) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define HAVE_ALLOCA - /* Specify the font for X to use. This used to be Rom14.500; that's nice on the X server shipped with the RS/6000, but it's not available on other servers. */ @@ -86,7 +77,6 @@ /* #undef START_FILES */ /* #define HAVE_SYSVIPC */ -/* #define HAVE_GETWD */ /* Don't try to include sioctl.h or ptem.h. */ #undef NEED_SIOCTL diff --text -u 'xemacs-21.5.18/src/m/pyrmips.h' 'xemacs-21.5.19/src/m/pyrmips.h' Index: ./src/m/pyrmips.h --- ./src/m/pyrmips.h Thu Dec 19 07:44:11 1996 +++ ./src/m/pyrmips.h Fri Nov 5 08:08:01 2004 @@ -6,6 +6,5 @@ #include "m-pyramid.h" #define SYSTEM_MALLOC -#define HAVE_ALLOCA #define CANNOT_DUMP diff --text -u 'xemacs-21.5.18/src/m/sequent-ptx.h' 'xemacs-21.5.19/src/m/sequent-ptx.h' Index: ./src/m/sequent-ptx.h --- ./src/m/sequent-ptx.h Sat Mar 1 16:25:39 2003 +++ ./src/m/sequent-ptx.h Fri Nov 5 08:08:01 2004 @@ -49,18 +49,6 @@ #define FSCALE 1000.0 #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#ifndef __GNUC__ -#define C_ALLOCA -#undef HAVE_ALLOCA -#endif - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/sequent.h' 'xemacs-21.5.19/src/m/sequent.h' Index: ./src/m/sequent.h --- ./src/m/sequent.h Sat Mar 1 16:25:39 2003 +++ ./src/m/sequent.h Fri Nov 5 08:08:01 2004 @@ -58,16 +58,6 @@ #define FSCALE 1000.0 #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -#define HAVE_ALLOCA - /* Name of file the to look in for the kernel symbol table (for load average) */ diff --text -u 'xemacs-21.5.18/src/m/sgi-challenge.h' 'xemacs-21.5.19/src/m/sgi-challenge.h' Index: ./src/m/sgi-challenge.h --- ./src/m/sgi-challenge.h Sat Mar 1 16:25:39 2003 +++ ./src/m/sgi-challenge.h Fri Nov 5 08:08:01 2004 @@ -62,16 +62,6 @@ #undef KERNEL_FILE #define KERNEL_FILE "/unix" -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -/* #define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp @@ -123,10 +113,6 @@ #undef FIRST_PTY_LETTER #define FIRST_PTY_LETTER 'q' -/* Define STACK_DIRECTION for alloca.c */ - -#define STACK_DIRECTION -1 - /* By Tor Arntsen <tor@spacetec.no> for XEmacs. */ #ifdef USE_GCC #define C_SWITCH_MACHINE "-D_BSD_TYPES -mcpu=r4000 -mips2" diff --text -u 'xemacs-21.5.18/src/m/symmetry.h' 'xemacs-21.5.19/src/m/symmetry.h' Index: ./src/m/symmetry.h --- ./src/m/symmetry.h Thu Dec 19 07:44:12 1996 +++ ./src/m/symmetry.h Fri Nov 5 08:08:02 2004 @@ -46,16 +46,6 @@ #define FSCALE 1000.0 #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -/*#define HAVE_ALLOCA*/ - /* Name of file the to look in for the kernel symbol table (for load average) */ diff --text -u 'xemacs-21.5.18/src/m/tad68k.h' 'xemacs-21.5.19/src/m/tad68k.h' Index: ./src/m/tad68k.h --- ./src/m/tad68k.h Sat Mar 1 16:25:40 2003 +++ ./src/m/tad68k.h Fri Nov 5 08:08:02 2004 @@ -31,17 +31,9 @@ /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - /* SysV has alloca in the PW library */ #define LIB_STANDARD "-lPW -lc" -#define HAVE_ALLOCA /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section diff --text -u 'xemacs-21.5.18/src/m/tahoe.h' 'xemacs-21.5.19/src/m/tahoe.h' Index: ./src/m/tahoe.h --- ./src/m/tahoe.h Fri Apr 13 03:24:40 2001 +++ ./src/m/tahoe.h Fri Nov 5 08:08:03 2004 @@ -54,7 +54,3 @@ /* This triggers some stuff to avoid a compiler bug */ #define TAHOE_REGISTER_BUG - -/* System provides alloca. */ - -#define HAVE_ALLOCA diff --text -u 'xemacs-21.5.18/src/m/targon31.h' 'xemacs-21.5.19/src/m/targon31.h' Index: ./src/m/targon31.h --- ./src/m/targon31.h Sat Mar 1 16:25:40 2003 +++ ./src/m/targon31.h Fri Nov 5 08:08:03 2004 @@ -40,16 +40,6 @@ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -/* #define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/tekxd88.h' 'xemacs-21.5.19/src/m/tekxd88.h' Index: ./src/m/tekxd88.h --- ./src/m/tekxd88.h Sat Mar 1 16:25:40 2003 +++ ./src/m/tekxd88.h Fri Nov 5 08:08:03 2004 @@ -41,22 +41,8 @@ code will not be sharable; but that's better than failing completely. */ #define NO_REMAP -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ -#ifdef __GNUC__ -# define alloca __builtin_alloca /* Use the gcc builtin alloca() ... */ -# define HAVE_ALLOCA /* ... and be sure that no other ones are tried out. */ -# undef C_ALLOCA -# define C_OPTIMIZE_SWITCH "-O2" -#else /* not __GNUC__ */ -# undef HAVE_ALLOCA -# define C_ALLOCA /* Use the alloca() supplied in alloca.c. */ -# define STACK_DIRECTION -1 /* The stack grows towards lower addresses. */ -# define C_OPTIMIZE_SWITCH "-O" +#ifndef __GNUC__ +# define C_OPTIMIZE_SWITCH -O #endif /* __GNUC__ */ #undef LIB_X11_LIB /* Don't use shared libraries defined in usg5-3.h */ diff --text -u 'xemacs-21.5.18/src/m/template.h' 'xemacs-21.5.19/src/m/template.h' Index: ./src/m/template.h --- ./src/m/template.h Sat Mar 1 16:25:40 2003 +++ ./src/m/template.h Fri Nov 5 08:08:03 2004 @@ -37,16 +37,6 @@ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -#define HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/tower32.h' 'xemacs-21.5.19/src/m/tower32.h' Index: ./src/m/tower32.h --- ./src/m/tower32.h Sat Mar 1 16:25:40 2003 +++ ./src/m/tower32.h Fri Nov 5 08:08:03 2004 @@ -38,16 +38,6 @@ /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* #define C_ALLOCA */ -#define HAVE_ALLOCA - /* Change some things to avoid bugs in compiler */ #define SWITCH_ENUM_BUG 1 diff --text -u 'xemacs-21.5.18/src/m/tower32v3.h' 'xemacs-21.5.19/src/m/tower32v3.h' Index: ./src/m/tower32v3.h --- ./src/m/tower32v3.h Sat Mar 1 16:25:40 2003 +++ ./src/m/tower32v3.h Fri Nov 5 08:08:03 2004 @@ -38,27 +38,15 @@ /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - #ifdef __GNUC__ -#define HAVE_ALLOCA -#define alloca __builtin_alloca #define C_OPTIMIZE_SWITCH "-O -fstrength-reduce -fomit-frame-pointer" #define LIB_STANDARD "-lc /lib/crtn.o" #else /* This section is correct if you do *not* change src/ymakefile so that CFLAGS includes C_OPTIMIZE_SWITCH rather than C_DEBUG_SWITCH. */ -#define HAVE_ALLOCA -#define "C_DEBUG_SWITCH -g -O0" +#define C_DEBUG_SWITCH "-g -O0" #define LIB_STANDARD "-lc -lPW /lib/crtn.o" /* This section is correct if you do enable C_OPTIMIZE_SWITCH. */ -/* #define C_ALLOCA */ -/* #define STACK_DIRECTION -1 */ /* #define C_OPTIMIZE_SWITCH -O2 */ /* #define LIB_STANDARD -lc /lib/crtn.o */ #endif diff --text -u 'xemacs-21.5.18/src/m/ustation.h' 'xemacs-21.5.19/src/m/ustation.h' Index: ./src/m/ustation.h --- ./src/m/ustation.h Sat Mar 1 16:25:40 2003 +++ ./src/m/ustation.h Fri Nov 5 08:08:03 2004 @@ -40,21 +40,6 @@ #define LOAD_AVE_CVT(x) ((int) ((x) * 100.0)) -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* On return from a subroutine, the 68020 compiler restores old contents of - register variables relative to sp, so alloca() screws up such routines. - The following definitions should work on all Masscomps. On the MC-5500 - (a 68000) one can #undef C_ALLOCA and #define HAVE_ALLOCA. */ - -#define C_ALLOCA -#undef HAVE_ALLOCA - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/vax.h' 'xemacs-21.5.19/src/m/vax.h' Index: ./src/m/vax.h --- ./src/m/vax.h Sun Nov 9 16:08:09 1997 +++ ./src/m/vax.h Fri Nov 5 08:08:04 2004 @@ -81,7 +81,6 @@ #ifdef USG #define LIB_STANDARD "-lPW -lc" -#define HAVE_ALLOCA /* There is some bug in unexec in for usg 5.2 on a vax which nobody who runs such a system has yet tracked down. */ @@ -92,10 +91,6 @@ #define TEXT_START 0 #endif /* USG */ -#ifdef BSD -#define HAVE_ALLOCA -#endif /* BSD */ - #ifdef BSD4_2 #define HAVE_FTIME #endif diff --text -u 'xemacs-21.5.18/src/m/wicat.h' 'xemacs-21.5.19/src/m/wicat.h' Index: ./src/m/wicat.h --- ./src/m/wicat.h Sat Mar 1 16:25:40 2003 +++ ./src/m/wicat.h Fri Nov 5 08:08:04 2004 @@ -43,18 +43,6 @@ #undef LOAD_AVE_CVT -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -/* For the Wicat C compiler version 4.2, this can be removed - and the alloca in alloca.s used. */ -#define C_ALLOCA -#define STACK_DIRECTION -1 /* grows towards lower addresses on WICAT */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp diff --text -u 'xemacs-21.5.18/src/m/xps100.h' 'xemacs-21.5.19/src/m/xps100.h' Index: ./src/m/xps100.h --- ./src/m/xps100.h Sat Mar 1 16:25:40 2003 +++ ./src/m/xps100.h Fri Nov 5 08:08:04 2004 @@ -39,23 +39,12 @@ /* #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE) */ -/* Define C_ALLOCA if this machine does not support a true alloca - and the one written in C should be used instead. - Define HAVE_ALLOCA to say that the system provides a properly - working alloca function and it should be used. - Define neither one if an assembler-language alloca - in the file alloca.s should be used. */ - -#define C_ALLOCA -/* #define HAVE_ALLOCA */ - /* Define NO_REMAP if memory segmentation makes it not work well to change the boundary between the text section and data section when Emacs is dumped. If you define this, the preloaded Lisp code will not be sharable; but that's better than failing completely. */ #define NO_REMAP -#define STACK_DIRECTION -1 #define TERMINFO #define SWITCH_ENUM_BUG #define LIB_STANDARD " -lc" diff --text -u 'xemacs-21.5.18/src/macros.c' 'xemacs-21.5.19/src/macros.c' Index: ./src/macros.c --- ./src/macros.c Fri Jun 21 06:18:37 2002 +++ ./src/macros.c Sat Jan 29 18:16:00 2005 @@ -181,7 +181,7 @@ void pop_kbd_macro_event (Lisp_Object event) { - if (NILP (Vexecuting_macro)) abort (); + if (NILP (Vexecuting_macro)) ABORT (); if (STRINGP (Vexecuting_macro) || VECTORP (Vexecuting_macro)) { @@ -278,7 +278,7 @@ executing_macro_index = 0; con->prefix_arg = Qnil; internal_catch (Qexecute_kbd_macro, call_command_loop, - Qnil, 0, 0); + Qnil, 0, 0, 0); } while (--repeat != 0 && (STRINGP (Vexecuting_macro) || diff --text -u 'xemacs-21.5.18/src/malloc.c' 'xemacs-21.5.19/src/malloc.c' Index: ./src/malloc.c Prereq: 1 --- ./src/malloc.c Wed Jun 16 21:49:26 2004 +++ ./src/malloc.c Tue Jan 25 08:34:03 2005 @@ -525,7 +525,7 @@ #ifdef rcheck botch ("block on free list clobbered"); #else /* not rcheck */ - abort (); + ABORT (); #endif /* not rcheck */ /* Fill in the info, and if range checking, set up the magic numbers */ @@ -569,7 +569,7 @@ #ifndef rcheck if (p -> mh_alloc != ISALLOC) - abort (); + ABORT (); #else /* rcheck */ if (p -> mh_alloc != ISALLOC) diff --text -u 'xemacs-21.5.18/src/marker.c' 'xemacs-21.5.19/src/marker.c' Index: ./src/marker.c --- ./src/marker.c Tue Sep 21 04:19:51 2004 +++ ./src/marker.c Fri Feb 4 01:14:07 2005 @@ -88,18 +88,18 @@ !marker1->buffer)); } -static unsigned long +static Hashcode marker_hash (Lisp_Object obj, int UNUSED (depth)) { - unsigned long hash = (unsigned long) XMARKER (obj)->buffer; + Hashcode hash = (Hashcode) XMARKER (obj)->buffer; if (hash) hash = HASH2 (hash, XMARKER (obj)->membpos); return hash; } static const struct memory_description marker_description[] = { - { XD_LISP_OBJECT, offsetof (Lisp_Marker, next), 0, 0, XD_FLAG_NO_KKCC }, - { XD_LISP_OBJECT, offsetof (Lisp_Marker, prev), 0, 0, XD_FLAG_NO_KKCC }, + { XD_LISP_OBJECT, offsetof (Lisp_Marker, next), 0, { 0 }, XD_FLAG_NO_KKCC }, + { XD_LISP_OBJECT, offsetof (Lisp_Marker, prev), 0, { 0 }, XD_FLAG_NO_KKCC }, { XD_LISP_OBJECT, offsetof (Lisp_Marker, buffer) }, { XD_END } }; diff --text -u 'xemacs-21.5.18/src/menubar-gtk.c' 'xemacs-21.5.19/src/menubar-gtk.c' Index: ./src/menubar-gtk.c --- ./src/menubar-gtk.c Tue Sep 21 04:19:51 2004 +++ ./src/menubar-gtk.c Tue Jan 25 08:34:03 2005 @@ -875,13 +875,15 @@ if (STRINGP (suffix) && XSTRING_LENGTH (suffix)) { - label_buffer = (Ibyte*) ALLOCA (XSTRING_LENGTH (name) + 15 + XSTRING_LENGTH (suffix)); - sprintf ((char*) label_buffer, "%s %s ", XSTRING_DATA (name), XSTRING_DATA (suffix)); + /* !!#### */ + label_buffer = alloca_ibytes (XSTRING_LENGTH (name) + 15 + XSTRING_LENGTH (suffix)); + qxesprintf (label_buffer, "%s %s ", XSTRING_DATA (name), + XSTRING_DATA (suffix)); } else { - label_buffer = (Ibyte*) ALLOCA (XSTRING_LENGTH (name) + 15); - sprintf ((char*) label_buffer, "%s ", XSTRING_DATA (name)); + label_buffer = alloca_ibytes (XSTRING_LENGTH (name) + 15); + qxesprintf (label_buffer, "%s ", XSTRING_DATA (name)); } temp_label = convert_underscores (label_buffer); @@ -1034,7 +1036,7 @@ else { return (NULL); - /* abort (); ???? */ + /* ABORT (); ???? */ } } @@ -1082,9 +1084,7 @@ menu_create_menubar (struct frame *f, Lisp_Object descr) { gboolean right_justify = FALSE; - Lisp_Object tail = Qnil; Lisp_Object value = descr; - Lisp_Object item_descr = Qnil; GtkWidget *menubar = FRAME_GTK_MENUBAR_WIDGET (f); GUI_ID id = (GUI_ID) gtk_object_get_data (GTK_OBJECT (menubar), XEMACS_MENU_GUIID_TAG); guint menu_position = 0; @@ -1098,74 +1098,74 @@ menubar_accel_group = gtk_accel_group_new(); - EXTERNAL_LIST_LOOP (tail, value) - { - gpointer current_child = g_list_nth_data (GTK_MENU_SHELL (menubar)->children, menu_position); - - item_descr = XCAR (tail); - - if (NILP (item_descr)) - { - /* Need to start right-justifying menus */ - right_justify = TRUE; - menu_position--; - } - else if (VECTORP (item_descr)) - { - /* It is a button description */ - GtkWidget *item; + { + EXTERNAL_LIST_LOOP_2 (item_descr, value) + { + gpointer current_child = g_list_nth_data (GTK_MENU_SHELL (menubar)->children, menu_position); - item = menu_descriptor_to_widget (item_descr, menubar_accel_group); - gtk_widget_set_name (item, "XEmacsMenuButton"); + if (NILP (item_descr)) + { + /* Need to start right-justifying menus */ + right_justify = TRUE; + menu_position--; + } + else if (VECTORP (item_descr)) + { + /* It is a button description */ + GtkWidget *item; - if (!item) - { - item = gtk_menu_item_new_with_label ("ITEM CREATION ERROR"); - } + item = menu_descriptor_to_widget (item_descr, menubar_accel_group); + gtk_widget_set_name (item, "XEmacsMenuButton"); - gtk_widget_show_all (item); - if (current_child) gtk_widget_destroy (GTK_WIDGET (current_child)); - gtk_menu_bar_insert (GTK_MENU_BAR (menubar), item, menu_position); - } - else if (LISTP (item_descr)) - { - /* Need to actually convert it into a menu and slap it in */ - GtkWidget *widget; - gboolean reused_p = FALSE; - - /* We may be able to reuse the widget, let's at least check. */ - if (current_child && menu_can_reuse_widget (GTK_WIDGET (current_child), - XSTRING_DATA (XCAR (item_descr)))) - { - widget = menu_convert (item_descr, GTK_WIDGET (current_child), - menubar_accel_group); - reused_p = TRUE; - } - else - { - widget = menu_convert (item_descr, NULL, menubar_accel_group); - if (current_child) gtk_widget_destroy (GTK_WIDGET (current_child)); - gtk_menu_bar_insert (GTK_MENU_BAR (menubar), widget, menu_position); - } - - if (widget) - { - if (right_justify) gtk_menu_item_right_justify (GTK_MENU_ITEM (widget)); - } - else - { - widget = gtk_menu_item_new_with_label ("ERROR"); - /* abort() */ - } - gtk_widget_show_all (widget); - } - else if (STRINGP (item_descr)) - { - /* Do I really want to be this careful? Anything else in a - menubar description is illegal */ - } - menu_position++; - } + if (!item) + { + item = gtk_menu_item_new_with_label ("ITEM CREATION ERROR"); + } + + gtk_widget_show_all (item); + if (current_child) gtk_widget_destroy (GTK_WIDGET (current_child)); + gtk_menu_bar_insert (GTK_MENU_BAR (menubar), item, menu_position); + } + else if (LISTP (item_descr)) + { + /* Need to actually convert it into a menu and slap it in */ + GtkWidget *widget; + gboolean reused_p = FALSE; + + /* We may be able to reuse the widget, let's at least check. */ + if (current_child && menu_can_reuse_widget (GTK_WIDGET (current_child), + XSTRING_DATA (XCAR (item_descr)))) + { + widget = menu_convert (item_descr, GTK_WIDGET (current_child), + menubar_accel_group); + reused_p = TRUE; + } + else + { + widget = menu_convert (item_descr, NULL, menubar_accel_group); + if (current_child) gtk_widget_destroy (GTK_WIDGET (current_child)); + gtk_menu_bar_insert (GTK_MENU_BAR (menubar), widget, menu_position); + } + + if (widget) + { + if (right_justify) gtk_menu_item_right_justify (GTK_MENU_ITEM (widget)); + } + else + { + widget = gtk_menu_item_new_with_label ("ERROR"); + /* ABORT() */ + } + gtk_widget_show_all (widget); + } + else if (STRINGP (item_descr)) + { + /* Do I really want to be this careful? Anything else in a + menubar description is illegal */ + } + menu_position++; + } + } /* Need to delete any menu items that were past the bounds of the new one */ { @@ -1495,7 +1495,6 @@ If non-nil, menus can be torn off into their own top-level windows. */ ); #endif - reinit_vars_of_menubar_gtk (); } /*---------------------------------------------------------------------------*/ diff --text -u 'xemacs-21.5.18/src/menubar-msw.c' 'xemacs-21.5.19/src/menubar-msw.c' Index: ./src/menubar-msw.c --- ./src/menubar-msw.c Tue Sep 21 04:19:51 2004 +++ ./src/menubar-msw.c Tue Jan 25 08:34:03 2005 @@ -383,7 +383,6 @@ populate_or_checksum_helper (HMENU menu, Lisp_Object path, Lisp_Object desc, Lisp_Object hash_tab, int bar_p, int populate_p) { - Lisp_Object item_desc; int deep_p, flush_right; struct gcpro gcpro1, gcpro2, gcpro3; unsigned long checksum; @@ -418,24 +417,26 @@ /* Loop thru the desc's CDR and add items for each entry */ flush_right = 0; - EXTERNAL_LIST_LOOP (item_desc, desc) - { - if (NILP (XCAR (item_desc))) - { - /* Do not flush right menubar items when MS style compliant */ - if (bar_p && !REPLACE_ME_WITH_GLOBAL_VARIABLE_WHICH_CONTROLS_RIGHT_FLUSH) - flush_right = 1; - if (!populate_p) - checksum = HASH2 (checksum, LISP_HASH (Qnil)); - } - else if (populate_p) - populate_menu_add_item (menu, path, hash_tab, - XCAR (item_desc), &accel_list, - flush_right, bar_p); - else - checksum = HASH2 (checksum, - checksum_menu_item (XCAR (item_desc))); - } + { + EXTERNAL_LIST_LOOP_2 (elt, desc) + { + if (NILP (elt)) + { + /* Do not flush right menubar items when MS style compliant */ + if (bar_p && !REPLACE_ME_WITH_GLOBAL_VARIABLE_WHICH_CONTROLS_RIGHT_FLUSH) + flush_right = 1; + if (!populate_p) + checksum = HASH2 (checksum, LISP_HASH (Qnil)); + } + else if (populate_p) + populate_menu_add_item (menu, path, hash_tab, + elt, &accel_list, + flush_right, bar_p); + else + checksum = HASH2 (checksum, + checksum_menu_item (elt)); + } + } if (populate_p) { @@ -556,12 +557,12 @@ if (menubar == NULL) return; - /* #### If a filter function has set desc to Qnil, this abort() + /* #### If a filter function has set desc to Qnil, this ABORT() triggers. To resolve, we must prevent filters explicitly from mangling with the active menu. In apply_filter probably? Is copy-tree on the whole menu too expensive? */ if (NILP (desc)) - /* abort(); */ + /* ABORT(); */ return; GCPRO1 (desc); /* just to be safe -- see above */ diff --text -u 'xemacs-21.5.18/src/menubar-x.c' 'xemacs-21.5.19/src/menubar-x.c' Index: ./src/menubar-x.c --- ./src/menubar-x.c Tue Sep 21 04:19:51 2004 +++ ./src/menubar-x.c Tue Jan 25 08:34:04 2005 @@ -576,7 +576,7 @@ data = compute_menubar_data (f, menubar, deep_p); if (!data || (!data->next && !data->contents)) - abort (); + ABORT (); if (!FRAME_X_MENUBAR_ID (f)) FRAME_X_MENUBAR_ID (f) = new_lwlib_id (); @@ -1375,8 +1375,6 @@ void vars_of_menubar_x (void) { - reinit_vars_of_menubar_x (); - #if defined (LWLIB_MENUBARS_LUCID) Fprovide (intern ("lucid-menubars")); #elif defined (LWLIB_MENUBARS_MOTIF) diff --text -u 'xemacs-21.5.18/src/menubar.c' 'xemacs-21.5.19/src/menubar.c' Index: ./src/menubar.c --- ./src/menubar.c Tue Sep 21 04:19:51 2004 +++ ./src/menubar.c Thu Feb 3 14:03:45 2005 @@ -1,7 +1,7 @@ /* Implements an elisp-programmable menubar. Copyright (C) 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1995 Tinker Systems and INS Engineering Corp. - Copyright (C) 2001, 2002 Ben Wing. + Copyright (C) 2001, 2002, 2003 Ben Wing. This file is part of XEmacs. @@ -187,49 +187,51 @@ */ (desc, path)) { - Lisp_Object path_entry, submenu_desc, submenu; struct gcpro gcpro1, gcpro2; Lisp_Object gui_item = allocate_gui_item (); Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); GCPRO2 (gui_item, desc); - EXTERNAL_LIST_LOOP (path_entry, path) - { - /* Verify that DESC describes a menu, not single item */ - if (!CONSP (desc)) - RETURN_UNGCPRO (Qnil); - - /* Parse this menu */ - desc = menu_parse_submenu_keywords (desc, gui_item); - - /* Check that this (sub)menu is active */ - if (!gui_item_active_p (gui_item)) - RETURN_UNGCPRO (Qnil); + { + EXTERNAL_LIST_LOOP_2 (elt, path) + { + /* Verify that DESC describes a menu, not single item */ + if (!CONSP (desc)) + RETURN_UNGCPRO (Qnil); + + /* Parse this menu */ + desc = menu_parse_submenu_keywords (desc, gui_item); + + /* Check that this (sub)menu is active */ + if (!gui_item_active_p (gui_item)) + RETURN_UNGCPRO (Qnil); + + /* Apply :filter */ + if (!NILP (pgui_item->filter)) + desc = call1 (pgui_item->filter, desc); - /* Apply :filter */ - if (!NILP (pgui_item->filter)) - desc = call1 (pgui_item->filter, desc); - - /* Find the next menu on the path inside this one */ - EXTERNAL_LIST_LOOP (submenu_desc, desc) + /* Find the next menu on the path inside this one */ { - submenu = XCAR (submenu_desc); - if (CONSP (submenu) - && STRINGP (XCAR (submenu)) - && !NILP (Fstring_equal (XCAR (submenu), XCAR (path_entry)))) + EXTERNAL_LIST_LOOP_2 (submenu, desc) { - desc = submenu; - goto descend; + if (CONSP (submenu) + && STRINGP (XCAR (submenu)) + && !NILP (Fstring_equal (XCAR (submenu), elt))) + { + desc = submenu; + goto descend; + } } } - /* Submenu not found */ - RETURN_UNGCPRO (Qnil); + /* Submenu not found */ + RETURN_UNGCPRO (Qnil); - descend: - /* Prepare for the next iteration */ - gui_item_init (gui_item); - } + descend: + /* Prepare for the next iteration */ + gui_item_init (gui_item); + } + } /* We have successfully descended down the end of the path */ UNGCPRO; @@ -324,14 +326,51 @@ return Qnil; } -DEFUN ("normalize-menu-item-name", Fnormalize_menu_item_name, 1, 2, 0, /* +DEFUN ("compare-menu-text", Fcompare_menu_text, 2, 2, 0, /* +Compare the text of two menu items, ignoring accelerator specs and case. +Also treat %% as a single %. Return < 0 if STRING1 is less than STRING2, +0 if equal, > 0 if STRING1 is greater than STRING2. +*/ + (string1, string2)) +{ + Ibyte *p; + Ibyte *q; + + CHECK_STRING (string1); + CHECK_STRING (string2); + + p = XSTRING_DATA (string1); + q = XSTRING_DATA (string2); + + for (;;) + { + Ichar val; + if (*p == '%' && *(p + 1) == '%') + p++; + else if (*p == '%' && *(p + 1) == '_') + p += 2; + if (*q == '%' && *(q + 1) == '%') + q++; + else if (*q == '%' && *(q + 1) == '_') + q += 2; + if (!*p || !*q) + return make_int (*p - *q); + val = DOWNCASE (0, itext_ichar (p)) - DOWNCASE (0, itext_ichar (q)); + if (val) + return make_int (val); + INC_IBYTEPTR (p); + INC_IBYTEPTR (q); + } +} + +DEFUN ("normalize-menu-text", Fnormalize_menu_text, 1, 1, 0, /* Convert a menu item name string into normal form, and return the new string. Menu item names should be converted to normal form before being compared. This removes %_'s (accelerator indications) and converts %% to %. +The returned string may be the same string as the original. */ - (name, buffer)) + (name)) { - struct buffer *buf = decode_buffer (buffer, 0); Charcount end; int i; Ibyte *name_data; @@ -345,12 +384,11 @@ end = string_char_length (name); name_data = XSTRING_DATA (name); - string_result = (Ibyte *) ALLOCA (end * MAX_ICHAR_LEN); + string_result = alloca_ibytes (end * MAX_ICHAR_LEN); string_result_ptr = string_result; for (i = 0; i < end; i++) { elt = itext_ichar (name_data); - elt = DOWNCASE (buf, elt); if (expecting_underscore) { expecting_underscore = 0; @@ -398,7 +436,8 @@ DEFSYMBOL (Qmenu_escape); DEFSUBR (Fpopup_menu); - DEFSUBR (Fnormalize_menu_item_name); + DEFSUBR (Fcompare_menu_text); + DEFSUBR (Fnormalize_menu_text); DEFSUBR (Fmenu_find_real_submenu); } diff --text -u 'xemacs-21.5.18/src/minibuf.c' 'xemacs-21.5.19/src/minibuf.c' Index: ./src/minibuf.c --- ./src/minibuf.c Tue Sep 21 04:19:51 2004 +++ ./src/minibuf.c Fri Nov 5 08:06:42 2004 @@ -255,10 +255,8 @@ /* Ignore this element if it fails to match all the regexps. */ if (!NILP (Vcompletion_regexp_list)) { - Lisp_Object regexps; - EXTERNAL_LIST_LOOP (regexps, Vcompletion_regexp_list) + EXTERNAL_LIST_LOOP_2 (re, Vcompletion_regexp_list) { - Lisp_Object re = XCAR (regexps); CHECK_STRING (re); if (fast_string_match (re, nonreloc, reloc, offset, length, 0, ERROR_ME, 0) < 0) @@ -955,8 +953,6 @@ void vars_of_minibuf (void) { - reinit_vars_of_minibuf (); - staticpro (&Vminibuf_prompt); Vminibuf_prompt = Qnil; diff --text -u 'xemacs-21.5.18/src/miscplay.c' 'xemacs-21.5.19/src/miscplay.c' Index: ./src/miscplay.c --- ./src/miscplay.c Tue Sep 21 04:19:51 2004 +++ ./src/miscplay.c Fri Nov 5 08:06:42 2004 @@ -48,7 +48,7 @@ int align; enum wvState state; size_t left; - UChar_Binary leftover[HEADERSZ]; + Binbyte leftover[HEADERSZ]; signed long chunklength; } wave; struct { @@ -56,13 +56,13 @@ int isdata; int skipping; size_t left; - UChar_Binary leftover[HEADERSZ]; + Binbyte leftover[HEADERSZ]; } audio; } parsestate; /* Use a global buffer as scratch-pad for possible conversions of the sampling format */ -UChar_Binary miscplay_sndbuf[SNDBUFSZ]; +Binbyte miscplay_sndbuf[SNDBUFSZ]; /* Initialize global parser state information to zero */ void reset_parsestate() @@ -121,7 +121,7 @@ memcpy(parsestate.wave.leftover+parsestate.wave.left, *data,rq); parsestate.wave.left += rq; - (*(UChar_Binary **)data) += rq; + (*(Binbyte **)data) += rq; *sz -= rq; return(rc); } @@ -192,7 +192,7 @@ else { if (parsestate.wave.chunklength > 0 && *sz > 0) { *sz -= parsestate.wave.chunklength; - (*(UChar_Binary **)data) += parsestate.wave.chunklength; } + (*(Binbyte **)data) += parsestate.wave.chunklength; } parsestate.wave.state = wvOutOfBlock; } break; case wvSoundChunk: { @@ -217,7 +217,7 @@ count = *sz; count -= rq = count % parsestate.wave.align; } *outbuf = *data; - (*(UChar_Binary **)data) += count; + (*(Binbyte **)data) += count; *sz -= count; if ((parsestate.wave.chunklength -= count) < parsestate.wave.align) { parsestate.wave.state = wvOutOfBlock; @@ -258,7 +258,7 @@ count = parsestate.audio.align - parsestate.audio.left); *outbuf = parsestate.audio.leftover; *sz -= count; - *data = (*(Char_Binary **)data) + count; + *data = (*(CBinbyte **)data) + count; parsestate.audio.left = 0; return(parsestate.audio.align); } else { @@ -266,7 +266,7 @@ memmove(parsestate.audio.leftover + parsestate.audio.left, *data, *sz); - *data = (*(Char_Binary **)data) + *sz; + *data = (*(CBinbyte **)data) + *sz; parsestate.audio.left += *sz; *sz = 0; return(0); } } @@ -278,7 +278,7 @@ *outbuf = *data; if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) { memmove(parsestate.audio.leftover, - (Char_Binary *)*outbuf + rc - parsestate.audio.left, + (CBinbyte *)*outbuf + rc - parsestate.audio.left, parsestate.audio.left); rc -= parsestate.audio.left; } *sz = 0; @@ -288,7 +288,7 @@ header information and determine how many bytes we need to skip until the start of the sound chunk */ if (!parsestate.audio.skipping) { - UChar_Binary *header = (UChar_Binary *) *data; + Binbyte *header = (Binbyte *) *data; if (*sz < 8) { sound_warn("Irrecoverable error while parsing Sun/DEC audio file"); return(0); } @@ -310,10 +310,10 @@ if (*sz >= (size_t) parsestate.audio.skipping) { /* Skip just the header information and return the sound chunk */ int rc = *sz - parsestate.audio.skipping; - *outbuf = (Char_Binary *)*data + parsestate.audio.skipping; + *outbuf = (CBinbyte *)*data + parsestate.audio.skipping; if ((parsestate.audio.left = rc % parsestate.audio.align) != 0) { memmove(parsestate.audio.leftover, - (Char_Binary *)*outbuf + rc - parsestate.audio.left, + (CBinbyte *)*outbuf + rc - parsestate.audio.left, parsestate.audio.left); rc -= parsestate.audio.left; } *sz = 0; @@ -341,20 +341,20 @@ /* Convert 8 bit unsigned stereo data to 8 bit unsigned mono data */ size_t sndcnv8U_2mono(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; count = *sz / 2; if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) { - *dest++ = (UChar_Binary)(((int)*(src) + + *dest++ = (Binbyte)(((int)*(src) + (int)*(src+1)) / 2); src += 2; } @@ -365,21 +365,21 @@ /* Convert 8 bit signed stereo data to 8 bit signed mono data */ size_t sndcnv8S_2mono(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc, count; count = *sz / 2; if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) { - *dest++ = (UChar_Binary)(((int)*((SChar_Binary *)(src)) + - (int)*((SChar_Binary *)(src+1))) / 2); + *dest++ = (Binbyte)(((int)*((SBinbyte *)(src)) + + (int)*((SBinbyte *)(src+1))) / 2); src += 2; } *data = src; @@ -389,21 +389,21 @@ /* Convert 8 bit signed stereo data to 8 bit unsigned mono data */ size_t sndcnv2monounsigned(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; count = *sz / 2; if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) { - *dest++ = (UChar_Binary)(((int)*((SChar_Binary *)(src)) + - (int)*((SChar_Binary *)(src+1))) / 2) ^ 0x80; + *dest++ = (Binbyte)(((int)*((SBinbyte *)(src)) + + (int)*((SBinbyte *)(src+1))) / 2) ^ 0x80; src += 2; } *data = src; @@ -413,15 +413,15 @@ /* Convert 8 bit signed mono data to 8 bit unsigned mono data */ size_t sndcnv2unsigned(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; count = *sz; if (count > SNDBUFSZ) { *sz -= SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) @@ -432,7 +432,7 @@ /* Convert a number in the range -32768..32767 to an 8 bit ulaw encoded number --- I hope, I got this conversion right :-) */ -static inline SChar_Binary int2ulaw(int i) +static inline SBinbyte int2ulaw(int i) { /* Lookup table for fast calculation of number of bits that need shifting*/ static short int t_bits[128] = { @@ -457,7 +457,7 @@ size_t sndcnvULaw_2linear(void **data,size_t *sz,void **outbuf) { /* conversion table stolen from Linux's ulaw.h */ - static UChar_Binary ulaw_dsp[] = { + static Binbyte ulaw_dsp[] = { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 66, 68, 70, 72, 74, 76, 78, 80, @@ -491,7 +491,7 @@ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; - UChar_Binary *p=(UChar_Binary *)*data; + Binbyte *p=(Binbyte *)*data; *outbuf = *data; while ((*sz)--) @@ -501,7 +501,7 @@ } *sz = 0; *data = p; - return p - (UChar_Binary *)*outbuf; + return p - (Binbyte *)*outbuf; } /* Convert 8 bit ulaw stereo data to 8 bit ulaw mono data */ @@ -543,15 +543,15 @@ +60, +56, +52, +48, +44, +40, +36, +32, +28, +24, +20, +16, +12, +8, +4, +0}; - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; count = *sz / 2; if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) @@ -589,8 +589,8 @@ signed mono data */ size_t sndcnv16_2monoLE(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; signed short i; @@ -598,7 +598,7 @@ if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; for (count /= 2; count--; ) { @@ -607,8 +607,8 @@ (int)(src[2]) + 256*(int)(src[3])) / 2; src += 4; - *dest++ = (UChar_Binary)(i & 0xFF); - *dest++ = (UChar_Binary)((i / 256) & 0xFF); } + *dest++ = (Binbyte)(i & 0xFF); + *dest++ = (Binbyte)((i / 256) & 0xFF); } *data = src; return(rc); } @@ -617,8 +617,8 @@ signed mono data */ size_t sndcnv16_2monoBE(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; signed short i; @@ -626,7 +626,7 @@ if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; for (count /= 2; count--; ) { @@ -635,8 +635,8 @@ (int)(src[3]) + 256*(int)(src[2])) / 2; src += 4; - *dest++ = (UChar_Binary)((i / 256) & 0xFF); - *dest++ = (UChar_Binary)(i & 0xFF); } + *dest++ = (Binbyte)((i / 256) & 0xFF); + *dest++ = (Binbyte)(i & 0xFF); } *data = src; return(rc); } @@ -644,19 +644,19 @@ /* Convert 16 bit little endian signed data to 8 bit unsigned data */ size_t sndcnv2byteLE(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; count = *sz / 2; if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) { - *dest++ = (UChar_Binary)(((SChar_Binary *)src)[1] ^ (SChar_Binary)0x80); + *dest++ = (Binbyte)(((SBinbyte *)src)[1] ^ (SBinbyte)0x80); src += 2; } *data = src; @@ -666,19 +666,19 @@ /* Convert 16 bit big endian signed data to 8 bit unsigned data */ size_t sndcnv2byteBE(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; count = *sz / 2; if (count > SNDBUFSZ) { *sz -= 2*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) { - *dest++ = (UChar_Binary)(((SChar_Binary *)src)[0] ^ (SChar_Binary)0x80); + *dest++ = (Binbyte)(((SBinbyte *)src)[0] ^ (SBinbyte)0x80); src += 2; } *data = src; @@ -689,20 +689,20 @@ mono data */ size_t sndcnv2monobyteLE(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; count = *sz / 4; if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) { - *dest++ = (UChar_Binary)(((int)((SChar_Binary *)src)[1] + - (int)((SChar_Binary *)src)[3]) / 2 ^ 0x80); + *dest++ = (Binbyte)(((int)((SBinbyte *)src)[1] + + (int)((SBinbyte *)src)[3]) / 2 ^ 0x80); src += 4; } *data = src; @@ -713,20 +713,20 @@ mono data */ size_t sndcnv2monobyteBE(void **data,size_t *sz,void **outbuf) { - REGISTER UChar_Binary *src; - REGISTER UChar_Binary *dest; + REGISTER Binbyte *src; + REGISTER Binbyte *dest; int rc,count; count = *sz / 4; if (count > SNDBUFSZ) { *sz -= 4*SNDBUFSZ; count = SNDBUFSZ; } else *sz = 0; rc = count; - src = (UChar_Binary *) *data; + src = (Binbyte *) *data; *outbuf = dest = miscplay_sndbuf; while (count--) { - *dest++ = (UChar_Binary)(((int)((SChar_Binary *)src)[0] + - (int)((SChar_Binary *)src)[2]) / 2 ^ 0x80); + *dest++ = (Binbyte)(((int)((SBinbyte *)src)[0] + + (int)((SBinbyte *)src)[2]) / 2 ^ 0x80); src += 4; } *data = src; @@ -736,7 +736,7 @@ /* Look at the header of the sound file and try to determine the format; we can recognize files in VOC, WAVE, and, Sun/DEC-audio format--- everything else is assumed to be raw 8 bit unsigned data sampled at 8kHz */ -fmtType analyze_format(UChar_Binary *format,int *fmt,int *speed, +fmtType analyze_format(Binbyte *format,int *fmt,int *speed, int *tracks, size_t (**parsesndfile)(void **,size_t *sz, void **)) diff --text -u 'xemacs-21.5.18/src/miscplay.h' 'xemacs-21.5.19/src/miscplay.h' Index: ./src/miscplay.h --- ./src/miscplay.h Thu May 24 16:51:24 2001 +++ ./src/miscplay.h Fri Nov 5 08:06:42 2004 @@ -55,7 +55,7 @@ size_t sndcnv2monobyteLE(void **data,size_t *sz,void **outbuf); size_t sndcnv2monobyteBE(void **data,size_t *sz,void **outbuf); -fmtType analyze_format(UChar_Binary *format,int *fmt,int *speed, +fmtType analyze_format(Binbyte *format,int *fmt,int *speed, int *tracks, size_t (**parsesndfile)(void **,size_t *sz, void **)); diff --text -u 'xemacs-21.5.18/src/mule-charset.c' 'xemacs-21.5.19/src/mule-charset.c' Index: ./src/mule-charset.c --- ./src/mule-charset.c Tue Sep 21 04:19:52 2004 +++ ./src/mule-charset.c Fri Feb 4 01:14:07 2005 @@ -1,7 +1,7 @@ /* Functions to handle multilingual characters. Copyright (C) 1992, 1995 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 2001, 2002 Ben Wing. + Copyright (C) 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -162,20 +162,6 @@ write_fmt_string (printcharfun, " 0x%x>", cs->header.uid); } -static void -finalize_charset (void *header, int for_disksave) -{ - /* See mule-charset.h, definition of Lisp_Charset. */ - Lisp_Object charset = wrap_charset ((Lisp_Charset *) header); - if (for_disksave && XCHARSET_TO_UNICODE_TABLE (charset)) - { - /* Control-1, ASCII, Composite don't have tables */ - free_charset_unicode_tables (charset); - XCHARSET_TO_UNICODE_TABLE (charset) = 0; - XCHARSET_FROM_UNICODE_TABLE (charset) = 0; - } -} - static const struct memory_description charset_description[] = { { XD_INT, offsetof (Lisp_Charset, dimension) }, { XD_INT, offsetof (Lisp_Charset, from_unicode_levels) }, @@ -187,15 +173,15 @@ { XD_LISP_OBJECT, offsetof (Lisp_Charset, reverse_direction_charset) }, { XD_LISP_OBJECT, offsetof (Lisp_Charset, ccl_program) }, { XD_UNION, offsetof (Lisp_Charset, to_unicode_table), - XD_INDIRECT (0, 0), &to_unicode_description }, + XD_INDIRECT (0, 0), { &to_unicode_description } }, { XD_UNION, offsetof (Lisp_Charset, from_unicode_table), - XD_INDIRECT (1, 0), &from_unicode_description }, + XD_INDIRECT (1, 0), { &from_unicode_description } }, { XD_END } }; DEFINE_LRECORD_IMPLEMENTATION ("charset", charset, 1, /* dumpable flag */ - mark_charset, print_charset, finalize_charset, + mark_charset, print_charset, 0, 0, 0, charset_description, Lisp_Charset); /* Make a new charset. */ /* #### SJT Should generic properties be allowed? */ @@ -1014,30 +1000,13 @@ DEFSYMBOL (Qcomposite); } -static int -init_charset_unicode_tables_mapper (Lisp_Object UNUSED (key), - Lisp_Object value, void *UNUSED (closure)) -{ - init_charset_unicode_tables (value); - return 0; -} - -void -init_mule_charset (void) -{ - /* See mule-charset.h, definition of Lisp_Charset. */ - if (initialized) - elisp_maphash (init_charset_unicode_tables_mapper, Vcharset_hash_table, - 0); -} - void vars_of_mule_charset (void) { int i, j, k; chlook = xnew_and_zero (struct charset_lookup); /* zero for Purify. */ - dump_add_root_struct_ptr (&chlook, &charset_lookup_description); + dump_add_root_block_ptr (&chlook, &charset_lookup_description); /* Table of charsets indexed by leading byte. */ for (i = 0; i < countof (chlook->charset_by_leading_byte); i++) diff --text -u 'xemacs-21.5.18/src/mule-coding.c' 'xemacs-21.5.19/src/mule-coding.c' Index: ./src/mule-coding.c --- ./src/mule-coding.c Tue Sep 21 04:19:52 2004 +++ ./src/mule-coding.c Fri Feb 4 01:14:07 2005 @@ -952,10 +952,10 @@ static const struct memory_description iso2022_coding_system_description[] = { { XD_LISP_OBJECT_ARRAY, offsetof (struct iso2022_coding_system, initial_charset), 4 }, - { XD_STRUCT_PTR, offsetof (struct iso2022_coding_system, input_conv), - 1, &ccsd_description }, - { XD_STRUCT_PTR, offsetof (struct iso2022_coding_system, output_conv), - 1, &ccsd_description }, + { XD_BLOCK_PTR, offsetof (struct iso2022_coding_system, input_conv), + 1, { &ccsd_description } }, + { XD_BLOCK_PTR, offsetof (struct iso2022_coding_system, output_conv), + 1, { &ccsd_description } }, { XD_END } }; @@ -1247,7 +1247,7 @@ chars = 96; dim = 2; break; default: - abort (); chars = 0; dim = 0; + ABORT (); chars = 0; dim = 0; } charset = Fmake_charset (Qunbound, Qnil, @@ -1274,46 +1274,7 @@ or invocation of an invalid character set and treat that as an unrecognized escape sequence. - ******************************************************************** - - #### Strategies for error annotation and coding orthogonalization - - We really want to separate out a number of things. Conceptually, - there is a nested syntax. - - At the top level is the ISO 2022 extension syntax, including charset - designation and invocation, and certain auxiliary controls such as the - ISO 6429 direction specification. These are octet-oriented, with the - single exception (AFAIK) of the "exit Unicode" sequence which uses the - UTF's natural width (1 byte for UTF-7 and UTF-8, 2 bytes for UCS-2 and - UTF-16, and 4 bytes for UCS-4 and UTF-32). This will be treated as a - (deprecated) special case in Unicode processing. - - The middle layer is ISO 2022 character interpretation. This will depend - on the current state of the ISO 2022 registers, and assembles octets - into the character's internal representation. - - The lowest level is translating system control conventions. At present - this is restricted to newline translation, but one could imagine doing - tab conversion or line wrapping here. "Escape from Unicode" processing - would be done at this level. - - At each level the parser will verify the syntax. In the case of a - syntax error or warning (such as a redundant escape sequence that affects - no characters), the parser will take some action, typically inserting the - erroneous octets directly into the output and creating an annotation - which can be used by higher level I/O to mark the affected region. - - This should make it possible to do something sensible about separating - newline convention processing from character construction, and about - preventing ISO 2022 escape sequences from being recognized - inappropriately. - - The basic strategy will be to have octet classification tables, and - switch processing according to the table entry. - - It's possible that, by doing the processing with tables of functions or - the like, the parser can be used for both detection and translation. */ +*/ static int parse_iso2022_esc (Lisp_Object codesys, struct iso2022_coding_stream *iso, @@ -1591,7 +1552,7 @@ else { /* Can this ever be reached? -slb */ - abort (); + ABORT (); goto error; } @@ -1640,7 +1601,7 @@ designated: if (NILP (cs) && check_invalid_charsets) { - abort (); + ABORT (); /* #### This should never happen now that we automatically create temporary charsets as necessary. We should probably remove this code. --ben */ @@ -2280,7 +2241,7 @@ break; default: - abort (); + ABORT (); } } char_boundary = 0; @@ -2374,7 +2335,7 @@ } break; default: - abort (); + ABORT (); } } } @@ -2480,11 +2441,8 @@ parse_charset_conversion_specs (charset_conversion_spec_dynarr *store_here, Lisp_Object spec_list) { - Lisp_Object rest; - - EXTERNAL_LIST_LOOP (rest, spec_list) + EXTERNAL_LIST_LOOP_2 (car, spec_list) { - Lisp_Object car = XCAR (rest); Lisp_Object from, to; struct charset_conversion_spec spec; @@ -3078,7 +3036,7 @@ { Lisp_Object sym; struct ccl_program test_ccl; - Char_ASCII *suffix; + Ascbyte *suffix; /* Check key first. */ if (EQ (key, Qdecode)) diff --text -u 'xemacs-21.5.18/src/mule-wnnfns.c' 'xemacs-21.5.19/src/mule-wnnfns.c' Index: ./src/mule-wnnfns.c --- ./src/mule-wnnfns.c Fri Aug 29 00:44:29 2003 +++ ./src/mule-wnnfns.c Fri Nov 5 08:06:43 2004 @@ -361,6 +361,7 @@ return Qnil; } size = XSTRING_LENGTH (lname) > 1024 ? 1026 : XSTRING_LENGTH (lname) + 2; + /* !!#### */ envname = (char *) ALLOCA (size); strncpy (envname, (char *) XSTRING_DATA (lname), size-2); envname[size-2] = '\0'; @@ -1890,8 +1891,6 @@ void vars_of_mule_wnn (void) { - reinit_vars_of_mule_wnn (); - DEFVAR_INT ("lb-sisheng", &lb_sisheng /* Leading character for Sisheng. */ ); diff --text -u 'xemacs-21.5.18/src/nas.c' 'xemacs-21.5.19/src/nas.c' Index: ./src/nas.c --- ./src/nas.c Tue Sep 21 04:19:52 2004 +++ ./src/nas.c Fri Nov 5 08:06:43 2004 @@ -136,7 +136,7 @@ extern Lisp_Object Vsynchronous_sounds; -static Sound SoundOpenDataForReading (UChar_Binary *data, int length); +static Sound SoundOpenDataForReading (Binbyte *data, int length); static AuServer *aud; @@ -274,7 +274,7 @@ static void do_caching_play (Sound s, int volume, - UChar_Binary *buf) + Binbyte *buf) { AuBucketAttributes *list, b; @@ -442,9 +442,9 @@ return 1; } -int nas_play_sound_data (UChar_Binary *data, int length, int volume); +int nas_play_sound_data (Binbyte *data, int length, int volume); int -nas_play_sound_data (UChar_Binary *data, int length, int volume) +nas_play_sound_data (Binbyte *data, int length, int volume) { Sound s; int offset; @@ -621,7 +621,7 @@ /* Create a name from the sound. */ static Extbyte * -NameFromData (const Char_Binary *buf, +NameFromData (const CBinbyte *buf, int len) { @@ -665,7 +665,7 @@ */ static SndInfo * -SndOpenDataForReading (const Char_Binary *data, +SndOpenDataForReading (const CBinbyte *data, int length) { @@ -682,7 +682,7 @@ if (NAS_LITTLE_ENDIAN) { - Char_Binary n; + CBinbyte n; swapl (&si->h.magic, n); swapl (&si->h.dataOffset, n); @@ -731,7 +731,7 @@ #define Err() { return NULL; } #define readFourcc(_f) dread(_f, sizeof(RIFF_FOURCC), 1) #define cmpID(_x, _y) \ - strncmp((Char_Binary *) (_x), (Char_Binary *) (_y), sizeof(RIFF_FOURCC)) + strncmp((CBinbyte *) (_x), (CBinbyte *) (_y), sizeof(RIFF_FOURCC)) #define PAD2(_x) (((_x) + 1) & ~1) /* These functions here are for faking file I/O from buffer. */ @@ -760,7 +760,7 @@ if (file_posn + nread <= file_len) { - memcpy(buf, (Char_Binary *) file_data + file_posn, size * nitems); + memcpy(buf, (CBinbyte *) file_data + file_posn, size * nitems); file_posn += nread; return nitems; } @@ -775,7 +775,7 @@ dgetc (void) { if (file_posn < file_len) - return ((Char_Binary *)file_data)[file_posn++]; + return ((CBinbyte *)file_data)[file_posn++]; else return -1; } @@ -829,7 +829,7 @@ readChunk (RiffChunk *c) { int status; - Char_Binary n; + CBinbyte n; if ((status = dread(c, sizeof(RiffChunk), 1))) if (NAS_BIG_ENDIAN) @@ -842,7 +842,7 @@ read the wave data from a buffer in memory. */ static WaveInfo * -WaveOpenDataForReading (const Char_Binary *data, +WaveOpenDataForReading (const CBinbyte *data, int length) { RiffChunk ck; @@ -976,7 +976,7 @@ static Sound -SoundOpenDataForReading (UChar_Binary *data, +SoundOpenDataForReading (Binbyte *data, int length) { @@ -988,7 +988,7 @@ if (!(s = (Sound) malloc (sizeof (SoundRec)))) return NULL; - if ((s->formatInfo = SndOpenDataForReading ((Char_Binary *) data, length)) != NULL) + if ((s->formatInfo = SndOpenDataForReading ((CBinbyte *) data, length)) != NULL) { #if (AudioLibraryVersionMajor >= 2 ) && (AudioLibraryVersionMinor >= 3) if ((toProc = SoundFileGetProc(SoundFileFormatSnd, @@ -1009,7 +1009,7 @@ return NULL; } } - else if ((s->formatInfo = WaveOpenDataForReading ((Char_Binary *) data, length)) != NULL) + else if ((s->formatInfo = WaveOpenDataForReading ((CBinbyte *) data, length)) != NULL) { #if (AudioLibraryVersionMajor >= 2 ) && (AudioLibraryVersionMinor >= 3) if ((toProc = SoundFileGetProc(SoundFileFormatWave, diff --text -u 'xemacs-21.5.18/src/native-gtk-toolbar.c' 'xemacs-21.5.19/src/native-gtk-toolbar.c' Index: ./src/native-gtk-toolbar.c --- ./src/native-gtk-toolbar.c Tue Sep 21 04:19:52 2004 +++ ./src/native-gtk-toolbar.c Tue Jan 25 08:34:04 2005 @@ -49,7 +49,7 @@ (frame)->right_toolbar_was_visible = flag; \ break; \ default: \ - abort (); \ + ABORT (); \ } \ } while (0) diff --text -u 'xemacs-21.5.18/src/nt.c' 'xemacs-21.5.19/src/nt.c' Index: ./src/nt.c --- ./src/nt.c Tue Sep 21 04:19:53 2004 +++ ./src/nt.c Fri Jan 28 11:36:25 2005 @@ -1,6 +1,6 @@ /* Utility and Unix shadow routines under MS Windows (WIN32_NATIVE defined). Copyright (C) 1994, 1995 Free Software Foundation, Inc. - Copyright (C) 2000, 2001, 2002 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -30,7 +30,7 @@ incomplete synching, so beware.) Synched (completely!) with Emacs 20.6 by Ben Wing, 6-23-00. Largely rewritten by Ben Wing for XEmacs Mule support. - Synched (completely!) with Emacs 21.1.103 by Ben Wing, 6-13-01. + Synched (completely!) with Emacs 21.0.103 by Ben Wing, 6-13-01. */ /* This file Mule-ized by Ben Wing, 6-23-00. */ @@ -295,7 +295,7 @@ if (qxestrpbrk (name, "*?|<>\"")) return 0; - C_STRING_TO_TSTR (name, nameext); + PATHNAME_CONVERT_OUT (name, nameext); dir_handle = qxeFindFirstFile (nameext, &find_data); if (dir_handle != INVALID_HANDLE_VALUE) { @@ -389,7 +389,7 @@ if (qxeRegQueryValueEx (hrootkey, keyext, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS - && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL + && (lpvalue = xnew_array (BYTE, cbData)) != NULL && qxeRegQueryValueEx (hrootkey, keyext, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS) return (lpvalue); @@ -407,7 +407,7 @@ if (qxeRegQueryValueEx (hrootkey, keyext, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS && - (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL && + (lpvalue = xnew_array (BYTE, cbData)) != NULL && qxeRegQueryValueEx (hrootkey, keyext, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS) return (lpvalue); @@ -433,7 +433,7 @@ LPBYTE lpval; DWORD dwType; - static Char_ASCII *env_vars[] = + static Ascbyte *env_vars[] = { "HOME", "EMACSLOADPATH", @@ -483,7 +483,7 @@ Charcount cch; cch = qxeExpandEnvironmentStrings ((Extbyte *) lpval, buf, 0); - buf = (Extbyte *) ALLOCA (cch * XETCHAR_SIZE); + buf = alloca_extbytes (cch * XETCHAR_SIZE); qxeExpandEnvironmentStrings ((Extbyte *) lpval, buf, cch); TSTR_TO_C_STRING (buf, envval); eputenv (env_vars[i], (CIbyte *) envval); @@ -510,17 +510,14 @@ The same applies to COMSPEC. */ { - Lisp_Object tail; - - EXTERNAL_LIST_LOOP (tail, Vprocess_environment) + EXTERNAL_LIST_LOOP_2 (str, Vprocess_environment) { - Lisp_Object str = XCAR (tail); if (STRINGP (str)) { Ibyte *dat = XSTRING_DATA (str); - if (qxestrncasecmp_c (dat, "PATH=", 5) == 0) + if (qxestrncasecmp_ascii (dat, "PATH=", 5) == 0) memcpy (dat, "PATH=", 5); - else if (qxestrncasecmp_c (dat, "COMSPEC=", 8) == 0) + else if (qxestrncasecmp_ascii (dat, "COMSPEC=", 8) == 0) memcpy (dat, "COMSPEC=", 8); } } @@ -666,7 +663,7 @@ Ibyte drive[3] = { root_dir[0], ':' }; Extbyte *driveext; - C_STRING_TO_TSTR (drive, driveext); + PATHNAME_CONVERT_OUT (drive, driveext); if (qxeWNetGetConnection (driveext, remote_name, sizeof (remote_name) / XETCHAR_SIZE) == NO_ERROR) @@ -685,7 +682,7 @@ Extbyte type[256 * MAX_XETCHAR_SIZE]; Extbyte *rootdirext; - C_STRING_TO_TSTR (root_dir, rootdirext); + PATHNAME_CONVERT_OUT (root_dir, rootdirext); /* Info is not cached, or is stale. */ if (!qxeGetVolumeInformation (rootdirext, @@ -700,7 +697,7 @@ entry if present. */ if (info == NULL) { - info = (volume_info_data *) xmalloc (sizeof (volume_info_data)); + info = xnew (volume_info_data); add_volume_info (root_dir, info); } else @@ -727,7 +724,7 @@ { /* We probably only need a couple of bytes, but let's be generous in case this function gets changed */ - Ibyte *temp = alloca_array (Ibyte, qxestrlen (name) + 10); + Ibyte *temp = alloca_ibytes (qxestrlen (name) + 10); Ibyte *rootname = NULL; /* default to current volume */ volume_info_data *info; @@ -781,10 +778,10 @@ mswindows_is_executable (const Ibyte *name) { Ibyte *p = qxestrrchr (name, '.'); - return (p != NULL && (qxestrcasecmp_c (p, ".exe") == 0 || - qxestrcasecmp_c (p, ".com") == 0 || - qxestrcasecmp_c (p, ".bat") == 0 || - qxestrcasecmp_c (p, ".cmd") == 0)); + return (p != NULL && (qxestrcasecmp_ascii (p, ".exe") == 0 || + qxestrcasecmp_ascii (p, ".com") == 0 || + qxestrcasecmp_ascii (p, ".bat") == 0 || + qxestrcasecmp_ascii (p, ".cmd") == 0)); } /* Emulate the Unix directory procedures opendir, closedir, @@ -872,16 +869,16 @@ { DECLARE_EISTRING (filename); Ichar lastch; + Extbyte *fileext; eicpy_rawz (filename, dir_pathname); lastch = eigetch_char (filename, eicharlen (filename) - 1); if (!IS_DIRECTORY_SEP (lastch)) eicat_ch (filename, '\\'); eicat_ch (filename, '*'); - eito_external (filename, Qmswindows_tstr); + PATHNAME_CONVERT_OUT (eidata (filename), fileext); - dir_find_handle = qxeFindFirstFile (eiextdata (filename), - &dir_find_data); + dir_find_handle = qxeFindFirstFile (fileext, &dir_find_data); if (dir_find_handle == INVALID_HANDLE_VALUE) return NULL; @@ -905,6 +902,33 @@ DECLARE_EISTRING (found); Bytecount namlen; + if (mswindows_shortcuts_are_symlinks) + { + int len = qxestrlen (val); + if (len > 4 && !qxestrcasecmp_ascii (val + len - 4, ".LNK")) + { + /* If we've found a valid link, then chop off the .LNK ending */ + DECLARE_EISTRING (linkname); + Ichar lastch; + Ibyte *resolved; + + /* First check if link is valid */ + PATHNAME_RESOLVE_LINKS (dir_pathname, resolved); + eicpy_rawz (linkname, resolved); + lastch = eigetch_char (linkname, eicharlen (linkname) - 1); + if (!IS_DIRECTORY_SEP (lastch)) + eicat_ch (linkname, '\\'); + eicat_rawz (linkname, val); + resolved = mswindows_read_link (eidata (linkname)); + if (resolved) + { + xfree (resolved, Ibyte *); + len -= 4; + val[len] = '\0'; + } + } + } + eicpy_rawz (found, val); if (need_to_free) xfree (val, Ibyte *); @@ -933,7 +957,7 @@ nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER; nr.dwUsage = RESOURCEUSAGE_CONTAINER; nr.lpLocalName = NULL; - C_STRING_TO_TSTR (path, nr.lpRemoteName); + PATHNAME_CONVERT_OUT (path, nr.lpRemoteName); nr.lpComment = NULL; nr.lpProvider = NULL; @@ -1026,7 +1050,7 @@ { Extbyte *pathext; - C_STRING_TO_TSTR (path, pathext); + PATHNAME_CONVERT_OUT (path, pathext); if ((attributes = qxeGetFileAttributes (pathext)) == -1) { /* Should try mapping GetLastError to errno; for now just indicate @@ -1069,7 +1093,7 @@ return -1; } - C_STRING_TO_TSTR (old, oldext); + PATHNAME_CONVERT_OUT (old, oldext); fileh = qxeCreateFile (oldext, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (fileh != INVALID_HANDLE_VALUE) @@ -1087,12 +1111,12 @@ struct { WIN32_STREAM_ID wid; - WCHAR wbuffer[MAX_PATH]; /* extra space for link name */ + WCHAR wbuffer[_MAX_PATH]; /* extra space for link name */ } data; TO_EXTERNAL_FORMAT (C_STRING, new, ALLOCA, (newuni, wlen), Qmswindows_unicode); - if (wlen / sizeof (WCHAR) < MAX_PATH) + if (wlen / sizeof (WCHAR) < _MAX_PATH) { LPVOID context = NULL; DWORD wbytes = 0; @@ -1178,8 +1202,8 @@ seems to make the second rename work properly. */ qxesprintf (p, "_.%s.%u", o, i); i++; - C_STRING_TO_EXTERNAL (oldname, oldext, Qfile_name); - C_STRING_TO_EXTERNAL (temp, tempext, Qfile_name); + PATHNAME_CONVERT_OUT (oldname, oldext); + PATHNAME_CONVERT_OUT (temp, tempext); result = rename (oldext, tempext); } /* This loop must surely terminate! */ @@ -1201,15 +1225,28 @@ { Extbyte *newext, *tempext; - C_STRING_TO_EXTERNAL (newname, newext, Qfile_name); - C_STRING_TO_EXTERNAL (temp, tempext, Qfile_name); - result = rename (tempext, newext); - - if (result < 0 - && (errno == EEXIST || errno == EACCES) - && _chmod (newext, 0666) == 0 - && _unlink (newext) == 0) - result = rename (tempext, newext); + PATHNAME_CONVERT_OUT (newname, newext); + PATHNAME_CONVERT_OUT (temp, tempext); + if (XEUNICODE_P) + { + result = _wrename ((const wchar_t *) tempext, + (const wchar_t *) newext); + if (result < 0 + && (errno == EEXIST || errno == EACCES) + && _wchmod ((const wchar_t *) newext, 0666) == 0 + && _wunlink ((const wchar_t *) newext) == 0) + result = _wrename ((const wchar_t *) tempext, + (const wchar_t *) newext); + } + else + { + result = rename (tempext, newext); + if (result < 0 + && (errno == EEXIST || errno == EACCES) + && _chmod (newext, 0666) == 0 + && _unlink (newext) == 0) + result = rename (tempext, newext); + } } return result; @@ -1220,10 +1257,18 @@ { Extbyte *pathout; - C_STRING_TO_EXTERNAL (path, pathout, Qfile_name); + PATHNAME_CONVERT_OUT (path, pathout); /* On Unix, unlink works without write permission. */ - _chmod (pathout, 0666); - return _unlink (pathout); + if (XEUNICODE_P) + { + _wchmod ((const wchar_t *) pathout, 0666); + return _wunlink ((const wchar_t *) pathout); + } + else + { + _chmod (pathout, 0666); + return _unlink (pathout); + } } static FILETIME utc_base_ft; @@ -1513,6 +1558,8 @@ { if (!IS_DIRECTORY_SEP (name[len-1])) qxestrcat (name, (Ibyte *) "\\"); + /* File has already been resolved and we don't want to do it again + in case of lstat() */ C_STRING_TO_TSTR (name, nameext); if (qxeGetDriveType (nameext) < 2) { @@ -1577,13 +1624,15 @@ else { if (!NILP (Vmswindows_get_true_file_attributes)) + /* File has already been resolved and we don't want to do it again + in case of lstat() */ C_STRING_TO_TSTR (name, nameext); if (!NILP (Vmswindows_get_true_file_attributes) /* No access rights required to get info. */ && (fh = qxeCreateFile (nameext, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) { - /* This is more accurate in terms of gettting the correct number + /* This is more accurate in terms of getting the correct number of links, but is quite slow (it is noticable when Emacs is making a list of file name completions). */ BY_HANDLE_FILE_INFORMATION info; @@ -1626,6 +1675,22 @@ buf->st_nlink = 1; fake_inode = 0; } + + if (mswindows_shortcuts_are_symlinks && + buf->st_mode == _S_IFREG) + { + len = qxestrlen (name); + if (len > 4 && !qxestrcasecmp_ascii (name + len - 4, ".LNK")) + { + /* check if link is valid */ + Ibyte *resolved = mswindows_read_link (name); + if (resolved) + { + xfree (resolved, Ibyte *); + buf->st_mode = S_IFLNK; + } + } + } } SetErrorMode (errm); @@ -1701,7 +1766,7 @@ times = &deftime; } - LISP_STRING_TO_TSTR (path, filename); + LISP_PATHNAME_CONVERT_OUT (path, filename); /* APA: SetFileTime fails to set mtime correctly (always 1-Jan-1970) */ #if 0 /* Need write access to set times. */ @@ -1771,7 +1836,7 @@ DWORD size, upper_size; Extbyte *fileext; - C_STRING_TO_TSTR (filename, fileext); + PATHNAME_CONVERT_OUT (filename, fileext); file = qxeCreateFile (fileext, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); @@ -1807,7 +1872,7 @@ void *file_base; Extbyte *fileext; - C_STRING_TO_TSTR (filename, fileext); + PATHNAME_CONVERT_OUT (filename, fileext); file = qxeCreateFile (fileext, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); @@ -1881,10 +1946,10 @@ p = qxestrrchr (filename, '.'); /* We can only identify DOS .com programs from the extension. */ - if (p && qxestrcasecmp_c (p, ".com") == 0) + if (p && qxestrcasecmp_ascii (p, ".com") == 0) *is_dos_app = TRUE; - else if (p && (qxestrcasecmp_c (p, ".bat") == 0 || - qxestrcasecmp_c (p, ".cmd") == 0)) + else if (p && (qxestrcasecmp_ascii (p, ".bat") == 0 || + qxestrcasecmp_ascii (p, ".cmd") == 0)) { /* A DOS shell script - it appears that CreateProcess is happy to accept this (somewhat surprisingly); presumably it looks at @@ -2001,7 +2066,7 @@ */ (filename)) { - Extbyte shortname[MAX_PATH * MAX_XETCHAR_SIZE]; + Extbyte shortname[PATH_MAX_EXTERNAL]; Extbyte *fileext; Ibyte *shortint; @@ -2010,7 +2075,7 @@ /* first expand it. */ filename = Fexpand_file_name (filename, Qnil); - LISP_STRING_TO_TSTR (filename, fileext); + LISP_PATHNAME_CONVERT_OUT (filename, fileext); /* luckily, this returns the short version of each element in the path. */ if (qxeGetShortPathName (fileext, shortname, sizeof (shortname) / XETCHAR_SIZE) == 0) @@ -2124,7 +2189,7 @@ { Extbyte *driveext; - C_STRING_TO_TSTR (drive, driveext); + PATHNAME_CONVERT_OUT (drive, driveext); /* Record if this drive letter refers to a fixed drive. */ fixed_drives[DRIVE_INDEX (*drive)] = diff --text -u 'xemacs-21.5.18/src/ntheap.c' 'xemacs-21.5.19/src/ntheap.c' Index: ./src/ntheap.c --- ./src/ntheap.c Sat Mar 1 16:25:36 2003 +++ ./src/ntheap.c Fri Nov 5 08:06:44 2004 @@ -52,39 +52,39 @@ } /* Round ADDRESS up to be aligned with ALIGN. */ -UChar_Binary * -round_to_next (UChar_Binary *address, unsigned long align) +URawbyte * +round_to_next (URawbyte *address, unsigned long align) { unsigned long tmp; tmp = (unsigned long) address; tmp = (tmp + align - 1) / align; - return (UChar_Binary *) (tmp * align); + return (URawbyte *) (tmp * align); } /* Info for keeping track of our heap. */ -UChar_Binary *data_region_base = UNINIT_PTR; -UChar_Binary *data_region_end = UNINIT_PTR; -UChar_Binary *real_data_region_end = UNINIT_PTR; +URawbyte *data_region_base = UNINIT_PTR; +URawbyte *data_region_end = UNINIT_PTR; +URawbyte *real_data_region_end = UNINIT_PTR; unsigned long data_region_size = UNINIT_LONG; unsigned long reserved_heap_size = UNINIT_LONG; /* The start of the data segment. */ -UChar_Binary * +URawbyte * get_data_start (void) { return data_region_base; } /* The end of the data segment. */ -UChar_Binary * +URawbyte * get_data_end (void) { return data_region_end; } -static UChar_Binary * +static URawbyte * allocate_heap (void) { /* The base address for our GNU malloc heap is chosen in conjunction @@ -148,7 +148,7 @@ PAGE_NOACCESS); #endif - return (UChar_Binary *) ptr; + return (URawbyte *) ptr; } @@ -177,7 +177,7 @@ if (size < 0) { int new_size; - UChar_Binary *new_data_region_end; + URawbyte *new_data_region_end; size = -size; @@ -188,7 +188,7 @@ /* We can only decommit full pages, so allow for partial deallocation [cga]. */ new_data_region_end = (data_region_end - size); - new_data_region_end = (UChar_Binary *) + new_data_region_end = (URawbyte *) ((long) (new_data_region_end + syspage_mask) & ~syspage_mask); new_size = real_data_region_end - new_data_region_end; real_data_region_end = new_data_region_end; @@ -217,7 +217,7 @@ /* We really only commit full pages, so record where the real end of committed memory is [cga]. */ - real_data_region_end = (UChar_Binary *) + real_data_region_end = (URawbyte *) ((long) (data_region_end + syspage_mask) & ~syspage_mask); } @@ -239,8 +239,8 @@ void *tmp; MEMORY_BASIC_INFORMATION info; DWORD size; - UChar_Binary *base = get_heap_end (); - UChar_Binary *end = + URawbyte *base = get_heap_end (); + URawbyte *end = base + get_reserved_heap_size () - get_committed_heap_size (); VirtualQuery (base, &info, sizeof (info)); if (info.State != MEM_FREE) diff --text -u 'xemacs-21.5.18/src/ntplay.c' 'xemacs-21.5.19/src/ntplay.c' Index: ./src/ntplay.c --- ./src/ntplay.c Tue Sep 21 04:19:53 2004 +++ ./src/ntplay.c Fri Jan 28 11:36:26 2005 @@ -31,32 +31,30 @@ #include "sysfile.h" -static int play_sound_data_1 (UChar_Binary *data, int length, +static int play_sound_data_1 (Binbyte *data, int length, int volume, int convert); void -play_sound_file (Extbyte *sound_file, int UNUSED (volume)) +nt_play_sound_file (Lisp_Object path, int UNUSED (volume)) { DWORD flags = SND_ASYNC | SND_NODEFAULT | SND_FILENAME; - Lisp_Object fname = - Ffile_name_nondirectory (build_tstr_string (sound_file)); + Lisp_Object fname = Ffile_name_nondirectory (path); Extbyte *fnameext; - CHECK_STRING (fname); LISP_STRING_TO_TSTR (fname, fnameext); if (qxeSearchPath (NULL, fnameext, NULL, 0, NULL, NULL) == 0) { /* file isn't in the path so read it as data */ int size; - UChar_Binary *data; - int ofd = qxe_open (XSTRING_DATA (fname), O_RDONLY | OPEN_BINARY, 0); + Binbyte *data; + int ofd = qxe_open (XSTRING_DATA (path), O_RDONLY | OPEN_BINARY, 0); - if (ofd <0) + if (ofd < 0) return; size = lseek (ofd, 0, SEEK_END); - data = (UChar_Binary *) xmalloc (size); + data = xnew_binbytes (size); lseek (ofd, 0, SEEK_SET); if (!data) @@ -68,7 +66,7 @@ if (retry_read (ofd, data, size) != size) { retry_close (ofd); - xfree (data, UChar_Binary *); + xfree (data, Binbyte *); return; } retry_close (ofd); @@ -82,21 +80,21 @@ /* mswindows can't cope with playing a sound from alloca space so we have to convert if necessary */ static int -play_sound_data_1 (UChar_Binary *data, int length, int UNUSED (volume), +play_sound_data_1 (Binbyte *data, int length, int UNUSED (volume), int convert_to_malloc) { DWORD flags = SND_ASYNC | SND_MEMORY | SND_NODEFAULT; - static UChar_Binary *sound_data = 0; + static Binbyte *sound_data = 0; if (sound_data) { qxePlaySound (NULL, NULL, flags); - xfree (sound_data, UChar_Binary *); + xfree (sound_data, Binbyte *); sound_data = 0; } if (convert_to_malloc) { - sound_data = (UChar_Binary *) xmalloc (length); + sound_data = xnew_binbytes (length); memcpy (sound_data, data, length); } else @@ -109,7 +107,7 @@ } int -play_sound_data (UChar_Binary *data, int length, int volume) +play_sound_data (Binbyte *data, int length, int volume) { return play_sound_data_1 (data, length, volume, TRUE); } diff --text -u 'xemacs-21.5.18/src/number-gmp.c' 'xemacs-21.5.19/src/number-gmp.c' Index: ./src/number-gmp.c --- ./src/number-gmp.c Tue Sep 21 04:19:53 2004 +++ ./src/number-gmp.c Fri Nov 5 08:06:45 2004 @@ -91,7 +91,8 @@ void init_number_gmp () { - mp_set_memory_functions ((void *(*) (size_t))xmalloc, gmp_realloc, gmp_free); + mp_set_memory_functions ((void *(*) (size_t)) xmalloc, gmp_realloc, + gmp_free); /* The smallest number that is printed without exponents */ mpf_init_set_d (float_print_min, 0.001); diff --text -u 'xemacs-21.5.18/src/number-gmp.h' 'xemacs-21.5.19/src/number-gmp.h' Index: ./src/number-gmp.h --- ./src/number-gmp.h Tue Sep 21 04:19:53 2004 +++ ./src/number-gmp.h Fri Feb 4 01:14:07 2005 @@ -152,6 +152,7 @@ #define ratio_set_bigfloat(r,f) mpq_set_f (r, f) #define ratio_set_long_ulong(r,num,den) mpq_set_si (r, num, den) #define ratio_set_ulong_ulong(r,num,den) mpq_set_ui (r, num, den) +/* FIXME: Why does this canonicalize, but the previous 2 don't? */ #define ratio_set_bignum_bignum(r,num,den) do { \ mpz_set (mpq_numref (r), num); \ mpz_set (mpq_denref (r), den); \ diff --text -u 'xemacs-21.5.18/src/number.c' 'xemacs-21.5.19/src/number.c' Index: ./src/number.c --- ./src/number.c Tue Sep 21 04:19:54 2004 +++ ./src/number.c Fri Feb 4 01:14:07 2005 @@ -64,12 +64,43 @@ return bignum_hashcode (XBIGNUM_DATA (obj)); } +static void +bignum_convert (const void *object, void **data, Bytecount *size) +{ + CIbyte *bstr = bignum_to_string (*(bignum *)object, 10); + *data = bstr; + *size = strlen(bstr)+1; +} + +static void +bignum_convfree (const void * UNUSED (object), void *data, + Bytecount UNUSED (size)) +{ + xfree (data, void *); +} + +static void * +bignum_deconvert (void *object, void *data, Bytecount UNUSED (size)) +{ + bignum *b = (bignum *) object; + bignum_init(*b); + bignum_set_string(*b, (const char *) data, 10); + return object; +} + +static const struct opaque_convert_functions bignum_opc = { + bignum_convert, + bignum_convfree, + bignum_deconvert +}; + static const struct memory_description bignum_description[] = { - { XD_OPAQUE_PTR, offsetof (Lisp_Bignum, data) }, + { XD_OPAQUE_DATA_CONVERTIBLE, offsetof (Lisp_Bignum, data), + 0, { &bignum_opc }, XD_FLAG_NO_KKCC }, { XD_END } }; -DEFINE_BASIC_LRECORD_IMPLEMENTATION ("bignum", bignum, 0, 0, bignum_print, +DEFINE_BASIC_LRECORD_IMPLEMENTATION ("bignum", bignum, 1, 0, bignum_print, 0, bignum_equal, bignum_hash, bignum_description, Lisp_Bignum); @@ -401,7 +432,7 @@ return BIGFLOAT_T; #endif /* Catch unintentional bad uses of this function */ - abort (); + ABORT (); /* NOTREACHED */ return FIXNUM_T; } @@ -425,7 +456,7 @@ number = make_int (marker_position (number)); /* Note that CHECK_NUMBER ensures that NUMBER is a supported type. Hence, - we abort() in the #else sections below, because it shouldn't be possible + we ABORT() in the #else sections below, because it shouldn't be possible to arrive there. */ CHECK_NUMBER (number); current_type = get_number_type (number); @@ -440,13 +471,13 @@ #ifdef HAVE_BIGNUM return make_bignum (XREALINT (number)); #else - abort (); + ABORT (); #endif /* HAVE_BIGNUM */ case RATIO_T: #ifdef HAVE_RATIO return make_ratio (XREALINT (number), 1UL); #else - abort (); + ABORT (); #endif /* HAVE_RATIO */ case FLOAT_T: return make_float (XREALINT (number)); @@ -454,7 +485,7 @@ #ifdef HAVE_BIGFLOAT return make_bigfloat (XREALINT (number), precision); #else - abort (); + ABORT (); #endif /* HAVE_BIGFLOAT */ } case BIGNUM_T: @@ -470,7 +501,7 @@ bignum_set_long (scratch_bignum, 1L); return make_ratio_bg (XBIGNUM_DATA (number), scratch_bignum); #else - abort (); + ABORT (); #endif /* HAVE_RATIO */ case FLOAT_T: return make_float (bignum_to_double (XBIGNUM_DATA (number))); @@ -483,11 +514,11 @@ return temp; } #else - abort (); + ABORT (); #endif /* HAVE_BIGFLOAT */ } #else - abort (); + ABORT (); #endif /* HAVE_BIGNUM */ case RATIO_T: #ifdef HAVE_RATIO @@ -514,11 +545,11 @@ return temp; } #else - abort (); + ABORT (); #endif /* HAVE_BIGFLOAT */ } #else - abort (); + ABORT (); #endif /* HAVE_RATIO */ case FLOAT_T: switch (type) @@ -530,14 +561,14 @@ bignum_set_double (scratch_bignum, XFLOAT_DATA (number)); return make_bignum_bg (scratch_bignum); #else - abort (); + ABORT (); #endif /* HAVE_BIGNUM */ case RATIO_T: #ifdef HAVE_RATIO ratio_set_double (scratch_ratio, XFLOAT_DATA (number)); return make_ratio_rt (scratch_ratio); #else - abort (); + ABORT (); #endif /* HAVE_RATIO */ case FLOAT_T: return number; @@ -547,7 +578,7 @@ bigfloat_set_double (scratch_bigfloat, XFLOAT_DATA (number)); return make_bigfloat_bf (scratch_bigfloat); #else - abort (); + ABORT (); #endif /* HAVE_BIGFLOAT */ } case BIGFLOAT_T: @@ -561,14 +592,14 @@ bignum_set_bigfloat (scratch_bignum, XBIGFLOAT_DATA (number)); return make_bignum_bg (scratch_bignum); #else - abort (); + ABORT (); #endif /* HAVE_BIGNUM */ case RATIO_T: #ifdef HAVE_RATIO ratio_set_bigfloat (scratch_ratio, XBIGFLOAT_DATA (number)); return make_ratio_rt (scratch_ratio); #else - abort (); + ABORT (); #endif case FLOAT_T: return make_float (bigfloat_to_double (XBIGFLOAT_DATA (number))); @@ -577,10 +608,10 @@ return number; } #else - abort (); + ABORT (); #endif /* HAVE_BIGFLOAT */ } - abort (); + ABORT (); /* NOTREACHED */ return Qzero; } @@ -770,13 +801,8 @@ #ifdef HAVE_BIGFLOAT #ifdef HAVE_BIGNUM - /* Uncomment the next two lines and remove the line below them when dumping - bignums becomes possible. */ - /* Vbigfloat_max_prec = make_bignum (0L); bignum_set_ulong (XBIGNUM_DATA (Vbigfloat_max_prec), ULONG_MAX); - */ - Vbigfloat_max_prec = make_int (EMACS_INT_MAX); #else Vbigfloat_max_prec = make_int (EMACS_INT_MAX); #endif diff --text -u 'xemacs-21.5.18/src/objects-gtk.c' 'xemacs-21.5.19/src/objects-gtk.c' Index: ./src/objects-gtk.c --- ./src/objects-gtk.c Tue Sep 21 04:19:54 2004 +++ ./src/objects-gtk.c Fri Jan 28 11:58:51 2005 @@ -178,7 +178,7 @@ COLOR_INSTANCE_GTK_COLOR (c2))); } -static unsigned long +static Hashcode gtk_color_instance_hash (struct Lisp_Color_Instance *c, int UNUSED (depth)) { return (gdk_color_hash (COLOR_INSTANCE_GTK_COLOR (c), NULL)); @@ -206,6 +206,14 @@ return (1); } +static Lisp_Object +gtk_color_list (void) +{ + /* #### BILL!!! + Is this correct? */ + return call0 (intern ("x-color-list-internal")); +} + /************************************************************************/ /* font instances */ @@ -330,7 +338,7 @@ /* Forward declarations for X specific functions at the end of the file */ Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp); -static Lisp_Object __gtk_list_fonts_internal (const char *pattern); +static Lisp_Object __gtk_font_list_internal (const char *pattern); static Lisp_Object gtk_font_instance_truename (struct Lisp_Font_Instance *f, @@ -361,14 +369,14 @@ } static Lisp_Object -gtk_list_fonts (Lisp_Object pattern, Lisp_Object UNUSED (device), +gtk_font_list (Lisp_Object pattern, Lisp_Object UNUSED (device), Lisp_Object UNUSED (maxnumber)) { const char *patternext; TO_EXTERNAL_FORMAT (LISP_STRING, pattern, C_STRING_ALLOCA, patternext, Qbinary); - return (__gtk_list_fonts_internal (patternext)); + return (__gtk_font_list_internal (patternext)); } #ifdef MULE @@ -454,13 +462,14 @@ CONSOLE_HAS_METHOD (gtk, color_instance_hash); CONSOLE_HAS_METHOD (gtk, color_instance_rgb_components); CONSOLE_HAS_METHOD (gtk, valid_color_name_p); + CONSOLE_HAS_METHOD (gtk, color_list); CONSOLE_HAS_METHOD (gtk, initialize_font_instance); CONSOLE_HAS_METHOD (gtk, print_font_instance); CONSOLE_HAS_METHOD (gtk, finalize_font_instance); CONSOLE_HAS_METHOD (gtk, font_instance_truename); CONSOLE_HAS_METHOD (gtk, font_instance_properties); - CONSOLE_HAS_METHOD (gtk, list_fonts); + CONSOLE_HAS_METHOD (gtk, font_list); #ifdef MULE CONSOLE_HAS_METHOD (gtk, find_charset_font); CONSOLE_HAS_METHOD (gtk, font_spec_matches_charset); @@ -587,7 +596,7 @@ return (font_name); } -static Lisp_Object __gtk_list_fonts_internal (const char *pattern) +static Lisp_Object __gtk_font_list_internal (const char *pattern) { char **names; int count = 0; diff --text -u 'xemacs-21.5.18/src/objects-msw.c' 'xemacs-21.5.19/src/objects-msw.c' Index: ./src/objects-msw.c --- ./src/objects-msw.c Tue Sep 21 04:19:54 2004 +++ ./src/objects-msw.c Fri Jan 28 11:58:51 2005 @@ -2,7 +2,7 @@ Copyright (C) 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995 Tinker Systems. - Copyright (C) 1995, 1996, 2000, 2001, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004 Ben Wing. Copyright (C) 1995 Sun Microsystems, Inc. Copyright (C) 1997 Jonathan Harris. @@ -50,7 +50,7 @@ typedef struct colormap_t { - const Char_ASCII *name; + const Ascbyte *name; COLORREF colorref; } colormap_t; @@ -728,7 +728,7 @@ typedef struct fontmap_t { - const Char_ASCII *name; + const Ascbyte *name; int value; } fontmap_t; @@ -964,7 +964,7 @@ return (PALETTERGB (r, g, b)); } } - else if (!qxestrncmp_c (name, "rgb:", 4)) + else if (!qxestrncmp_ascii (name, "rgb:", 4)) { unsigned int r, g, b; @@ -990,7 +990,7 @@ } else if (*name) /* Can't be an empty string */ { - Ibyte *nospaces = (Ibyte *) ALLOCA (qxestrlen (name) + 1); + Ibyte *nospaces = alloca_ibytes (qxestrlen (name) + 1); Ibyte *c = nospaces; while (*name) if (*name != ' ') @@ -1000,7 +1000,7 @@ *c = '\0'; for (i = 0; i < countof (mswindows_X_color_map); i++) - if (!qxestrcasecmp_c (nospaces, mswindows_X_color_map[i].name)) + if (!qxestrcasecmp_ascii (nospaces, mswindows_X_color_map[i].name)) return (mswindows_X_color_map[i].colorref); } return (COLORREF) -1; @@ -1010,7 +1010,7 @@ mswindows_color_to_string (COLORREF color) { int i; - Char_ASCII buf[8]; + Ascbyte buf[8]; COLORREF pcolor = PALETTERGB (GetRValue (color), GetGValue (color), GetBValue (color)); @@ -1057,14 +1057,14 @@ return 0; } else if (fontname) - qxestrcat_c (qxestrcat (fontname, c1), ":"); + qxestrcat_ascii (qxestrcat (fontname, c1), ":"); } else if (fontname) { if (c2 && c2[0] != '\0') - qxestrcat_c (qxestrcat (fontname, c2), ":"); + qxestrcat_ascii (qxestrcat (fontname, c2), ":"); else - qxestrcat_c (fontname, ":"); + qxestrcat_ascii (fontname, ":"); } if (e1) *(e1++) = ':'; @@ -1134,7 +1134,7 @@ for (i = 0; i < countof (charset_map); i++) if (lpelfe->elfLogFont.lfCharSet == charset_map[i].value) { - qxestrcat_c (fontname, charset_map[i].name); + qxestrcat_ascii (fontname, charset_map[i].name); break; } if (i == countof (charset_map)) @@ -1204,8 +1204,8 @@ c1 = qxestrrchr (font1, ':'); c2 = qxestrrchr (font2, ':'); - t1 = !qxestrcasecmp_c (c1 + 1, "western"); - t2 = !qxestrcasecmp_c (c2 + 1, "western"); + t1 = !qxestrcasecmp_ascii (c1 + 1, "western"); + t2 = !qxestrcasecmp_ascii (c2 + 1, "western"); if (t1 && !t2) return 1; @@ -1243,8 +1243,8 @@ return 1; } - t1 = !qxestrncasecmp_c (font1, "courier new:", 12); - t2 = !qxestrncasecmp_c (font2, "courier new:", 12); + t1 = !qxestrncasecmp_ascii (font1, "courier new:", 12); + t2 = !qxestrncasecmp_ascii (font2, "courier new:", 12); if (t1 && !t2) return 1; @@ -1390,7 +1390,7 @@ COLOR_INSTANCE_MSWINDOWS_COLOR (c2)); } -static unsigned long +static Hashcode mswindows_color_instance_hash (Lisp_Color_Instance *c, int UNUSED (depth)) { return (unsigned long) COLOR_INSTANCE_MSWINDOWS_COLOR (c); @@ -1492,7 +1492,7 @@ C_STRING_TO_TSTR (fontname, extfontname); if (logfont) { - xetcsncpy ((Extbyte *) logfont->lfFaceName, extfontname, + qxetcsncpy ((Extbyte *) logfont->lfFaceName, extfontname, LF_FACESIZE - 1); logfont->lfFaceName[LF_FACESIZE - 1] = 0; } @@ -1500,7 +1500,7 @@ /* weight */ if (fields < 2) - qxestrcpy_c (weight, fontweight_map[0].name); + qxestrcpy_ascii (weight, fontweight_map[0].name); /* Maybe split weight into weight and style */ if ((c = qxestrchr (weight, ' '))) @@ -1512,7 +1512,7 @@ style = NULL; for (i = 0; i < countof (fontweight_map); i++) - if (!qxestrcasecmp_c (weight, fontweight_map[i].name)) + if (!qxestrcasecmp_ascii (weight, fontweight_map[i].name)) { if (logfont) logfont->lfWeight = fontweight_map[i].value; @@ -1537,7 +1537,7 @@ if (style) { /* #### what about oblique? */ - if (qxestrcasecmp_c (style, "italic") == 0) + if (qxestrcasecmp_ascii (style, "italic") == 0) { if (logfont) logfont->lfItalic = TRUE; @@ -1557,7 +1557,7 @@ else if (logfont) logfont->lfItalic = FALSE; - if (fields < 3 || !qxestrcmp_c (points, "")) + if (fields < 3 || !qxestrcmp_ascii (points, "")) ; else if (points[0] == '0' || qxestrspn (points, "0123456789") < qxestrlen (points)) @@ -1601,9 +1601,9 @@ else effects2 = NULL; - if (qxestrcasecmp_c (effects, "underline") == 0) + if (qxestrcasecmp_ascii (effects, "underline") == 0) underline = TRUE; - else if (qxestrcasecmp_c (effects, "strikeout") == 0) + else if (qxestrcasecmp_ascii (effects, "strikeout") == 0) strikeout = TRUE; else { @@ -1614,9 +1614,9 @@ if (effects2 && effects2[0] != '\0') { - if (qxestrcasecmp_c (effects2, "underline") == 0) + if (qxestrcasecmp_ascii (effects2, "underline") == 0) underline = TRUE; - else if (qxestrcasecmp_c (effects2, "strikeout") == 0) + else if (qxestrcasecmp_ascii (effects2, "strikeout") == 0) strikeout = TRUE; else { @@ -1630,12 +1630,12 @@ if (underline) { if (strikeout) - qxestrcpy_c (effects, "underline strikeout"); + qxestrcpy_ascii (effects, "underline strikeout"); else - qxestrcpy_c (effects, "underline"); + qxestrcpy_ascii (effects, "underline"); } else if (strikeout) - qxestrcpy_c (effects, "strikeout"); + qxestrcpy_ascii (effects, "strikeout"); if (logfont) { @@ -1663,12 +1663,12 @@ font_instantiate() calls the devmeth find_matching_font(), which gets a truename font spec with the registry (i.e. the charset spec) filled in appropriately to the charset. */ - if (!qxestrcmp_c (charset, "")) + if (!qxestrcmp_ascii (charset, "")) ; else { for (i = 0; i < countof (charset_map); i++) - if (!qxestrcasecmp_c (charset, charset_map[i].name)) + if (!qxestrcasecmp_ascii (charset, charset_map[i].name)) { if (logfont) logfont->lfCharSet = charset_map[i].value; @@ -1926,7 +1926,7 @@ } static Lisp_Object -mswindows_list_fonts (Lisp_Object pattern, Lisp_Object device, +mswindows_font_list (Lisp_Object pattern, Lisp_Object device, Lisp_Object UNUSED (maxnumber)) { struct device *d = XDEVICE (device); @@ -1937,7 +1937,7 @@ else if (DEVICE_MSPRINTER_P (d)) font_list = DEVICE_MSPRINTER_FONTLIST (d); else - abort (); + ABORT (); LIST_LOOP (fonttail, font_list) { @@ -2001,7 +2001,7 @@ font_charset = c; /* For border-glyph use */ - if (!qxestrcasecmp_c (font_charset, "symbol")) + if (!qxestrcasecmp_ascii (font_charset, "symbol")) font_charset = (const Ibyte *) "western"; /* Get code page for the charset */ @@ -2188,7 +2188,7 @@ /* If FONT specifies a particular charset, this will only list fonts with that charset; otherwise, it will list fonts with all charsets. */ - fontlist = mswindows_list_fonts (font, device, Qnil); + fontlist = mswindows_font_list (font, device, Qnil); if (!stage) { @@ -2219,10 +2219,8 @@ /* non-methods */ /************************************************************************/ -DEFUN ("mswindows-color-list", Fmswindows_color_list, 0, 0, 0, /* -Return a list of the colors available on mswindows devices. -*/ - ()) +static Lisp_Object +mswindows_color_list (void) { Lisp_Object result = Qnil; int i; @@ -2233,7 +2231,6 @@ return Fnreverse (result); } - /************************************************************************/ /* initialization */ @@ -2242,7 +2239,6 @@ void syms_of_objects_mswindows (void) { - DEFSUBR (Fmswindows_color_list); } void @@ -2257,13 +2253,14 @@ CONSOLE_HAS_METHOD (mswindows, color_instance_hash); CONSOLE_HAS_METHOD (mswindows, color_instance_rgb_components); CONSOLE_HAS_METHOD (mswindows, valid_color_name_p); + CONSOLE_HAS_METHOD (mswindows, color_list); CONSOLE_HAS_METHOD (mswindows, initialize_font_instance); /* CONSOLE_HAS_METHOD (mswindows, mark_font_instance); */ CONSOLE_HAS_METHOD (mswindows, print_font_instance); CONSOLE_HAS_METHOD (mswindows, finalize_font_instance); CONSOLE_HAS_METHOD (mswindows, font_instance_truename); - CONSOLE_HAS_METHOD (mswindows, list_fonts); + CONSOLE_HAS_METHOD (mswindows, font_list); #ifdef MULE CONSOLE_HAS_METHOD (mswindows, font_spec_matches_charset); CONSOLE_HAS_METHOD (mswindows, find_charset_font); @@ -2280,13 +2277,14 @@ CONSOLE_INHERITS_METHOD (msprinter, mswindows, color_instance_hash); CONSOLE_INHERITS_METHOD (msprinter, mswindows, color_instance_rgb_components); CONSOLE_INHERITS_METHOD (msprinter, mswindows, valid_color_name_p); + CONSOLE_INHERITS_METHOD (msprinter, mswindows, color_list); CONSOLE_HAS_METHOD (msprinter, initialize_font_instance); /* CONSOLE_INHERITS_METHOD (msprinter, mswindows, mark_font_instance); */ CONSOLE_INHERITS_METHOD (msprinter, mswindows, print_font_instance); CONSOLE_INHERITS_METHOD (msprinter, mswindows, finalize_font_instance); CONSOLE_INHERITS_METHOD (msprinter, mswindows, font_instance_truename); - CONSOLE_INHERITS_METHOD (msprinter, mswindows, list_fonts); + CONSOLE_INHERITS_METHOD (msprinter, mswindows, font_list); #ifdef MULE CONSOLE_INHERITS_METHOD (msprinter, mswindows, font_spec_matches_charset); CONSOLE_INHERITS_METHOD (msprinter, mswindows, find_charset_font); @@ -2320,6 +2318,4 @@ make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL); staticpro (&Vfont_signature_data); #endif /* MULE */ - - reinit_vars_of_object_mswindows (); } diff --text -u 'xemacs-21.5.18/src/objects-tty.c' 'xemacs-21.5.19/src/objects-tty.c' Index: ./src/objects-tty.c --- ./src/objects-tty.c Tue Sep 21 04:19:54 2004 +++ ./src/objects-tty.c Fri Jan 28 11:58:51 2005 @@ -106,10 +106,8 @@ return Qnil; } -DEFUN ("tty-color-list", Ftty_color_list, 0, 0, 0, /* -Return a list of the registered TTY colors. -*/ - ()) +static Lisp_Object +tty_color_list (void) { Lisp_Object result = Qnil; Lisp_Object rest; @@ -213,7 +211,7 @@ COLOR_INSTANCE_TTY_SYMBOL (c2))); } -static unsigned long +static Hashcode tty_color_instance_hash (Lisp_Color_Instance *c, int UNUSED (depth)) { return LISP_HASH (COLOR_INSTANCE_TTY_SYMBOL (c)); @@ -238,7 +236,7 @@ Ibyte *str = XSTRING_DATA (name); Lisp_Object charset = Qnil; - if (qxestrncmp_c (str, "normal", 6)) + if (qxestrncmp_ascii (str, "normal", 6)) return 0; str += 6; if (*str) @@ -293,7 +291,7 @@ } static Lisp_Object -tty_list_fonts (Lisp_Object UNUSED (pattern), Lisp_Object UNUSED (device), +tty_font_list (Lisp_Object UNUSED (pattern), Lisp_Object UNUSED (device), Lisp_Object UNUSED (maxnumber)) { return list1 (build_string ("normal")); @@ -368,7 +366,6 @@ DEFSUBR (Fregister_tty_color); DEFSUBR (Funregister_tty_color); DEFSUBR (Ffind_tty_color); - DEFSUBR (Ftty_color_list); #if 0 DEFSUBR (Fset_tty_dynamic_color_specs); DEFSUBR (Ftty_dynamic_color_specs); @@ -386,12 +383,13 @@ CONSOLE_HAS_METHOD (tty, color_instance_equal); CONSOLE_HAS_METHOD (tty, color_instance_hash); CONSOLE_HAS_METHOD (tty, valid_color_name_p); + CONSOLE_HAS_METHOD (tty, color_list); CONSOLE_HAS_METHOD (tty, initialize_font_instance); CONSOLE_HAS_METHOD (tty, mark_font_instance); CONSOLE_HAS_METHOD (tty, print_font_instance); CONSOLE_HAS_METHOD (tty, finalize_font_instance); - CONSOLE_HAS_METHOD (tty, list_fonts); + CONSOLE_HAS_METHOD (tty, font_list); #ifdef MULE CONSOLE_HAS_METHOD (tty, font_spec_matches_charset); CONSOLE_HAS_METHOD (tty, find_charset_font); diff --text -u 'xemacs-21.5.18/src/objects-x.c' 'xemacs-21.5.19/src/objects-x.c' Index: ./src/objects-x.c --- ./src/objects-x.c Tue Sep 21 04:19:55 2004 +++ ./src/objects-x.c Fri Jan 28 11:58:52 2005 @@ -2,7 +2,7 @@ Copyright (C) 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995 Tinker Systems. - Copyright (C) 1995, 1996, 2000, 2001, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004 Ben Wing. Copyright (C) 1995 Sun Microsystems, Inc. This file is part of XEmacs. @@ -326,7 +326,7 @@ (color1.blue == color2.blue)); } -static unsigned long +static Hashcode x_color_instance_hash (Lisp_Color_Instance *c, int UNUSED (depth)) { XColor color = COLOR_INSTANCE_X_COLOR (c); @@ -355,6 +355,12 @@ return XParseColor (dpy, cmap, extname, &c); } +static Lisp_Object +x_color_list (void) +{ + return call0 (intern ("x-color-list-internal")); +} + /************************************************************************/ /* font instances */ @@ -652,7 +658,7 @@ if (ok) { int L = strlen (composed_name) + 1; - result = (Extbyte *) xmalloc (L); + result = xnew_extbytes (L); strncpy (result, composed_name, L); } else @@ -827,17 +833,17 @@ atom == DEVICE_XATOM_SPACING (d) || atom == DEVICE_XATOM_CHARSET_REGISTRY (d) || atom == DEVICE_XATOM_CHARSET_ENCODING (d) || - !qxestrcmp_c (name_str, "CHARSET_COLLECTIONS") || - !qxestrcmp_c (name_str, "FONTNAME_REGISTRY") || - !qxestrcmp_c (name_str, "CLASSIFICATION") || - !qxestrcmp_c (name_str, "COPYRIGHT") || - !qxestrcmp_c (name_str, "DEVICE_FONT_NAME") || - !qxestrcmp_c (name_str, "FULL_NAME") || - !qxestrcmp_c (name_str, "MONOSPACED") || - !qxestrcmp_c (name_str, "QUALITY") || - !qxestrcmp_c (name_str, "RELATIVE_SET") || - !qxestrcmp_c (name_str, "RELATIVE_WEIGHT") || - !qxestrcmp_c (name_str, "STYLE"))) + !qxestrcmp_ascii (name_str, "CHARSET_COLLECTIONS") || + !qxestrcmp_ascii (name_str, "FONTNAME_REGISTRY") || + !qxestrcmp_ascii (name_str, "CLASSIFICATION") || + !qxestrcmp_ascii (name_str, "COPYRIGHT") || + !qxestrcmp_ascii (name_str, "DEVICE_FONT_NAME") || + !qxestrcmp_ascii (name_str, "FULL_NAME") || + !qxestrcmp_ascii (name_str, "MONOSPACED") || + !qxestrcmp_ascii (name_str, "QUALITY") || + !qxestrcmp_ascii (name_str, "RELATIVE_SET") || + !qxestrcmp_ascii (name_str, "RELATIVE_WEIGHT") || + !qxestrcmp_ascii (name_str, "STYLE"))) { Extbyte *val_str = XGetAtomName (dpy, props [i].card32); @@ -853,7 +859,7 @@ } static Lisp_Object -x_list_fonts (Lisp_Object pattern, Lisp_Object device, Lisp_Object maxnumber) +x_font_list (Lisp_Object pattern, Lisp_Object device, Lisp_Object maxnumber) { Extbyte **names; int count = 0; @@ -1005,13 +1011,14 @@ CONSOLE_HAS_METHOD (x, color_instance_hash); CONSOLE_HAS_METHOD (x, color_instance_rgb_components); CONSOLE_HAS_METHOD (x, valid_color_name_p); + CONSOLE_HAS_METHOD (x, color_list); CONSOLE_HAS_METHOD (x, initialize_font_instance); CONSOLE_HAS_METHOD (x, print_font_instance); CONSOLE_HAS_METHOD (x, finalize_font_instance); CONSOLE_HAS_METHOD (x, font_instance_truename); CONSOLE_HAS_METHOD (x, font_instance_properties); - CONSOLE_HAS_METHOD (x, list_fonts); + CONSOLE_HAS_METHOD (x, font_list); #ifdef MULE CONSOLE_HAS_METHOD (x, find_charset_font); CONSOLE_HAS_METHOD (x, font_spec_matches_charset); diff --text -u 'xemacs-21.5.18/src/objects.c' 'xemacs-21.5.19/src/objects.c' Index: ./src/objects.c --- ./src/objects.c Fri Oct 15 02:26:24 2004 +++ ./src/objects.c Fri Feb 4 01:14:07 2005 @@ -1,7 +1,7 @@ /* Generic Objects and Functions. Copyright (C) 1995 Free Software Foundation, Inc. Copyright (C) 1995 Board of Trustees, University of Illinois. - Copyright (C) 1995, 1996, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -63,7 +63,7 @@ static const struct memory_description color_instance_data_description_1 []= { #ifdef HAVE_TTY - { XD_STRUCT_PTR, tty_console, 1, &tty_color_instance_data_description}, + { XD_BLOCK_PTR, tty_console, 1, { &tty_color_instance_data_description } }, #endif { XD_END } }; @@ -77,7 +77,7 @@ { XD_LISP_OBJECT, offsetof (Lisp_Color_Instance, name)}, { XD_LISP_OBJECT, offsetof (Lisp_Color_Instance, device)}, { XD_UNION, offsetof (Lisp_Color_Instance, data), - XD_INDIRECT (0, 0), &color_instance_data_description }, + XD_INDIRECT (0, 0), { &color_instance_data_description } }, {XD_END} }; @@ -133,13 +133,13 @@ DEVMETH (XDEVICE (c1->device), color_instance_equal, (c1, c2, depth))); } -static unsigned long +static Hashcode color_instance_hash (Lisp_Object obj, int depth) { Lisp_Color_Instance *c = XCOLOR_INSTANCE (obj); struct device *d = DEVICEP (c->device) ? XDEVICE (c->device) : 0; - return HASH2 ((unsigned long) d, + return HASH2 ((Hashcode) d, !d ? LISP_HASH (obj) : DEVMETH_OR_GIVEN (d, color_instance_hash, (c, depth), LISP_HASH (obj))); @@ -248,6 +248,18 @@ return MAYBE_INT_DEVMETH (d, valid_color_name_p, (d, color)) ? Qt : Qnil; } +DEFUN ("color-list", Fcolor_list, 0, 1, 0, /* +Return a list of color names. +DEVICE specifies which device to return names for, and defaults to the +currently selected device. +*/ + (device)) +{ + device = wrap_device (decode_device (device)); + + return MAYBE_LISP_DEVMETH (XDEVICE (device), color_list, ()); +} + /*************************************************************************** * Font-Instance Object * @@ -260,7 +272,7 @@ static const struct memory_description font_instance_data_description_1 []= { #ifdef HAVE_TTY - { XD_STRUCT_PTR, tty_console, 1, &tty_font_instance_data_description}, + { XD_BLOCK_PTR, tty_console, 1, { &tty_font_instance_data_description} }, #endif { XD_END } }; @@ -275,7 +287,7 @@ { XD_LISP_OBJECT, offsetof (Lisp_Font_Instance, truename)}, { XD_LISP_OBJECT, offsetof (Lisp_Font_Instance, device)}, { XD_UNION, offsetof (Lisp_Font_Instance, data), - XD_INDIRECT (0, 0), &font_instance_data_description }, + XD_INDIRECT (0, 0), { &font_instance_data_description } }, { XD_END } }; @@ -334,7 +346,7 @@ depth + 1); } -static unsigned long +static Hashcode font_instance_hash (Lisp_Object obj, int depth) { return internal_hash (font_instance_truename_internal @@ -506,7 +518,7 @@ font_instance_properties, (f)); } -DEFUN ("list-fonts", Flist_fonts, 1, 3, 0, /* +DEFUN ("font-list", Ffont_list, 1, 3, 0, /* Return a list of font names matching the given pattern. DEVICE specifies which device to search for names, and defaults to the currently selected device. @@ -516,7 +528,7 @@ CHECK_STRING (pattern); device = wrap_device (decode_device (device)); - return MAYBE_LISP_DEVMETH (XDEVICE (device), list_fonts, (pattern, device, + return MAYBE_LISP_DEVMETH (XDEVICE (device), font_list, (pattern, device, maxnumber)); } @@ -618,7 +630,7 @@ XVECTOR_DATA (instantiator)[1], domain, ERROR_ME, 0, depth)); default: - abort (); + ABORT (); } } else if (NILP (instantiator)) @@ -630,7 +642,7 @@ device); } else - abort (); /* The spec validation routines are screwed up. */ + ABORT (); /* The spec validation routines are screwed up. */ return Qunbound; } @@ -894,7 +906,7 @@ else if (NILP (instantiator)) return Qunbound; else - abort (); /* Eh? */ + ABORT (); /* Eh? */ return Qunbound; } @@ -1025,7 +1037,7 @@ return retval; } else - abort (); /* Eh? */ + ABORT (); /* Eh? */ return Qunbound; } @@ -1121,6 +1133,7 @@ DEFSUBR (Fcolor_instance_name); DEFSUBR (Fcolor_instance_rgb_components); DEFSUBR (Fvalid_color_name_p); + DEFSUBR (Fcolor_list); DEFSYMBOL_MULTIWORD_PREDICATE (Qfont_instancep); DEFSUBR (Fmake_font_instance); @@ -1132,7 +1145,7 @@ DEFSUBR (Ffont_instance_proportional_p); DEFSUBR (Ffont_instance_truename); DEFSUBR (Ffont_instance_properties); - DEFSUBR (Flist_fonts); + DEFSUBR (Ffont_list); /* Qcolor, Qfont defined in general.c */ DEFSYMBOL (Qface_boolean); @@ -1214,5 +1227,4 @@ void vars_of_objects (void) { - reinit_vars_of_objects (); } diff --text -u 'xemacs-21.5.18/src/opaque.c' 'xemacs-21.5.19/src/opaque.c' Index: ./src/opaque.c --- ./src/opaque.c Tue Sep 21 04:19:55 2004 +++ ./src/opaque.c Wed Jan 26 19:22:28 2005 @@ -100,11 +100,11 @@ /* This will not work correctly for opaques with subobjects! */ -static unsigned long +static Hashcode hash_opaque (Lisp_Object obj, int UNUSED (depth)) { if (XOPAQUE_SIZE (obj) == sizeof (unsigned long)) - return *((unsigned long *) XOPAQUE_DATA (obj)); + return *((Hashcode *) XOPAQUE_DATA (obj)); else return memory_hash (XOPAQUE_DATA (obj), XOPAQUE_SIZE (obj)); } @@ -141,10 +141,10 @@ return (XOPAQUE_PTR (obj1)->ptr == XOPAQUE_PTR (obj2)->ptr); } -static unsigned long +static Hashcode hash_opaque_ptr (Lisp_Object obj, int UNUSED (depth)) { - return (unsigned long) XOPAQUE_PTR (obj)->ptr; + return (Hashcode) XOPAQUE_PTR (obj)->ptr; } static const struct memory_description opaque_ptr_description[] = { diff --text -u 'xemacs-21.5.18/src/print.c' 'xemacs-21.5.19/src/print.c' Index: ./src/print.c --- ./src/print.c Tue Sep 21 04:19:55 2004 +++ ./src/print.c Tue Jan 25 08:34:05 2005 @@ -123,7 +123,7 @@ into an opaque object. */ struct debug_bindings { - int inhibit_non_essential_printing_operations; + int inhibit_non_essential_conversion_operations; int print_depth; int print_readably; int print_unbuffered; @@ -154,14 +154,18 @@ if (stream || output_is_std_handle) { - if (initialized && !inhibit_non_essential_printing_operations) + if (initialized && !inhibit_non_essential_conversion_operations) TO_EXTERNAL_FORMAT (DATA, (ptr, len), ALLOCA, (extptr, extlen), Qterminal); else { +#ifdef NON_ASCII_INTERNAL_FORMAT +#error Do something here +#else extptr = (Extbyte *) ptr; extlen = (Bytecount) len; +#endif } } @@ -291,7 +295,7 @@ Ibyte kludge[8192]; Bytecount kludgelen; - if (initialized && !inhibit_non_essential_printing_operations) + if (initialized && !inhibit_non_essential_conversion_operations) fmt = GETTEXT (fmt); vsprintf ((CIbyte *) kludge, fmt, args); kludgelen = qxestrlen (kludge); @@ -424,7 +428,7 @@ we inhibit GC. */ if (len < 65536) { - Ibyte *copied = alloca_array (Ibyte, len); + Ibyte *copied = alloca_ibytes (len); memcpy (copied, newnonreloc + offset, len); Lstream_write (XLSTREAM (function), copied, len); } @@ -1147,7 +1151,7 @@ } } -#define ONE_DIGIT(figure) *p++ = n / (figure) + '0' +#define ONE_DIGIT(figure) *p++ = (char) (n / (figure) + '0') #define ONE_DIGIT_ADVANCE(figure) (ONE_DIGIT (figure), n %= (figure)) #define DIGITS_1(figure) ONE_DIGIT (figure) @@ -1473,7 +1477,7 @@ static void printing_major_badness (Lisp_Object printcharfun, - Char_ASCII *badness_string, int type, void *val, + Ascbyte *badness_string, int type, void *val, enum printing_badness badness) { Ibyte buf[666]; @@ -1496,10 +1500,10 @@ /* Don't abort or signal if called from debug_print() or already crashing */ - if (!inhibit_non_essential_printing_operations) + if (!inhibit_non_essential_conversion_operations) { #ifdef ERROR_CHECK_TYPES - abort (); + ABORT (); #else /* not ERROR_CHECK_TYPES */ if (print_readably) signal_ferror (Qinternal_error, "printing %s", buf); @@ -1560,7 +1564,7 @@ /* Avoid calling internal_bind_int, which conses, when called from debug_prin1. In that case, we have bound print_depth to 0 anyway. */ - if (!inhibit_non_essential_printing_operations) + if (!inhibit_non_essential_conversion_operations) { specdepth = internal_bind_int (&print_depth, print_depth + 1); @@ -1653,7 +1657,7 @@ debug_print() or we're already crashing. In such cases, (further) crashing is counterproductive. */ - if (inhibit_non_essential_printing_operations && + if (inhibit_non_essential_conversion_operations && !debug_can_access_memory (lheader, sizeof (*lheader))) { write_fmt_string (printcharfun, "#<EMACS BUG: BAD MEMORY %p>", @@ -1697,7 +1701,7 @@ (e.g. under Unix we typically have to set a SIGSEGV handler and try to trigger a seg fault). */ - if (inhibit_non_essential_printing_operations) + if (inhibit_non_essential_conversion_operations) { if (!debug_can_access_memory (lheader, detagged_lisp_object_size (lheader))) @@ -1740,7 +1744,7 @@ } } - if (!inhibit_non_essential_printing_operations) + if (!inhibit_non_essential_conversion_operations) unbind_to (specdepth); UNGCPRO; } @@ -1914,7 +1918,7 @@ int extlen; const Extbyte *extptr; #if 0 /* We want to see the internal representation, don't we? */ - if (initialized && !inhibit_non_essential_printing_operations) + if (initialized && !inhibit_non_essential_conversion_operations) TO_EXTERNAL_FORMAT (DATA, (str, len), ALLOCA, (extptr, extlen), Qterminal); @@ -2062,8 +2066,8 @@ { struct debug_bindings *bindings = (struct debug_bindings *) XOPAQUE (debug_prin1_bindings)->data; - inhibit_non_essential_printing_operations = - bindings->inhibit_non_essential_printing_operations; + inhibit_non_essential_conversion_operations = + bindings->inhibit_non_essential_conversion_operations; print_depth = bindings->print_depth; print_readably = bindings->print_readably; print_unbuffered = bindings->print_unbuffered; @@ -2089,8 +2093,8 @@ struct debug_bindings *bindings = (struct debug_bindings *) XOPAQUE (debug_prin1_bindings)->data; - bindings->inhibit_non_essential_printing_operations = - inhibit_non_essential_printing_operations; + bindings->inhibit_non_essential_conversion_operations = + inhibit_non_essential_conversion_operations; bindings->print_depth = print_depth; bindings->print_readably = print_readably; bindings->print_unbuffered = print_unbuffered; @@ -2100,7 +2104,7 @@ bindings->Vinhibit_quit = Vinhibit_quit; specdepth = record_unwind_protect (debug_prin1_exit, Qnil); - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; print_depth = 0; print_readably = debug_print_readably != -1 ? debug_print_readably : 0; print_unbuffered++; @@ -2128,7 +2132,7 @@ void debug_p4 (Lisp_Object obj) { - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; if (STRINGP (obj)) debug_out ("\"%s\"", XSTRING_DATA (obj)); else if (CONSP (obj)) @@ -2195,7 +2199,7 @@ ((struct lcrecord_header *) header)->uid); } - inhibit_non_essential_printing_operations = 0; + inhibit_non_essential_conversion_operations = 0; } static void @@ -2227,9 +2231,9 @@ debug_p3 (Lisp_Object obj) { debug_p4 (obj); - inhibit_non_essential_printing_operations = 1; + inhibit_non_essential_conversion_operations = 1; debug_out ("\n"); - inhibit_non_essential_printing_operations = 0; + inhibit_non_essential_conversion_operations = 0; } void @@ -2266,7 +2270,7 @@ /* by doing this, we trick various things that are non-essential but might cause crashes into not getting executed. */ int specdepth = - internal_bind_int (&inhibit_non_essential_printing_operations, 1); + internal_bind_int (&inhibit_non_essential_conversion_operations, 1); internal_bind_int (&print_depth, 0); internal_bind_int (&print_readably, 0); @@ -2375,8 +2379,6 @@ void vars_of_print (void) { - reinit_vars_of_print (); - DEFVAR_LISP ("standard-output", &Vstandard_output /* Output stream `print' uses by default for outputting a character. This may be any function of one argument. diff --text -u 'xemacs-21.5.18/src/process-nt.c' 'xemacs-21.5.19/src/process-nt.c' Index: ./src/process-nt.c --- ./src/process-nt.c Tue Sep 21 04:19:55 2004 +++ ./src/process-nt.c Fri Jan 28 11:36:26 2005 @@ -2,7 +2,7 @@ Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 1996, 2000, 2001, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -25,10 +25,15 @@ /* Mule-ized as of 8-6-00 */ +/* Major comment about parsing and/or constructing a command line taken + from Windows, or suitable for giving to one of the library routines that + calls a subprocess is in win32-native.el */ + #include <config.h> #include "lisp.h" #include "console-msw.h" +#include "events.h" #include "hash.h" #include "lstream.h" #include "process.h" @@ -120,6 +125,13 @@ LPVOID address; } process_memory; +static void +free_process_memory (process_memory *pmc) +{ + ResumeThread (pmc->h_thread); + CloseHandle (pmc->h_thread); +} + /* * Allocate SIZE bytes in H_PROCESS address space. Fill in PMC used * further by other routines. Return nonzero if successful. @@ -176,17 +188,11 @@ return 1; failure: - ResumeThread (pmc->h_thread); + free_process_memory (pmc); pmc->address = 0; return 0; } -static void -free_process_memory (process_memory *pmc) -{ - ResumeThread (pmc->h_thread); -} - /* * Run ROUTINE in the context of process determined by H_PROCESS. The * routine is passed the address of DATA as parameter. The ROUTINE must @@ -256,7 +262,7 @@ failure: free_process_memory (&pm); - return (DWORD)-1; + return (DWORD) -1; } /*-----------------------------------------------------------------------*/ @@ -382,7 +388,7 @@ assert (d.adr_GenerateConsoleCtrlEvent); d.event = CTRL_C_EVENT; retval = run_in_other_process (h_process, - (LPTHREAD_START_ROUTINE) sigint_proc, + (LPTHREAD_START_ROUTINE) sigint_proc, &d, sizeof (d)); break; } @@ -392,7 +398,7 @@ if (close_process) CloseHandle (h_process); - return (int)retval > 0 ? 1 : 0; + return (int) retval > 0 ? 1 : 0; } /* @@ -654,10 +660,14 @@ { assert (!for_disksave); /* If it's still in the list of processes we are waiting on delete - it. */ + it. This can happen if we forcibly delete a process and are unable + to kill it. */ mswindows_unwait_process (p); if (NT_DATA (p)->h_process) - CloseHandle (NT_DATA (p)->h_process); + { + CloseHandle (NT_DATA (p)->h_process); + NT_DATA (p)->h_process = 0; + } } /* @@ -700,8 +710,8 @@ int mswindows_compare_env (const void *strp1, const void *strp2) { - const Ibyte *str1 = *(const Ibyte **)strp1, - *str2 = *(const Ibyte **)strp2; + const Itext *str1 = * (const Itext **) strp1, + *str2 = * (const Itext **) strp2; while (*str1 && *str2 && *str1 != '=' && *str2 != '=') { @@ -754,14 +764,16 @@ if (mswindows_is_executable (XSTRING_DATA (program))) { Extbyte *progext; - LISP_STRING_TO_TSTR (program, progext); + LISP_PATHNAME_CONVERT_OUT (program, progext); image_type = qxeSHGetFileInfo (progext, 0, NULL, 0, SHGFI_EXETYPE); } else { DECLARE_EISTRING (progext); - eicpy_lstr (progext, program); - eicat_c (progext, ".exe"); + Ibyte *prog2; + LISP_PATHNAME_RESOLVE_LINKS (program, prog2); + eicpy_rawz (progext, prog2); + eicat_ascii (progext, ".exe"); eito_external (progext, Qmswindows_tstr); image_type = qxeSHGetFileInfo (eiextdata (progext), 0, NULL, 0, SHGFI_EXETYPE); @@ -799,8 +811,8 @@ CreatePipe (&hmyslurp_err, &hprocerr, &sa, 0); else /* Duplicate the stdout handle for use as stderr */ - DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(), - &hprocerr, 0, TRUE, DUPLICATE_SAME_ACCESS); + DuplicateHandle (GetCurrentProcess(), hprocout, GetCurrentProcess(), + &hprocerr, 0, TRUE, DUPLICATE_SAME_ACCESS); /* Stupid Win32 allows to create a pipe with *both* ends either inheritable or not. We need process ends inheritable, and local @@ -837,6 +849,8 @@ args_or_ret = Fnreverse (args_or_ret); args_or_ret = Fcons (program, args_or_ret); + /* This Lisp function is in win32-native.el and has lots of comments + about what exactly is going on. */ args_or_ret = call1 (Qmswindows_construct_process_command_line, args_or_ret); @@ -846,6 +860,7 @@ ("Bogus return value from `mswindows-construct-process-command-line'", args_or_ret); + /* #### What about path names, which may be links? */ LISP_STRING_TO_TSTR (args_or_ret, command_line); UNGCPRO; /* args_or_ret */ @@ -938,7 +953,7 @@ while leaving the real app name as argv[0]. */ if (is_dos_app) { - cmdname = (Ibyte *) ALLOCA (PATH_MAX); + cmdname = alloca_ibytes (PATH_MAX_INTERNAL); if (egetenv ("CMDPROXY")) qxestrcpy (cmdname, egetenv ("CMDPROXY")); else @@ -982,7 +997,7 @@ { Extbyte *curdirext; - LISP_STRING_TO_TSTR (cur_dir, curdirext); + LISP_PATHNAME_CONVERT_OUT (cur_dir, curdirext); err = (qxeCreateProcess (NULL, command_line, NULL, NULL, TRUE, (XEUNICODE_P ? @@ -1099,7 +1114,7 @@ chunklen = Lstream_read (lstream, chunkbuf, 512); if (chunklen <= 0) - break; /* perhaps should abort() if < 0? + break; /* perhaps should ABORT() if < 0? This should never happen. */ /* Lstream_write() will never successfully write less than the @@ -1134,6 +1149,20 @@ } } +static void +nt_deactivate_process (Lisp_Process *p, + USID *in_usid, + USID *err_usid) +{ + event_stream_delete_io_streams (p->pipe_instream, p->pipe_outstream, + p->pipe_errstream, in_usid, err_usid); + /* Go ahead and close the process handle now to prevent accumulation + of handles when lots of processes are run. (The handle gets closed + anyway upon GC, but that might be a ways away, esp. if + deleted-exited-processes is set to nil.) */ + nt_finalize_process_data (p, 0); +} + /* * Send a signal number SIGNO to PROCESS. * CURRENT_GROUP means send to the process group that currently owns @@ -1196,7 +1225,7 @@ static int get_internet_address (Lisp_Object host, struct sockaddr_in *address) { - Char_Binary buf[MAXGETHOSTSTRUCT]; + CBinbyte buf[MAXGETHOSTSTRUCT]; HWND hwnd; HANDLE hasync; int errcode = 0; @@ -1558,6 +1587,7 @@ PROCESS_HAS_METHOD (nt, create_process); PROCESS_HAS_METHOD (nt, update_status_if_terminated); PROCESS_HAS_METHOD (nt, send_process); + PROCESS_HAS_METHOD (nt, deactivate_process); PROCESS_HAS_METHOD (nt, kill_child_process); PROCESS_HAS_METHOD (nt, kill_process_by_pid); #ifdef HAVE_SOCKETS diff --text -u 'xemacs-21.5.18/src/process-unix.c' 'xemacs-21.5.19/src/process-unix.c' Index: ./src/process-unix.c --- ./src/process-unix.c Tue Sep 21 04:19:56 2004 +++ ./src/process-unix.c Fri Feb 4 13:06:34 2005 @@ -917,7 +917,7 @@ REGISTER Bytecount i; i = XSTRING_LENGTH (current_dir); - pwd = alloca_array (Ibyte, i + 6); + pwd = alloca_ibytes (i + 6); memcpy (pwd, "PWD=", 4); memcpy (pwd + 4, XSTRING_DATA (current_dir), i); i += 4; @@ -1511,30 +1511,38 @@ Ibyte chunkbuf[512]; Bytecount chunklen; - while (1) + do { int writeret; chunklen = Lstream_read (lstream, chunkbuf, 512); - if (chunklen <= 0) - break; /* perhaps should abort() if < 0? - This should never happen. */ old_sigpipe = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGPIPE, send_process_trap); - /* Lstream_write() will never successfully write less than - the amount sent in. In the worst case, it just buffers - the unwritten data. */ - writeret = Lstream_write (XLSTREAM (DATA_OUTSTREAM (p)), chunkbuf, - chunklen); - { - int save_errno = errno; - EMACS_SIGNAL (SIGPIPE, old_sigpipe); - errno = save_errno; - if (writeret < 0) - /* This is a real error. Blocking errors are handled - specially inside of the filedesc stream. */ - report_process_error ("writing to process", proc); - } + if (chunklen > 0) + { + int save_errno; + + /* Lstream_write() will never successfully write less than + the amount sent in. In the worst case, it just buffers + the unwritten data. */ + writeret = Lstream_write (XLSTREAM (DATA_OUTSTREAM(p)), chunkbuf, + chunklen); + save_errno = errno; + EMACS_SIGNAL (SIGPIPE, old_sigpipe); + errno = save_errno; + if (writeret < 0) + /* This is a real error. Blocking errors are handled + specially inside of the filedesc stream. */ + report_file_error ("writing to process", list1 (proc)); + } + else + { + /* Need to make sure that everything up to and including the + last chunk is flushed, even when the pipe is currently + blocked. */ + Lstream_flush (XLSTREAM (DATA_OUTSTREAM(p))); + EMACS_SIGNAL (SIGPIPE, old_sigpipe); + } while (Lstream_was_blocked_p (XLSTREAM (p->pipe_outstream))) { /* Buffer is full. Wait, accepting input; @@ -1549,7 +1557,9 @@ Lstream_flush (XLSTREAM (p->pipe_outstream)); EMACS_SIGNAL (SIGPIPE, old_sigpipe); } + /* Perhaps should ABORT() if < 0? This should never happen. */ } + while (chunklen > 0); } else { /* We got here from a longjmp() from the SIGPIPE handler */ @@ -1620,10 +1630,10 @@ { SIGTYPE (*old_sigpipe) (int) = 0; - if (UNIX_DATA(p)->infd >= 0) - flush_pending_output (UNIX_DATA(p)->infd); - if (UNIX_DATA(p)->errfd >= 0) - flush_pending_output (UNIX_DATA(p)->errfd); + if (UNIX_DATA (p)->infd >= 0) + flush_pending_output (UNIX_DATA (p)->infd); + if (UNIX_DATA (p)->errfd >= 0) + flush_pending_output (UNIX_DATA (p)->errfd); /* closing the outstream could result in SIGPIPE, so ignore it. */ old_sigpipe = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGPIPE, SIG_IGN); @@ -1631,8 +1641,8 @@ p->pipe_errstream, in_usid, err_usid); EMACS_SIGNAL (SIGPIPE, old_sigpipe); - UNIX_DATA(p)->infd = -1; - UNIX_DATA(p)->errfd = -1; + UNIX_DATA (p)->infd = -1; + UNIX_DATA (p)->errfd = -1; } /* If the subtty field of the process data is not filled in, do so now. */ diff --text -u 'xemacs-21.5.18/src/process.c' 'xemacs-21.5.19/src/process.c' Index: ./src/process.c --- ./src/process.c Wed Sep 22 11:06:49 2004 +++ ./src/process.c Tue Jan 25 08:34:06 2005 @@ -2,7 +2,7 @@ Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 1996, 2001, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -63,6 +63,10 @@ #include "systty.h" #include "syswait.h" +#ifdef WIN32_NATIVE +#include "syswindows.h" +#endif + Lisp_Object Qprocessp, Qprocess_live_p, Qprocess_readable_p; /* Process methods */ @@ -378,7 +382,7 @@ #endif /* This may be called during a GC from process_send_signal() from - kill_buffer_processes() if emacs decides to abort(). */ + kill_buffer_processes() if emacs decides to ABORT(). */ if (PROCESSP (name)) return name; else if (STRINGP (name)) @@ -1788,7 +1792,7 @@ name = XSTRING_DATA (XSYMBOL (signal_)->name); #define handle_signal(sym) do { \ - if (!qxestrcmp_c ( name, #sym)) \ + if (!qxestrcmp_ascii ( name, #sym)) \ return sym; \ } while (0) @@ -2146,9 +2150,9 @@ &in_usid, &err_usid); if (in_usid != USID_DONTHASH) - remhash ((const void*)in_usid, usid_to_process); + remhash ((const void *) in_usid, usid_to_process); if (err_usid != USID_DONTHASH) - remhash ((const void*)err_usid, usid_to_process); + remhash ((const void *) err_usid, usid_to_process); p->pipe_instream = Qnil; p->pipe_outstream = Qnil; @@ -2435,11 +2439,19 @@ { /* jwz: always initialize Vprocess_environment, so that egetenv() works in temacs. */ - char **envp; + Extbyte **envp; Vprocess_environment = Qnil; +#ifdef WIN32_NATIVE + _wgetenv (L""); /* force initialization of _wenviron */ + for (envp = (Extbyte **) _wenviron; envp && *envp; envp++) + Vprocess_environment = + Fcons (build_ext_string (*envp, Qmswindows_unicode), + Vprocess_environment); +#else for (envp = environ; envp && *envp; envp++) Vprocess_environment = Fcons (build_ext_string (*envp, Qnative), Vprocess_environment); +#endif /* This gets set back to 0 in disksave_object_finalization() */ env_initted = 1; } @@ -2475,7 +2487,7 @@ if (!egetenv ("SHELL")) { - Ibyte *faux_var = alloca_array (Ibyte, 7 + qxestrlen (shell)); + Ibyte *faux_var = alloca_ibytes (7 + qxestrlen (shell)); qxesprintf (faux_var, "SHELL=%s", shell); Vprocess_environment = Fcons (build_intstring (faux_var), Vprocess_environment); diff --text -u 'xemacs-21.5.18/src/profile.c' 'xemacs-21.5.19/src/profile.c' Index: ./src/profile.c --- ./src/profile.c Tue Sep 21 04:19:56 2004 +++ ./src/profile.c Fri Feb 4 01:14:08 2005 @@ -1,5 +1,5 @@ /* Why the hell is XEmacs so fucking slow? - Copyright (C) 1996, 2002, 2003 Ben Wing. + Copyright (C) 1996, 2002, 2003, 2004 Ben Wing. Copyright (C) 1998 Free Software Foundation, Inc. This file is part of XEmacs. @@ -39,77 +39,13 @@ int mswindows_is_blocking; #endif -/* Written by Ben Wing. +/* Written by Ben Wing. */ - 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. +/* + +Documented in + + (Info-goto-node "(internals)Profiling") */ /* We use a plain table here because we're recording inside of a signal @@ -132,6 +68,15 @@ static Lisp_Object QSprocessing_events_at_top_level; static Lisp_Object QSunknown, QSprofile_overhead; +#ifdef DEBUG_XEMACS +/* For temporary profiling */ +Lisp_Object QSin_temp_spot_1; +Lisp_Object QSin_temp_spot_2; +Lisp_Object QSin_temp_spot_3; +Lisp_Object QSin_temp_spot_4; +Lisp_Object QSin_temp_spot_5; +#endif /* DEBUG_XEMACS */ + static Lisp_Object Qtiming, Qtotal_timing, Qcall_count; static Lisp_Object Qgc_usage, Qtotal_gc_usage; @@ -163,8 +108,8 @@ static const struct memory_description plain_hash_table_description_1[] = { { XD_ELEMCOUNT, offsetof (struct hash_table, size) }, - { XD_STRUCT_PTR, offsetof (struct hash_table, harray), XD_INDIRECT (0, 0), - &hentry_description }, + { XD_BLOCK_PTR, offsetof (struct hash_table, harray), XD_INDIRECT (0, 0), + { &hentry_description } }, { XD_END } }; @@ -192,16 +137,16 @@ create_timing_profile_table (); if (NILP (Vtotal_timing_profile_table)) Vtotal_timing_profile_table = - make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); + make_lisp_hash_table (1000, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); if (NILP (Vcall_count_profile_table)) Vcall_count_profile_table = - make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); + make_lisp_hash_table (1000, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); if (NILP (Vgc_usage_profile_table)) Vgc_usage_profile_table = - make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); + make_lisp_hash_table (1000, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); if (NILP (Vtotal_gc_usage_profile_table)) Vtotal_gc_usage_profile_table = - make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); + make_lisp_hash_table (1000, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); } static Lisp_Object @@ -242,13 +187,8 @@ void profile_record_consing (EMACS_INT size) { - Lisp_Object fun; - Lisp_Object count; - in_profiling++; - fun = current_profile_function (); - count = Fgethash (fun, Vgc_usage_profile_table, Qzero); - Fputhash (fun, make_int (size + XINT (count)), Vgc_usage_profile_table); + inchash_eq (current_profile_function (), Vgc_usage_profile_table, size); in_profiling--; } @@ -292,11 +232,7 @@ /* See comments in create_timing_profile_table(). */ pregrow_hash_table_if_necessary (big_profile_table, EXTRA_BREATHING_ROOM); profiling_lock = 0; - Fputhash (*bt->function, - make_int (1 + XINT (Fgethash (*bt->function, - Vcall_count_profile_table, - Qzero))), - Vcall_count_profile_table); + inchash_eq (*bt->function, Vcall_count_profile_table, 1); /* This may be set if the function was in its preamble at the time that `start-profiling' was called. If so, we shouldn't reset the values because we may get inconsistent results, since we have already started @@ -741,11 +677,28 @@ #if 0 /* #### This is supposed to be for KKCC but KKCC doesn't use this stuff currently. */ - dump_add_root_struct_ptr (&big_profile_table, &plain_hash_table_description); + dump_add_root_block_ptr (&big_profile_table, &plain_hash_table_description); #endif /* 0 */ profiling_lock = 0; +#ifdef DEBUG_XEMACS + QSin_temp_spot_1 = build_msg_string ("(in temp spot 1)"); + staticpro (&QSin_temp_spot_1); + + QSin_temp_spot_2 = build_msg_string ("(in temp spot 2)"); + staticpro (&QSin_temp_spot_2); + + QSin_temp_spot_3 = build_msg_string ("(in temp spot 3)"); + staticpro (&QSin_temp_spot_3); + + QSin_temp_spot_4 = build_msg_string ("(in temp spot 4)"); + staticpro (&QSin_temp_spot_4); + + QSin_temp_spot_5 = build_msg_string ("(in temp spot 5)"); + staticpro (&QSin_temp_spot_5); +#endif /* DEBUG_XEMACS */ + QSunknown = build_msg_string ("(unknown)"); staticpro (&QSunknown); QSprocessing_events_at_top_level = diff --text -u 'xemacs-21.5.18/src/profile.h' 'xemacs-21.5.19/src/profile.h' Index: ./src/profile.h --- ./src/profile.h Thu Feb 13 18:57:08 2003 +++ ./src/profile.h Wed Jan 26 19:09:20 2005 @@ -95,3 +95,30 @@ if (do_backtrace) \ POP_BACKTRACE (backtrace); \ } while (0) + +#define RETURN_EXIT_PROFILING(tag, type, expr) \ +do \ +{ \ + type _ret_exitpr_ = (expr); \ + PROFILE_RECORD_EXITING_SECTION (tag); \ + RETURN_SANS_WARNINGS _ret_exitpr_; \ +} while (0) + +#define RETURN_LISP_EXIT_PROFILING(tag, expr) \ + RETURN_EXIT_PROFILING (tag, Lisp_Object, expr) + +#define RETURN_UNGCPRO_EXIT_PROFILING(tag, expr) \ +{ \ + Lisp_Object ret_ungc_val = (expr); \ + UNGCPRO; \ + PROFILE_RECORD_EXITING_SECTION (tag); \ + RETURN_SANS_WARNINGS ret_ungc_val; \ +} while (0) + +#ifdef DEBUG_XEMACS +extern Lisp_Object QSin_temp_spot_1; +extern Lisp_Object QSin_temp_spot_2; +extern Lisp_Object QSin_temp_spot_3; +extern Lisp_Object QSin_temp_spot_4; +extern Lisp_Object QSin_temp_spot_5; +#endif /* DEBUG_XEMACS */ diff --text -u 'xemacs-21.5.18/src/ralloc.c' 'xemacs-21.5.19/src/ralloc.c' Index: ./src/ralloc.c --- ./src/ralloc.c Fri Nov 21 01:04:47 2003 +++ ./src/ralloc.c Tue Jan 25 08:34:06 2005 @@ -256,7 +256,7 @@ } if (! heap) - abort (); + ABORT (); /* If we can't fit SIZE bytes in that heap, try successive later heaps. */ @@ -362,7 +362,7 @@ /* This heap should have no blocs in it. */ if (last_heap->first_bloc != NIL_BLOC || last_heap->last_bloc != NIL_BLOC) - abort (); + ABORT (); /* Return the last heap, with its header, to the system. */ excess = (char *)last_heap->end - (char *)last_heap->start; @@ -377,7 +377,7 @@ } if ((*real_morecore) (- excess) == 0) - abort (); + ABORT (); } } @@ -480,7 +480,7 @@ /* No need to ever call this if arena is frozen, bug somewhere! */ if (r_alloc_freeze_level) - abort(); + ABORT(); while (b) { @@ -635,7 +635,7 @@ /* No need to ever call this if arena is frozen, bug somewhere! */ if (r_alloc_freeze_level) - abort(); + ABORT(); if (bloc == NIL_BLOC || size == bloc->size) return 1; @@ -647,7 +647,7 @@ } if (heap == NIL_HEAP) - abort (); + ABORT (); old_size = bloc->size; bloc->size = size; @@ -978,7 +978,7 @@ dead_bloc = find_bloc (ptr); if (dead_bloc == NIL_BLOC) - abort (); + ABORT (); free_bloc (dead_bloc); *ptr = 0; @@ -1023,7 +1023,7 @@ bloc = find_bloc (ptr); if (bloc == NIL_BLOC) - abort (); + ABORT (); if (size < bloc->size) { @@ -1093,7 +1093,7 @@ init_ralloc (); if (--r_alloc_freeze_level < 0) - abort (); + ABORT (); /* This frees all unused blocs. It is not too inefficient, as the resize and memmove is done only once. Afterwards, all unreferenced blocs are @@ -1137,7 +1137,7 @@ first_heap->start = first_heap->bloc_start = virtual_break_value = break_value = (*real_morecore) (0); if (break_value == NIL) - abort (); + ABORT (); page_size = PAGE; extra_bytes = ROUNDUP (50000); @@ -1813,13 +1813,13 @@ { if (p->addr == addr) { - if (p->sz != sz) abort(); /* ACK! Shouldn't happen at all. */ + if (p->sz != sz) ABORT(); /* ACK! Shouldn't happen at all. */ munmap( (VM_ADDR) p->addr, p->sz ); p->flag = empty; break; } } - if (!p) abort(); /* Can't happen... we've got a block to free which is not in + if (!p) ABORT(); /* Can't happen... we've got a block to free which is not in the address list. */ Coalesce_Addr_Blocks(); } @@ -1867,7 +1867,7 @@ switch(r_alloc_initialized) { case 0: - abort(); + ABORT(); case 1: *ptr = (POINTER) UNDERLYING_MALLOC(size); break; @@ -1910,7 +1910,7 @@ switch( r_alloc_initialized) { case 0: - abort(); + ABORT(); case 1: UNDERLYING_FREE( *ptr ); /* Certain this is from the heap. */ @@ -1954,7 +1954,7 @@ if (r_alloc_initialized == 0) { - abort (); + ABORT (); return 0; /* suppress compiler warning */ } else if (r_alloc_initialized == 1) diff --text -u 'xemacs-21.5.18/src/rangetab.c' 'xemacs-21.5.19/src/rangetab.c' Index: ./src/rangetab.c --- ./src/rangetab.c Tue Sep 21 04:19:56 2004 +++ ./src/rangetab.c Fri Feb 4 01:14:08 2005 @@ -1,6 +1,6 @@ /* XEmacs routines to deal with range tables. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 2002 Ben Wing. + Copyright (C) 1995, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -30,11 +30,55 @@ Lisp_Object Qrange_tablep; Lisp_Object Qrange_table; +Lisp_Object Qstart_closed_end_open; +Lisp_Object Qstart_open_end_open; +Lisp_Object Qstart_closed_end_closed; +Lisp_Object Qstart_open_end_closed; + /************************************************************************/ /* Range table object */ /************************************************************************/ +static enum range_table_type +range_table_symbol_to_type (Lisp_Object symbol) +{ + if (NILP (symbol)) + return RANGE_START_CLOSED_END_OPEN; + + CHECK_SYMBOL (symbol); + if (EQ (symbol, Qstart_closed_end_open)) + return RANGE_START_CLOSED_END_OPEN; + if (EQ (symbol, Qstart_closed_end_closed)) + return RANGE_START_CLOSED_END_CLOSED; + if (EQ (symbol, Qstart_open_end_open)) + return RANGE_START_OPEN_END_OPEN; + if (EQ (symbol, Qstart_open_end_closed)) + return RANGE_START_OPEN_END_CLOSED; + + invalid_constant ("Unknown range table type", symbol); + RETURN_NOT_REACHED (RANGE_START_CLOSED_END_OPEN); +} + +static Lisp_Object +range_table_type_to_symbol (enum range_table_type type) +{ + switch (type) + { + case RANGE_START_CLOSED_END_OPEN: + return Qstart_closed_end_open; + case RANGE_START_CLOSED_END_CLOSED: + return Qstart_closed_end_closed; + case RANGE_START_OPEN_END_OPEN: + return Qstart_open_end_open; + case RANGE_START_OPEN_END_CLOSED: + return Qstart_open_end_closed; + } + + ABORT (); + return Qnil; +} + /* We use a sorted array of ranges. #### We should be using the gap array stuff from extents.c. This @@ -58,20 +102,37 @@ Lisp_Range_Table *rt = XRANGE_TABLE (obj); int i; - write_c_string (printcharfun, "#s(range-table data ("); + if (print_readably) + write_fmt_string_lisp (printcharfun, "#s(range-table type %s data (", + 1, range_table_type_to_symbol (rt->type)); + else + write_c_string (printcharfun, "#<range-table "); for (i = 0; i < Dynarr_length (rt->entries); i++) { struct range_table_entry *rte = Dynarr_atp (rt->entries, i); + int so, ec; if (i > 0) write_c_string (printcharfun, " "); - if (rte->first == rte->last) - write_fmt_string (printcharfun, "%ld ", (long) (rte->first)); - else - write_fmt_string (printcharfun, "(%ld %ld) ", (long) (rte->first), - (long) (rte->last)); + switch (rt->type) + { + case RANGE_START_CLOSED_END_OPEN: so = 0, ec = 0; break; + case RANGE_START_CLOSED_END_CLOSED: so = 0, ec = 1; break; + case RANGE_START_OPEN_END_OPEN: so = 1, ec = 0; break; + case RANGE_START_OPEN_END_CLOSED: so = 1; ec = 1; break; + default: ABORT (); so = 0, ec = 0; break; + } + write_fmt_string (printcharfun, "%c%ld %ld%c ", + print_readably ? '(' : so ? '(' : '[', + (long) (rte->first - so), + (long) (rte->last - ec), + print_readably ? ')' : ec ? ']' : ')' + ); print_internal (rte->val, printcharfun, 1); } - write_c_string (printcharfun, "))"); + if (print_readably) + write_c_string (printcharfun, "))"); + else + write_fmt_string (printcharfun, " 0x%x>", rt->header.uid); } static int @@ -98,19 +159,19 @@ return 1; } -static unsigned long +static Hashcode range_table_entry_hash (struct range_table_entry *rte, int depth) { return HASH3 (rte->first, rte->last, internal_hash (rte->val, depth + 1)); } -static unsigned long +static Hashcode range_table_hash (Lisp_Object obj, int depth) { Lisp_Range_Table *rt = XRANGE_TABLE (obj); int i; int size = Dynarr_length (rt->entries); - unsigned long hash = size; + Hashcode hash = size; /* approach based on internal_array_hash(). */ if (size <= 5) @@ -153,7 +214,8 @@ }; static const struct memory_description range_table_description[] = { - { XD_STRUCT_PTR, offsetof (Lisp_Range_Table, entries), 1, &rted_description }, + { XD_BLOCK_PTR, offsetof (Lisp_Range_Table, entries), 1, + { &rted_description } }, { XD_END } }; @@ -180,7 +242,7 @@ struct range_table_entry *rte = Dynarr_atp (rt->entries, i); assert (rte->last >= rte->first); if (i > 0) - assert (Dynarr_at (rt->entries, i - 1).last < rte->first); + assert (Dynarr_at (rt->entries, i - 1).last <= rte->first); } } @@ -207,8 +269,8 @@ of the list), so NEWPOS must round down. */ int newpos = (left + right) >> 1; struct range_table_entry *entry = tab + newpos; - if (pos > entry->last) - left = newpos+1; + if (pos >= entry->last) + left = newpos + 1; else if (pos < entry->first) right = newpos; else @@ -226,16 +288,50 @@ return RANGE_TABLEP (object) ? Qt : Qnil; } -DEFUN ("make-range-table", Fmake_range_table, 0, 0, 0, /* +DEFUN ("range-table-type", Frange_table_type, 1, 1, 0, /* +Return non-nil if OBJECT is a range table. +*/ + (range_table)) +{ + CHECK_RANGE_TABLE (range_table); + return range_table_type_to_symbol (XRANGE_TABLE (range_table)->type); +} + +DEFUN ("make-range-table", Fmake_range_table, 0, 1, 0, /* Return a new, empty range table. You can manipulate it using `put-range-table', `get-range-table', `remove-range-table', and `clear-range-table'. +Range tables allow you to efficiently set values for ranges of integers. + + TYPE is a symbol indicating how ranges are assumed to function at their + ends. It can be one of + + SYMBOL RANGE-START RANGE-END + ------ ----------- --------- + `start-closed-end-open' (the default) closed open + `start-closed-end-closed' closed closed + `start-open-end-open' open open + `start-open-end-closed' open closed + + A `closed' endpoint of a range means that the number at that end is included + in the range. For an `open' endpoint, the number would not be included. + + For example, a closed-open range from 5 to 20 would be indicated as [5, + 20) where a bracket indicates a closed end and a parenthesis an open end, + and would mean `all the numbers between 5 and 20', including 5 but not 20. + This seems a little strange at first but is in fact extremely common in + the outside world as well as in computers and makes things work sensibly. + For example, if I say "there are seven days between today and next week + today", I'm including today but not next week today; if I included both, + there would be eight days. Similarly, there are 15 (= 20 - 5) elements in + the range [5, 20), but 16 in the range [5, 20]. */ - ()) + (type)) { Lisp_Range_Table *rt = alloc_lcrecord_type (Lisp_Range_Table, &lrecord_range_table); rt->entries = Dynarr_new (range_table_entry); + rt->type = range_table_symbol_to_type (type); return wrap_range_table (rt); } @@ -253,6 +349,7 @@ rtnew = alloc_lcrecord_type (Lisp_Range_Table, &lrecord_range_table); rtnew->entries = Dynarr_new (range_table_entry); + rtnew->type = rt->type; Dynarr_add_many (rtnew->entries, Dynarr_atp (rt->entries, 0), Dynarr_length (rt->entries)); @@ -284,6 +381,24 @@ int insert_me_here = -1; Lisp_Range_Table *rt = XRANGE_TABLE (table); + /* Fix up the numbers in accordance with the open/closedness to make + them behave like default open/closed. */ + + switch (rt->type) + { + case RANGE_START_CLOSED_END_OPEN: break; + case RANGE_START_CLOSED_END_CLOSED: last++; break; + case RANGE_START_OPEN_END_OPEN: first++; break; + case RANGE_START_OPEN_END_CLOSED: first++, last++; break; + } + + if (first == last) + return; + if (first > last) + /* This will happen if originally first == last and both ends are + open. #### Should we signal an error? */ + return; + /* Now insert in the proper place. This gets tricky because we may be overlapping one or more existing ranges and need to fix them up. */ @@ -304,44 +419,55 @@ /* completely after the new range. No more possibilities of finding overlapping ranges. */ break; + /* At this point the existing ENTRY overlaps or touches the new one. */ if (entry->first < first && entry->last <= last) { /* looks like: - [ NEW ] - [ EXISTING ] + [ NEW ) + [ EXISTING ) + + or + + [ NEW ) + [ EXISTING ) */ /* truncate the end off of it. */ - entry->last = first - 1; + entry->last = first; } else if (entry->first < first && entry->last > last) /* looks like: - [ NEW ] - [ EXISTING ] + [ NEW ) + [ EXISTING ) */ /* need to split this one in two. */ { struct range_table_entry insert_me_too; - insert_me_too.first = last + 1; + insert_me_too.first = last; insert_me_too.last = entry->last; insert_me_too.val = entry->val; - entry->last = first - 1; + entry->last = first; Dynarr_insert_many (rt->entries, &insert_me_too, 1, i + 1); } - else if (entry->last > last) + else if (entry->last >= last) { /* looks like: - [ NEW ] - [ EXISTING ] + [ NEW ) + [ EXISTING ) + + or + + [ NEW ) + [ EXISTING ) */ /* truncate the start off of it. */ - entry->first = last + 1; + entry->first = last; } else { @@ -377,7 +503,7 @@ { struct range_table_entry *entry = Dynarr_atp (rt->entries, insert_me_here - 1); - if (EQ (val, entry->val) && entry->last == first - 1) + if (EQ (val, entry->val) && entry->last == first) { entry->last = last; Dynarr_delete_many (rt->entries, insert_me_here, 1); @@ -392,7 +518,7 @@ { struct range_table_entry *entry = Dynarr_atp (rt->entries, insert_me_here + 1); - if (EQ (val, entry->val) && entry->first == last + 1) + if (EQ (val, entry->val) && entry->first == last) { entry->first = first; Dynarr_delete_many (rt->entries, insert_me_here, 1); @@ -401,7 +527,7 @@ } DEFUN ("put-range-table", Fput_range_table, 4, 4, 0, /* -Set the value for range (START, END) to be VALUE in RANGE-TABLE. +Set the value for range START .. END to be VALUE in RANGE-TABLE. */ (start, end, value, range_table)) { @@ -421,7 +547,7 @@ } DEFUN ("remove-range-table", Fremove_range_table, 3, 3, 0, /* -Remove the value for range (START, END) in RANGE-TABLE. +Remove the value for range START .. END in RANGE-TABLE. */ (start, end, range_table)) { @@ -491,18 +617,21 @@ /************************************************************************/ static int -rangetab_data_validate (Lisp_Object UNUSED (keyword), Lisp_Object value, +rangetab_type_validate (Lisp_Object UNUSED (keyword), Lisp_Object value, Error_Behavior UNUSED (errb)) { - Lisp_Object rest; + /* #### should deal with ERRB */ + range_table_symbol_to_type (value); + return 1; +} - /* #### should deal with errb */ - EXTERNAL_LIST_LOOP (rest, value) +static int +rangetab_data_validate (Lisp_Object UNUSED (keyword), Lisp_Object value, + Error_Behavior UNUSED (errb)) +{ + /* #### should deal with ERRB */ + EXTERNAL_PROPERTY_LIST_LOOP_3 (range, data, value) { - Lisp_Object range = XCAR (rest); - rest = XCDR (rest); - if (!CONSP (rest)) - sferror ("Invalid list format", value); if (!INTP (range) && !CHARP (range) && !(CONSP (range) && CONSP (XCDR (range)) && NILP (XCDR (XCDR (range))) @@ -515,27 +644,31 @@ } static Lisp_Object -rangetab_instantiate (Lisp_Object data) +rangetab_instantiate (Lisp_Object plist) { - Lisp_Object rangetab = Fmake_range_table (); + Lisp_Object data = Qnil, type = Qnil, rangetab; - if (!NILP (data)) + PROPERTY_LIST_LOOP_3 (key, value, plist) { - data = Fcar (Fcdr (data)); /* skip over 'data keyword */ - while (!NILP (data)) - { - Lisp_Object range = Fcar (data); - Lisp_Object val = Fcar (Fcdr (data)); - - data = Fcdr (Fcdr (data)); - if (CONSP (range)) - Fput_range_table (Fcar (range), Fcar (Fcdr (range)), val, - rangetab); - else - Fput_range_table (range, range, val, rangetab); - } + if (EQ (key, Qtype)) type = value; + else if (EQ (key, Qdata)) data = value; + else + ABORT (); } + rangetab = Fmake_range_table (type); + + { + PROPERTY_LIST_LOOP_3 (range, val, data) + { + if (CONSP (range)) + Fput_range_table (Fcar (range), Fcar (Fcdr (range)), val, + rangetab); + else + Fput_range_table (range, range, val, rangetab); + } + } + return rangetab; } @@ -739,7 +872,13 @@ DEFSYMBOL_MULTIWORD_PREDICATE (Qrange_tablep); DEFSYMBOL (Qrange_table); + DEFSYMBOL (Qstart_closed_end_open); + DEFSYMBOL (Qstart_open_end_open); + DEFSYMBOL (Qstart_closed_end_closed); + DEFSYMBOL (Qstart_open_end_closed); + DEFSUBR (Frange_table_p); + DEFSUBR (Frange_table_type); DEFSUBR (Fmake_range_table); DEFSUBR (Fcopy_range_table); DEFSUBR (Fget_range_table); @@ -757,4 +896,5 @@ st = define_structure_type (Qrange_table, 0, rangetab_instantiate); define_structure_type_keyword (st, Qdata, rangetab_data_validate); + define_structure_type_keyword (st, Qtype, rangetab_type_validate); } diff --text -u 'xemacs-21.5.18/src/rangetab.h' 'xemacs-21.5.19/src/rangetab.h' Index: ./src/rangetab.h --- ./src/rangetab.h Fri Mar 29 13:48:22 2002 +++ ./src/rangetab.h Mon Dec 6 12:52:17 2004 @@ -1,6 +1,6 @@ /* XEmacs routines to deal with range tables. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995 Ben Wing. + Copyright (C) 1995, 2004 Ben Wing. This file is part of XEmacs. @@ -39,10 +39,19 @@ Dynarr_declare (range_table_entry); } range_table_entry_dynarr; +enum range_table_type +{ + RANGE_START_CLOSED_END_OPEN, + RANGE_START_CLOSED_END_CLOSED, + RANGE_START_OPEN_END_CLOSED, + RANGE_START_OPEN_END_OPEN +}; + struct Lisp_Range_Table { struct lcrecord_header header; range_table_entry_dynarr *entries; + enum range_table_type type; }; typedef struct Lisp_Range_Table Lisp_Range_Table; diff --text -u 'xemacs-21.5.18/src/realpath.c' 'xemacs-21.5.19/src/realpath.c' Index: ./src/realpath.c --- ./src/realpath.c Wed Oct 22 23:17:00 2003 +++ ./src/realpath.c Fri Jan 28 11:36:26 2005 @@ -1,7 +1,7 @@ /* * realpath.c -- canonicalize pathname by removing symlinks * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> - * Copyright (C) 2001, 2002 Ben Wing. + * Copyright (C) 2001, 2002, 2004 Ben Wing. * This file is part of XEmacs. @@ -31,6 +31,8 @@ #include <config.h> #include "lisp.h" +#include "profile.h" + #include "sysfile.h" #include "sysdir.h" @@ -43,6 +45,8 @@ #endif #endif +Lisp_Object QSin_qxe_realpath; + /* Length of start of absolute filename. */ static int abs_start (const Ibyte *name) @@ -60,35 +64,66 @@ #endif } -/* Find real name of a file by resolving symbolic links and (under Windows) - looking up the correct case of the file as it appears on the file - system. +/* Find real name of a file by resolving symbolic links and/or shortcuts + under Windows (.LNK links), if such support is enabled. + + If no link found, and LINKS_ONLY is false, look up the correct case in + the file system of the last component. Under Windows, UNC servers and shares are lower-cased. Directories must be given without trailing '/'. One day, this could read Win2K's reparse - points. */ + points. + + Returns length of characters copied info BUF. + DOES NOT ZERO TERMINATE!!!!! +*/ static int -readlink_and_correct_case (const Ibyte *name, Ibyte *buf, - int size) +readlink_or_correct_case (const Ibyte *name, Ibyte *buf, Bytecount size, + Boolint links_only) { #ifndef WIN32_ANY - return qxe_readlink (name, buf, size); + return qxe_readlink (name, buf, (size_t) size); #else # ifdef CYGWIN Ibyte *tmp; - int n = qxe_readlink (name, buf, size); + int n = qxe_readlink (name, buf, (size_t) size); if (n >= 0 || errno != EINVAL) return n; /* The file may exist, but isn't a symlink. Try to find the right name. */ - tmp = (Ibyte *) ALLOCA (cygwin_posix_to_win32_path_list_buf_size - ((char *) name)); + tmp = + alloca_ibytes (cygwin_posix_to_win32_path_list_buf_size ((char *) name)); cygwin_posix_to_win32_path_list ((char *) name, (char *) tmp); name = tmp; +# else + if (mswindows_shortcuts_are_symlinks) + { + Ibyte *tmp = mswindows_read_link (name); + + if (tmp != NULL) + { + /* Fucking fixed buffers. */ + Bytecount len = qxestrlen (tmp); + if (len > size) + { + errno = ENAMETOOLONG; + return -1; + } + memcpy (buf, tmp, len); + xfree (tmp, Ibyte *); + return len; + } + } # endif + if (links_only) + { + errno = EINVAL; + return -1; + } + { int len = 0; int err = 0; @@ -105,7 +140,7 @@ errno = ENOENT; return -1; } - else if (qxestrlen (name) >= PATH_MAX) + else if (qxestrlen (name) >= PATH_MAX_INTERNAL) { errno = ENAMETOOLONG; return -1; @@ -144,16 +179,16 @@ FindClose (dir_handle); } - if ((len = eilen (result)) < size) + if ((len = eilen (result)) <= size) { DECLARE_EISTRING (eilastname); eicpy_rawz (eilastname, lastname); if (eicmp_ei (eilastname, result) == 0) - /* Signal that the name is already OK. */ - err = EINVAL; + /* Signal that the name is already OK. */ + err = EINVAL; else - memcpy (buf, eidata (result), len + 1); + memcpy (buf, eidata (result), len); } else err = ENAMETOOLONG; @@ -165,27 +200,35 @@ } /* Mule Note: This function works with and returns - internally-formatted strings. */ + internally-formatted strings. + + if LINKS_ONLY is true, don't do case canonicalization under + Windows. */ Ibyte * -qxe_realpath (const Ibyte *path, Ibyte *resolved_path) +qxe_realpath (const Ibyte *path, Ibyte *resolved_path, Boolint links_only) { - Ibyte copy_path[PATH_MAX]; + Ibyte copy_path[PATH_MAX_INTERNAL]; Ibyte *new_path = resolved_path; Ibyte *max_path; + Ibyte *retval = NULL; #if defined (HAVE_READLINK) || defined (WIN32_ANY) int readlinks = 0; - Ibyte link_path[PATH_MAX]; + Ibyte link_path[PATH_MAX_INTERNAL]; int n; int abslen = abs_start (path); #endif + PROFILE_DECLARE (); + + PROFILE_RECORD_ENTERING_SECTION (QSin_qxe_realpath); + restart: /* Make a copy of the source path since we may need to modify it. */ qxestrcpy (copy_path, path); path = copy_path; - max_path = copy_path + PATH_MAX - 2; + max_path = copy_path + PATH_MAX_INTERNAL - 2; if (0) ; @@ -216,14 +259,14 @@ /* No drive letter, but a beginning slash? Prepend drive letter. */ else if (abslen == 1) { - get_initial_directory (new_path, PATH_MAX - 1); + get_initial_directory (new_path, PATH_MAX_INTERNAL - 1); new_path += 3; path++; } /* Just a path name, prepend the current directory */ else { - get_initial_directory (new_path, PATH_MAX - 1); + get_initial_directory (new_path, PATH_MAX_INTERNAL - 1); new_path += qxestrlen (new_path); if (!IS_DIRECTORY_SEP (new_path[-1])) *new_path++ = DIRECTORY_SEP; @@ -232,7 +275,7 @@ /* If it's a relative pathname use get_initial_directory for starters. */ else if (abslen == 0) { - get_initial_directory (new_path, PATH_MAX - 1); + get_initial_directory (new_path, PATH_MAX_INTERNAL - 1); new_path += qxestrlen (new_path); if (!IS_DIRECTORY_SEP (new_path[-1])) *new_path++ = DIRECTORY_SEP; @@ -288,7 +331,7 @@ if (path > max_path) { errno = ENAMETOOLONG; - return NULL; + goto done; } *new_path++ = *path++; } @@ -297,7 +340,8 @@ /* See if latest pathname component is a symlink or needs case correction. */ *new_path = '\0'; - n = readlink_and_correct_case (resolved_path, link_path, PATH_MAX - 1); + n = readlink_or_correct_case (resolved_path, link_path, + PATH_MAX_INTERNAL - 1, links_only); if (n < 0) { @@ -308,7 +352,7 @@ #else if (errno != EINVAL) #endif - return NULL; + goto done; } else { @@ -316,7 +360,7 @@ if (readlinks++ > MAX_READLINKS) { errno = ELOOP; - return NULL; + goto done; } /* Note: readlink doesn't add the null byte. */ @@ -337,10 +381,10 @@ assert (new_path > resolved_path); /* Safe sex check. */ - if (qxestrlen (path) + n >= PATH_MAX) + if (qxestrlen (path) + n >= PATH_MAX_INTERNAL) { errno = ENAMETOOLONG; - return NULL; + goto done; } /* Insert symlink contents into path. */ @@ -360,5 +404,16 @@ /* Make sure it's null terminated. */ *new_path = '\0'; - return resolved_path; + retval = resolved_path; +done: + PROFILE_RECORD_EXITING_SECTION (QSin_qxe_realpath); + return retval; +} + +void +vars_of_realpath (void) +{ + QSin_qxe_realpath = + build_msg_string ("(in qxe_realpath)"); + staticpro (&QSin_qxe_realpath); } diff --text -u 'xemacs-21.5.18/src/redisplay-gtk.c' 'xemacs-21.5.19/src/redisplay-gtk.c' Index: ./src/redisplay-gtk.c --- ./src/redisplay-gtk.c Tue Sep 21 04:19:56 2004 +++ ./src/redisplay-gtk.c Tue Jan 25 08:34:06 2005 @@ -239,6 +239,7 @@ gtk_text_width (struct frame *UNUSED (f), struct face_cachel *cachel, CONST Ichar *str, Charcount len) { + /* !!#### */ int width_so_far = 0; unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len); struct textual_run *runs = alloca_array (struct textual_run, len); @@ -457,7 +458,7 @@ break; case IMAGE_POINTER: - abort (); + ABORT (); case IMAGE_WIDGET: if (EQ (XIMAGE_INSTANCE_WIDGET_TYPE (instance), @@ -481,14 +482,14 @@ break; default: - abort (); + ABORT (); } xpos += rb->width; elt++; } else - abort (); + ABORT (); } } @@ -659,6 +660,7 @@ int width, face_index findex, int cursor, int cursor_start, int cursor_width, int cursor_height) { + /* !!#### Needs review */ /* General variables */ struct frame *f = XFRAME (w->frame); struct device *d = XDEVICE (f->device); diff --text -u 'xemacs-21.5.18/src/redisplay-msw.c' 'xemacs-21.5.19/src/redisplay-msw.c' Index: ./src/redisplay-msw.c --- ./src/redisplay-msw.c Tue Sep 21 04:19:56 2004 +++ ./src/redisplay-msw.c Tue Jan 25 08:34:07 2005 @@ -148,7 +148,7 @@ Lisp_Object font_inst = FACE_CACHEL_FONT (cachel, run->charset); SIZE size; -#if 0 /* @@#### not the way of ikeyama's ws */ +#if 0 /* #### not the way of ikeyama's ws */ if (!fi->proportional_p || !hdc) { if (XCHARSET_DIMENSION (run->charset) == 2) @@ -166,7 +166,7 @@ cachel->underline, cachel->strikethru); GetTextExtentPoint32W (hdc, run->ptr, run->nwchars, &size); return size.cx; -#if 0 /* @@#### not the way of ikeyama's ws */ +#if 0 /* #### not the way of ikeyama's ws */ } #endif } @@ -1079,7 +1079,7 @@ case IMAGE_TEXT: case IMAGE_POINTER: default: - abort (); + ABORT (); } IMAGE_INSTANCE_OPTIMIZE_OUTPUT (XIMAGE_INSTANCE (instance)) = 0; @@ -1088,7 +1088,7 @@ elt++; } else - abort (); + ABORT (); } } diff --text -u 'xemacs-21.5.18/src/redisplay-output.c' 'xemacs-21.5.19/src/redisplay-output.c' Index: ./src/redisplay-output.c --- ./src/redisplay-output.c Tue Sep 21 04:19:57 2004 +++ ./src/redisplay-output.c Tue Jan 25 08:34:07 2005 @@ -419,7 +419,7 @@ else if (start_pos <= bounds.right_out) *next_start = bounds.right_out; else - abort (); + ABORT (); } for (block = 0; block < Dynarr_length (dba); block++) @@ -462,7 +462,7 @@ int defheight, defwidth; if (Dynarr_length (db->runes) <= cursor_location) - abort (); + ABORT (); window = wrap_window (w); @@ -1610,7 +1610,7 @@ case IMAGE_POINTER: default: - abort (); + ABORT (); } } IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0; @@ -1722,7 +1722,7 @@ f = XFRAME (locale); } else - abort (); + ABORT (); d = XDEVICE (f->device); diff --text -u 'xemacs-21.5.18/src/redisplay-tty.c' 'xemacs-21.5.19/src/redisplay-tty.c' Index: ./src/redisplay-tty.c --- ./src/redisplay-tty.c Tue Sep 21 04:19:57 2004 +++ ./src/redisplay-tty.c Tue Jan 25 08:34:07 2005 @@ -355,7 +355,7 @@ case IMAGE_TEXT: case IMAGE_POINTER: default: - abort (); + ABORT (); } IMAGE_INSTANCE_OPTIMIZE_OUTPUT (XIMAGE_INSTANCE (instance)) = 0; @@ -365,7 +365,7 @@ elt++; } else - abort (); + ABORT (); } } @@ -1057,6 +1057,7 @@ int init_tty_for_redisplay (struct device *d, char *terminal_type) { + /* !!#### Mule-ize this */ int status; char entry_buffer[2044]; /* char temp_buffer[2044]; */ diff --text -u 'xemacs-21.5.18/src/redisplay-x.c' 'xemacs-21.5.19/src/redisplay-x.c' Index: ./src/redisplay-x.c --- ./src/redisplay-x.c Tue Sep 21 04:19:57 2004 +++ ./src/redisplay-x.c Tue Jan 25 08:34:07 2005 @@ -244,6 +244,7 @@ x_text_width (struct frame *UNUSED (f), struct face_cachel *cachel, const Ichar *str, Charcount len) { + /* !!#### Needs review */ int width_so_far = 0; unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len); struct textual_run *runs = alloca_array (struct textual_run, len); @@ -483,7 +484,7 @@ case IMAGE_TEXT: case IMAGE_POINTER: default: - abort (); + ABORT (); } IMAGE_INSTANCE_OPTIMIZE_OUTPUT (XIMAGE_INSTANCE (instance)) = 0; @@ -493,7 +494,7 @@ elt++; } else - abort (); + ABORT (); } } diff --text -u 'xemacs-21.5.18/src/redisplay.c' 'xemacs-21.5.19/src/redisplay.c' Index: ./src/redisplay.c --- ./src/redisplay.c Tue Sep 21 04:19:57 2004 +++ ./src/redisplay.c Fri Feb 4 01:30:38 2005 @@ -522,7 +522,7 @@ }; static const struct memory_description rune_object_description_1[] = { - { XD_STRUCT_ARRAY, RUNE_DGLYPH, 1, &rune_dglyph_description }, + { XD_BLOCK_ARRAY, RUNE_DGLYPH, 1, { &rune_dglyph_description } }, { XD_END } }; @@ -533,7 +533,7 @@ static const struct memory_description rune_description_1[] = { { XD_INT, offsetof (rune, type) }, { XD_UNION, offsetof (rune, object), - XD_INDIRECT (0, 0), &rune_object_description }, + XD_INDIRECT (0, 0), { &rune_object_description } }, { XD_END } }; @@ -553,8 +553,8 @@ }; static const struct memory_description display_block_description_1[] = { - { XD_STRUCT_PTR, offsetof (display_block, runes), - 1, &rune_dynarr_description }, + { XD_BLOCK_PTR, offsetof (display_block, runes), + 1, { &rune_dynarr_description } }, { XD_END } }; @@ -595,12 +595,12 @@ }; static const struct memory_description display_line_description_1[] = { - { XD_STRUCT_PTR, offsetof (display_line, display_blocks), - 1, &display_block_dynarr_description }, - { XD_STRUCT_PTR, offsetof (display_line, left_glyphs), - 1, &glyph_block_dynarr_description }, - { XD_STRUCT_PTR, offsetof (display_line, right_glyphs), - 1, &glyph_block_dynarr_description }, + { XD_BLOCK_PTR, offsetof (display_line, display_blocks), + 1, { &display_block_dynarr_description } }, + { XD_BLOCK_PTR, offsetof (display_line, left_glyphs), + 1, { &glyph_block_dynarr_description } }, + { XD_BLOCK_PTR, offsetof (display_line, right_glyphs), + 1, { &glyph_block_dynarr_description } }, { XD_END } }; @@ -1569,7 +1569,7 @@ Lisp_Object format = XCAR (XCDR (entry)); Bytebpos len = XSTRING_LENGTH (format); Ibyte *src = XSTRING_DATA (format), *end = src + len; - Ibyte *result = alloca_array (Ibyte, len); + Ibyte *result = alloca_ibytes (len); Ibyte *dst = result; while (src < end) @@ -1764,7 +1764,7 @@ } break; default: - abort (); + ABORT (); } } @@ -1959,7 +1959,7 @@ /* Otherwise something is screwed up. */ else - abort (); + ABORT (); } face = glyph_face (gb->glyph, data->window); @@ -2067,7 +2067,7 @@ return NULL; } else - abort (); /* there are no unknown types */ + ABORT (); /* there are no unknown types */ } return NULL; @@ -2144,42 +2144,11 @@ #### This variable should probably have some rethought done to it. - #### It would also be really nice if you could specify that - the characters come out in hex instead of in octal. Mule - does that by adding a ctl-hexa variable similar to ctl-arrow, - but that's bogus -- we need a more general solution. I - think you need to extend the concept of display tables - into a more general conversion mechanism. Ideally you - could specify a Lisp function that converts characters, - but this violates the Second Golden Rule and besides would - make things way way way way slow. - - So instead, we extend the display-table concept, which was - historically limited to 256-byte vectors, to one of the - following: - - a) A 256-entry vector, for backward compatibility; - b) char-table, mapping characters to values; - c) range-table, mapping ranges of characters to values; - d) a list of the above. + See also - The (d) option allows you to specify multiple display tables - instead of just one. Each display table can specify conversions - for some characters and leave others unchanged. The way the - character gets displayed is determined by the first display table - with a binding for that character. This way, you could call a - function `enable-hex-display' that adds a hex display-table to - the list of display tables for the current buffer. - - #### ...not yet implemented... Also, we extend the concept of - "mapping" to include a printf-like spec. Thus you can make all - extended characters show up as hex with a display table like - this: + (Info-goto-node "(internals)Future Work -- Display Tables") - #s(range-table data ((256 524288) (format "%x"))) - - Since more than one display table is possible, you have - great flexibility in mapping ranges of characters. */ + */ Ichar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) ? XCHAR_OR_CHAR_INT (b->ctl_arrow) : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) @@ -3129,7 +3098,7 @@ struct glyph_block *gb = Dynarr_atp (gbd, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (gb->active && ((side == LEFT_GLYPHS && @@ -3214,7 +3183,7 @@ struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) { @@ -3266,7 +3235,7 @@ struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) @@ -3335,7 +3304,7 @@ struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) @@ -3377,7 +3346,7 @@ struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) @@ -3535,7 +3504,7 @@ struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) { @@ -3585,7 +3554,7 @@ struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { @@ -3649,7 +3618,7 @@ struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { @@ -3690,7 +3659,7 @@ struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) { @@ -4137,20 +4106,20 @@ /* A string. Add to the display line and check for %-constructs within it. */ - Ibyte *this = XSTRING_DATA (elt); + Ibyte *this_str = XSTRING_DATA (elt); - while ((pos < max_pos || max_pos == -1) && *this) + while ((pos < max_pos || max_pos == -1) && *this_str) { - Ibyte *last = this; + Ibyte *last = this_str; - while (*this && *this != '%') - this++; + while (*this_str && *this_str != '%') + this_str++; - if (this != last) + if (this_str != last) { /* No %-construct */ Charcount size = - bytecount_to_charcount (last, this - last); + bytecount_to_charcount (last, this_str - last); if (size <= *offset) *offset -= size; @@ -4165,32 +4134,32 @@ *offset = 0; } } - else /* *this == '%' */ + else /* *this_str == '%' */ { Charcount spec_width = 0; - this++; /* skip over '%' */ + this_str++; /* skip over '%' */ /* We can't allow -ve args due to the "%-" construct. * Argument specifies minwidth but not maxwidth * (maxwidth can be specified by * (<negative-number> . <stuff>) modeline elements) */ - while (isdigit (*this)) + while (isdigit (*this_str)) { - spec_width = spec_width * 10 + (*this - '0'); - this++; + spec_width = spec_width * 10 + (*this_str - '0'); + this_str++; } spec_width += pos; - if (*this == 'M') + if (*this_str == 'M') { pos = generate_fstring_runes (w, data, pos, spec_width, max_pos, Vglobal_mode_string, depth, max_pixsize, findex, type, offset, cur_ext); } - else if (*this == '-') + else if (*this_str == '-') { Charcount num_to_add; @@ -4217,9 +4186,9 @@ pos = add_string_to_fstring_db_runes (data, (const Ibyte *) "-", pos, pos, max_pos); } - else if (*this != 0) + else if (*this_str != 0) { - Ichar ch = itext_ichar (this); + Ichar ch = itext_ichar (this_str); Ibyte *str; Charcount size; @@ -4246,9 +4215,9 @@ } } - /* NOT this++. There could be any sort of character at + /* NOT this_str++. There could be any sort of character at the current position. */ - INC_IBYTEPTR (this); + INC_IBYTEPTR (this_str); } if (max_pixsize > 0) @@ -5316,112 +5285,11 @@ return ret_charcount; } +/* -/* 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() +Info on Re-entrancy crashes, with backtraces given: + (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT") */ @@ -5437,17 +5305,22 @@ { int yend = ypos + height; Charcount s_zv; - prop_block_dynarr *prop = 0; layout_bounds bounds; - assert (dla); + int depth = -1; - Dynarr_reset (dla); /* if there's nothing to do then do nothing. code after this assumes there is something to do. */ if (NILP (disp_string)) return; + /* See comment in regenerate_window() */ + if (!in_display) + depth = enter_redisplay_critical_section (); + + assert (dla); + Dynarr_reset (dla); + s_zv = string_char_length (disp_string); bounds.left_out = xpos; @@ -5527,6 +5400,9 @@ if (prop) Dynarr_free (prop); + + if (depth >= 0) + exit_redisplay_critical_section (depth); } @@ -5543,7 +5419,8 @@ changed it to the echo area buffer. */ static void -regenerate_window (struct window *w, Charbpos start_pos, Charbpos point, int type) +regenerate_window (struct window *w, Charbpos start_pos, Charbpos point, + int type) { struct frame *f = XFRAME (w->frame); struct buffer *b = XBUFFER (w->buffer); @@ -5551,6 +5428,7 @@ int yend; /* set farther down */ int yclip = WINDOW_TEXT_TOP_CLIP (w); int force; + int depth = -1; prop_block_dynarr *prop; layout_bounds bounds; @@ -5559,7 +5437,20 @@ /* The lines had better exist by this point. */ if (!(dla = window_display_lines (w, type))) - abort (); + ABORT (); + + if (!in_display) + depth = enter_redisplay_critical_section (); + + /* This is one spot where a re-entrancy crash will occur, due to a check + in the dynarr to make sure it isn't "locked" */ +/* + +Info on Re-entrancy crashes, with backtraces given: + + (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT") +*/ + Dynarr_reset (dla); w->max_line_len = 0; @@ -5740,6 +5631,9 @@ there when we first started working in this function. */ generate_modeline (w, Dynarr_atp (dla, 0), type); } + + if (depth >= 0) + exit_redisplay_critical_section (depth); } #define REGEN_INC_FIND_START_END \ @@ -5759,7 +5653,7 @@ dla_start = 0; \ } \ else \ - abort (); /* structs differ */ \ + ABORT (); /* structs differ */ \ \ dla_end = Dynarr_length (cdla) - 1; \ } \ @@ -7734,63 +7628,13 @@ } -/***************************************************************************** - Line Start Cache Description and Rationale - 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. - ****************************************************************************/ +/* + +Info on line-start cache: + + (Info-goto-node "(internals)Line Start Cache") +*/ /* This will get used quite a bit so we don't want to be constantly allocating and freeing it. */ @@ -8070,7 +7914,7 @@ else if (point < start) top = pos - 1; else - abort (); + ABORT (); new_pos = (bottom + top + 1) >> 1; if (pos == new_pos) diff --text -u 'xemacs-21.5.18/src/redisplay.h' 'xemacs-21.5.19/src/redisplay.h' Index: ./src/redisplay.h --- ./src/redisplay.h Mon Sep 22 13:21:43 2003 +++ ./src/redisplay.h Wed Jan 26 19:33:42 2005 @@ -1,7 +1,7 @@ /* Redisplay data structures. Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. Copyright (C) 1996 Chuck Thompson. - Copyright (C) 1995, 1996, 2002, 2003 Ben Wing. + Copyright (C) 1995, 1996, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -692,7 +692,7 @@ extern int display_arg; /* Type of display specified. Defined in emacs.c. */ -extern const Char_ASCII *display_use; +extern const Ascbyte *display_use; /* Nonzero means reading single-character input with prompt so put cursor on minibuffer after the prompt. */ @@ -840,5 +840,7 @@ void exit_redisplay_critical_section (int); int enter_redisplay_critical_section_maybe (void); void exit_redisplay_critical_section_maybe (int depth); +int enter_redisplay_critical_section_if (Boolint from_outside); +void exit_redisplay_critical_section_if (Boolint from_outside, int depth); #endif /* INCLUDED_redisplay_h_ */ diff --text -u 'xemacs-21.5.18/src/regex.c' 'xemacs-21.5.19/src/regex.c' Index: ./src/regex.c --- ./src/regex.c Fri Oct 15 02:26:24 2004 +++ ./src/regex.c Tue Jan 25 08:34:08 2005 @@ -28,10 +28,6 @@ #include <config.h> #endif -#ifndef REGISTER /* Rigidly enforced as of 20.3 */ -#define REGISTER -#endif - #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif @@ -41,10 +37,6 @@ #undef MULE #endif -/* We need this for `regex.h', and perhaps for the Emacs include files. */ -#include <sys/types.h> -#include <stddef.h> /* needed for ptrdiff_t under Solaris */ - /* XEmacs addition */ #ifdef REL_ALLOC #define REGEX_REL_ALLOC /* may be undefined below */ @@ -83,8 +75,15 @@ #else /* not emacs */ +#include <stdlib.h> +#include <sys/types.h> +#include <stddef.h> /* needed for ptrdiff_t under Solaris */ +#include <string.h> + #include "compiler.h" /* Get compiler-specific definitions like UNUSED */ +#define ABORT abort + /* If we are not linking with Emacs proper, we can't use the relocating allocator even if config.h says that we can. */ @@ -97,8 +96,6 @@ #endif #endif -#include <stdlib.h> - #define itext_ichar(str) ((Ichar) (str)[0]) #define itext_ichar_fmt(str, fmt, object) ((Ichar) (str)[0]) #define itext_ichar_ascii_fmt(str, fmt, object) ((Ichar) (str)[0]) @@ -118,8 +115,6 @@ #define itext_ichar_len(ptr) 1 #define itext_ichar_len_fmt(ptr, fmt) 1 -#include <string.h> - /* Define the syntax stuff for \<, \>, etc. */ /* This must be nonzero for the wordchar and notwordchar pattern @@ -300,7 +295,7 @@ we could still be screwed. So we set up a system where we indicate all places where we are prepared for malloc() or alloca(), and in any other circumstances, calls to those functions (from anywhere inside of - XEmacs!) will abort(). We do this even when REL_ALLOC is not defined + XEmacs!) will ABORT(). We do this even when REL_ALLOC is not defined so that we catch these problems sooner, since many developers and beta testers will not be running with REL_ALLOC. */ int regex_malloc_disallowed; @@ -345,6 +340,7 @@ #define REGEX_ALLOCATE ALLOCA + /* !!#### Needs review */ /* Assumes a `char *destination' variable. */ #define REGEX_REALLOCATE(source, osize, nsize) \ (destination = (char *) ALLOCA (nsize), \ @@ -425,7 +421,7 @@ void vars_of_regex (void) { - Vthe_lisp_rangetab = Fmake_range_table (); + Vthe_lisp_rangetab = Fmake_range_table (Qstart_closed_end_closed); staticpro (&Vthe_lisp_rangetab); } @@ -4150,7 +4146,7 @@ default: - abort (); /* We have listed all the cases. */ + ABORT (); /* We have listed all the cases. */ } /* switch *p++ */ /* Getting here means we have found the possible starting @@ -6353,7 +6349,7 @@ #endif /* emacs */ default: - abort (); + ABORT (); } continue; /* Successfully executed one pattern command; keep going. */ @@ -6979,7 +6975,7 @@ to this routine. If we are given anything else, or if other regex code generates an invalid error code, then the program has a bug. Dump core so we can fix it. */ - abort (); + ABORT (); msg = gettext (re_error_msgid[errcode]); diff --text -u 'xemacs-21.5.18/src/s/cxux.h' 'xemacs-21.5.19/src/s/cxux.h' Index: ./src/s/cxux.h --- ./src/s/cxux.h Wed Mar 13 17:53:22 2002 +++ ./src/s/cxux.h Fri Nov 5 08:08:28 2004 @@ -92,8 +92,6 @@ */ #undef const -#define HAVE_GETWD - /* * <pwd.h> already declares getpwuid, and with a uid_t argument in ANSI C * mode. Define this so xrdb.c will compile diff --text -u 'xemacs-21.5.18/src/s/mingw32.h' 'xemacs-21.5.19/src/s/mingw32.h' Index: ./src/s/mingw32.h --- ./src/s/mingw32.h Mon Nov 18 15:52:45 2002 +++ ./src/s/mingw32.h Fri Nov 5 08:08:28 2004 @@ -21,14 +21,7 @@ /* based on cygwin32.h by Andy Piper <andy@xemacs.org> */ -/* NOTE: MinGW is a way of using GCC to target the native Windows - environment. This works similarly to building with Cygwin, but the - resulting executable does not use the Cygwin DLL. Instead, MINGW - provides import libraries for the standard C library DLL's (specifically - CRTDLL -- #### how does this differ from MSVCRT and LIBC.LIB?). This - means that code for MinGW will be very similar to code written for - VC++. See comment in windowsnt.h for more information on how Cygwin - and native Windows relate. */ +/* See win32.c for info about the different Windows files in XEmacs. */ #include "win32-native.h" diff --text -u 'xemacs-21.5.18/src/s/usg5-4-2.h' 'xemacs-21.5.19/src/s/usg5-4-2.h' Index: ./src/s/usg5-4-2.h --- ./src/s/usg5-4-2.h Fri Apr 17 14:41:54 1998 +++ ./src/s/usg5-4-2.h Fri Nov 5 08:08:28 2004 @@ -10,8 +10,5 @@ #define VFORK_RETURN_TYPE pid_t -/* XEmacs change (since getwd is auto-determined) */ -#undef HAVE_GETWD /* (appears to be buggy on SVR4.2) */ - /* XEmacs change: communicate to m/intel386.h */ #define USG5_4_2 diff --text -u 'xemacs-21.5.18/src/s/win32-common.h' 'xemacs-21.5.19/src/s/win32-common.h' Index: ./src/s/win32-common.h --- ./src/s/win32-common.h Fri Jun 21 06:19:10 2002 +++ ./src/s/win32-common.h Fri Nov 5 08:08:28 2004 @@ -19,6 +19,8 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* See win32.c for info about the different Windows files in XEmacs. */ + /* Do not define LOAD_AVE_TYPE or LOAD_AVE_CVT since there is no load average available. */ diff --text -u 'xemacs-21.5.18/src/s/win32-native.h' 'xemacs-21.5.19/src/s/win32-native.h' Index: ./src/s/win32-native.h --- ./src/s/win32-native.h Tue Jul 30 06:06:12 2002 +++ ./src/s/win32-native.h Fri Nov 5 08:08:28 2004 @@ -19,6 +19,8 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* See win32.c for info about the different Windows files in XEmacs. */ + #include "win32-common.h" /* Identify ourselves */ diff --text -u 'xemacs-21.5.18/src/s/windowsnt.h' 'xemacs-21.5.19/src/s/windowsnt.h' Index: ./src/s/windowsnt.h --- ./src/s/windowsnt.h Mon Sep 20 13:07:46 2004 +++ ./src/s/windowsnt.h Tue Jan 25 08:34:34 2005 @@ -21,87 +21,7 @@ /* Synched up with: FSF 19.31. */ -/* Capsule summary of different preprocessor flags: - -1. Keep in mind that there are two possible OS environments we are dealing - with -- Cygwin and Native Windows. MS Windows natively provides - file-system, process, and window-system services through the Win32 API, - implemented by various DLL's. (The most important and 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.) The C - library is implemented on top of Win32 using either MSVCRT (dynamically - linked) or LIBC.LIB (statically linked). Cygwin provides a POSIX - emulation layer 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 - 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. The two environments also use - different compilers -- Native Windows uses Visual C++, and Cygwin uses - GCC. (MinGW, however, is a way of using GCC to target the Native - Windows environment. See comment in mingw32.h.) - -2. There are two windowing environments we can target XEmacs for when - running under MS Windows -- Windows native, and X. (It may seem strange - to write an X application under Windows, but there are in fact many X - servers out there running on Windows, and as far as I know there is no - real (or at least, that works well) networking Window-system extension - under MS Windows. Furthermore, if you're porting a Unix application to - Windows and use Cygwin to assist you, it might seem natural to use an - X server to avoid having to port all the code to Windows.) For XEmacs, - there are various reasons people could come up with for why we would - want to keep maintaining X Windows under MS Windows support. - -That gives us four possible build environments. I (Ben) build -regularly on fully-native-everything, Andy builds on Cygwin + MS -Windows + X Windows for windowing. - -The build flags used for these divisions are: - -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: - - -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 - -*/ +/* See win32.c for info about the different Windows files in XEmacs. */ #include "win32-native.h" @@ -239,13 +159,6 @@ files. */ #define XCDECL __cdecl -/* MSVC 6.0 has a mechanism to declare functions which never return */ -#if (_MSC_VER >= 1200) -#define DOESNT_RETURN_TYPE(rettype) __declspec(noreturn) rettype -#define DECLARE_DOESNT_RETURN_TYPE(rettype,decl) \ - __declspec(noreturn) rettype XCDECL decl -#endif /* MSVC 6.0 */ - /* MSVC warnings no-no crap. When adding one to this section, 1. Think twice. 2. Insert textual description of the warning. @@ -259,13 +172,16 @@ #endif /* compiler understands #pragma warning*/ +#if (_MSC_VER >= 1300) +/* function declared with __declspec(noreturn) has non-void return type; + Lisp primitives have to be declared with Lisp_Object return type or + lots of things get very messed up */ +#pragma warning ( disable : 4646 ) +#endif + /* MSVC version >= 2.x without /Za supports __inline */ #if (_MSC_VER < 900) || defined (__STDC__) # define inline #else # define inline __inline #endif - -/* lisp.h defines abort() as a macro. therefore, we must include all - files that contain prototypes for abort() before then. */ -#include <../include/process.h> diff --text -u 'xemacs-21.5.18/src/scrollbar-gtk.c' 'xemacs-21.5.19/src/scrollbar-gtk.c' Index: ./src/scrollbar-gtk.c --- ./src/scrollbar-gtk.c Tue Sep 21 04:19:58 2004 +++ ./src/scrollbar-gtk.c Tue Jan 25 08:34:09 2005 @@ -368,7 +368,7 @@ } break; default: - abort (); + ABORT (); } } @@ -443,7 +443,7 @@ event_data = Fcons (win, make_int ((int)adj->value)); break; default: - abort(); + ABORT(); } signal_special_gtk_user_event (frame, event_type, event_data); diff --text -u 'xemacs-21.5.18/src/scrollbar-x.c' 'xemacs-21.5.19/src/scrollbar-x.c' Index: ./src/scrollbar-x.c --- ./src/scrollbar-x.c Tue Sep 21 04:19:59 2004 +++ ./src/scrollbar-x.c Tue Jan 25 08:34:09 2005 @@ -281,7 +281,7 @@ } } - if (!wv->scrollbar_data) abort (); + if (!wv->scrollbar_data) ABORT (); free_widget_value_tree (wv); } else if (managed) @@ -367,7 +367,7 @@ } break; default: - abort (); + ABORT (); } } @@ -743,8 +743,6 @@ void vars_of_scrollbar_x (void) { - reinit_vars_of_scrollbar_x (); - #if defined (LWLIB_SCROLLBARS_LUCID) Fprovide (intern ("lucid-scrollbars")); #elif defined (LWLIB_SCROLLBARS_MOTIF) diff --text -u 'xemacs-21.5.18/src/scrollbar.c' 'xemacs-21.5.19/src/scrollbar.c' Index: ./src/scrollbar.c --- ./src/scrollbar.c Tue Sep 21 04:19:59 2004 +++ ./src/scrollbar.c Thu Jan 6 12:45:32 2005 @@ -267,7 +267,8 @@ { int total = 0; - total += DEVMETH (d, compute_scrollbar_instance_usage, (d, inst, ovstats)); + if (HAS_DEVMETH_P(d, compute_scrollbar_instance_usage)) + total += DEVMETH (d, compute_scrollbar_instance_usage, (d, inst, ovstats)); while (inst) { diff --text -u 'xemacs-21.5.18/src/search.c' 'xemacs-21.5.19/src/search.c' Index: ./src/search.c --- ./src/search.c Fri Oct 15 02:26:25 2004 +++ ./src/search.c Tue Jan 25 08:34:09 2005 @@ -1170,7 +1170,7 @@ if (!EQ (noerror, Qt)) { if (lim < BUF_BEGV (buf) || lim > BUF_ZV (buf)) - abort (); + ABORT (); BUF_SET_PT (buf, lim); return Qnil; #if 0 /* This would be clean, but maybe programs depend on @@ -1183,7 +1183,7 @@ } if (np < BUF_BEGV (buf) || np > BUF_ZV (buf)) - abort (); + ABORT (); BUF_SET_PT (buf, np); @@ -1341,7 +1341,7 @@ int charset_base = -1; int boyer_moore_ok = 1; Ibyte *pat = 0; - Ibyte *patbuf = alloca_array (Ibyte, len * MAX_ICHAR_LEN); + Ibyte *patbuf = alloca_ibytes (len * MAX_ICHAR_LEN); pat = patbuf; #ifdef MULE /* &&#### needs some 8-bit work here */ @@ -2058,7 +2058,7 @@ /* The following value is an upper bound on the amount of storage we need. In non-Mule, it is exact. */ Ibyte *storage = - (Ibyte *) ALLOCA (XSTRING_LENGTH (string) - punct_count + + alloca_ibytes (XSTRING_LENGTH (string) - punct_count + 5 * (word_count - 1) + 4); Ibyte *o = storage; @@ -2938,7 +2938,7 @@ } else /* last_thing_searched must always be Qt, a buffer, or Qnil. */ - abort (); + ABORT (); len = i; } @@ -3057,7 +3057,7 @@ CHECK_STRING (string); - temp = (Ibyte *) ALLOCA (XSTRING_LENGTH (string) * 2); + temp = alloca_ibytes (XSTRING_LENGTH (string) * 2); /* Now copy the data into the new string, inserting escapes. */ @@ -3152,8 +3152,6 @@ void vars_of_search (void) { - reinit_vars_of_search (); - DEFVAR_LISP ("forward-word-regexp", &Vforward_word_regexp /* *Regular expression to be used in `forward-word'. #### Not yet implemented. @@ -3175,6 +3173,6 @@ */ ); warn_about_possibly_incompatible_back_references = 1; - Vskip_chars_range_table = Fmake_range_table (); + Vskip_chars_range_table = Fmake_range_table (Qstart_closed_end_closed); staticpro (&Vskip_chars_range_table); } diff --text -u 'xemacs-21.5.18/src/select-common.h' 'xemacs-21.5.19/src/select-common.h' Index: ./src/select-common.h --- ./src/select-common.h Wed Jun 5 18:57:09 2002 +++ ./src/select-common.h Fri Nov 5 08:06:52 2004 @@ -67,7 +67,7 @@ static Lisp_Object selection_data_to_lisp_data (struct device *d, - UChar_Binary *data, + Rawbyte *data, Bytecount size, XE_ATOM_TYPE type, int format) @@ -168,7 +168,7 @@ static void lisp_data_to_selection_data (struct device *d, Lisp_Object obj, - UChar_Binary **data_ret, + Rawbyte **data_ret, XE_ATOM_TYPE *type_ret, Bytecount *size_ret, int *format_ret) @@ -200,7 +200,7 @@ (NILP (type) ? Qctext : Qbinary)); *format_ret = 8; *size_ret = extvallen; - *data_ret = (UChar_Binary *) xmalloc (*size_ret); + *data_ret = xnew_rawbytes (*size_ret); memcpy (*data_ret, extval, *size_ret); #ifdef MULE if (NILP (type)) type = QCOMPOUND_TEXT; @@ -221,7 +221,7 @@ ALLOCA, (extval, extvallen), Qctext); *size_ret = extvallen; - *data_ret = (UChar_Binary *) xmalloc (*size_ret); + *data_ret = xnew_rawbytes (*size_ret); memcpy (*data_ret, extval, *size_ret); #ifdef MULE if (NILP (type)) type = QCOMPOUND_TEXT; @@ -233,7 +233,7 @@ { *format_ret = 32; *size_ret = 1; - *data_ret = (UChar_Binary *) xmalloc (sizeof (XE_ATOM_TYPE) + 1); + *data_ret = xnew_rawbytes (sizeof (XE_ATOM_TYPE) + 1); (*data_ret) [sizeof (XE_ATOM_TYPE)] = 0; (*(XE_ATOM_TYPE **) data_ret) [0] = XE_SYMBOL_TO_ATOM (d, obj, 0); if (NILP (type)) type = QATOM; @@ -244,7 +244,7 @@ { *format_ret = 16; *size_ret = 1; - *data_ret = (UChar_Binary *) xmalloc (sizeof (short) + 1); + *data_ret = xnew_rawbytes (sizeof (short) + 1); (*data_ret) [sizeof (short)] = 0; (*(short **) data_ret) [0] = (short) XINT (obj); if (NILP (type)) type = QINTEGER; @@ -253,7 +253,7 @@ { *format_ret = 32; *size_ret = 1; - *data_ret = (UChar_Binary *) xmalloc (sizeof (long) + 1); + *data_ret = xnew_rawbytes (sizeof (long) + 1); (*data_ret) [sizeof (long)] = 0; (*(unsigned long **) data_ret) [0] = lisp_to_word (obj); if (NILP (type)) type = QINTEGER; @@ -272,7 +272,7 @@ if (NILP (type)) type = QATOM; *size_ret = XVECTOR_LENGTH (obj); *format_ret = 32; - *data_ret = (UChar_Binary *) xmalloc ((*size_ret) * sizeof (XE_ATOM_TYPE)); + *data_ret = xnew_rawbytes ((*size_ret) * sizeof (XE_ATOM_TYPE)); for (i = 0; i < *size_ret; i++) if (SYMBOLP (XVECTOR_DATA (obj) [i])) (*(XE_ATOM_TYPE **) data_ret) [i] = @@ -288,8 +288,8 @@ if (NILP (type)) type = QATOM_PAIR; *size_ret = XVECTOR_LENGTH (obj); *format_ret = 32; - *data_ret = (UChar_Binary *) - xmalloc ((*size_ret) * sizeof (XE_ATOM_TYPE) * 2); + *data_ret = + xnew_rawbytes ((*size_ret) * sizeof (XE_ATOM_TYPE) * 2); for (i = 0; i < *size_ret; i++) if (VECTORP (XVECTOR_DATA (obj) [i])) { @@ -321,7 +321,7 @@ syntax_error ("all elements of the vector must be integers or conses of integers", obj); - *data_ret = (UChar_Binary *) xmalloc (*size_ret * (*format_ret/8)); + *data_ret = xnew_rawbytes (*size_ret * (*format_ret/8)); for (i = 0; i < *size_ret; i++) if (*format_ret == 32) (*((unsigned long **) data_ret)) [i] = diff --text -u 'xemacs-21.5.18/src/select-gtk.c' 'xemacs-21.5.19/src/select-gtk.c' Index: ./src/select-gtk.c --- ./src/select-gtk.c Tue Sep 21 04:19:59 2004 +++ ./src/select-gtk.c Fri Nov 5 08:06:52 2004 @@ -192,7 +192,7 @@ count = specpdl_depth (); - cl = (struct _selection_closure *) xmalloc (sizeof (*cl)); + cl = xnew (struct _selection_closure); cl->data = selection_data; cl->successful = FALSE; @@ -200,7 +200,7 @@ make_opaque_ptr (cl)); { - UChar_Binary *data; + Rawbyte *data; Bytecount size; int format; GdkAtom type; @@ -213,7 +213,7 @@ successful_p = Qt; /* Tell x_selection_request_lisp_error() it's cool. */ cl->successful = TRUE; - xfree (data, UChar_Binary *); + xfree (data, Rawbyte *); } unbind_to (count); diff --text -u 'xemacs-21.5.18/src/select-x.c' 'xemacs-21.5.19/src/select-x.c' Index: ./src/select-x.c --- ./src/select-x.c Tue Sep 21 04:19:59 2004 +++ ./src/select-x.c Tue Jan 25 08:34:09 2005 @@ -392,7 +392,7 @@ Window window = (Window) *private_id; Lisp_Object selection = select_convert_out (QCLIPBOARD, Qnil, Qnil); - /* Whichever lazy git wrote this originally just called abort() + /* Whichever lazy git wrote this originally just called ABORT() when anything didn't go their way... */ /* Try some other text types */ @@ -479,7 +479,7 @@ */ static void x_reply_selection_request (XSelectionRequestEvent *event, int format, - UChar_Binary *data, Bytecount size, Atom type) + Rawbyte *data, Bytecount size, Atom type) { /* This function can GC */ XSelectionEvent reply; @@ -531,7 +531,7 @@ PropertyDelete); XChangeProperty (display, window, reply.property, DEVICE_XATOM_INCR (d), - 32, PropModeReplace, (UChar_Binary *) + 32, PropModeReplace, (Rawbyte *) &bytes_remaining, 1); XSelectInput (display, window, PropertyChangeMask); /* Tell 'em the INCR data is there... */ @@ -642,7 +642,7 @@ make_opaque_ptr (event)); { - UChar_Binary *data; + Rawbyte *data; Bytecount size; int format; Atom type; @@ -653,7 +653,7 @@ successful_p = Qt; /* Tell x_selection_request_lisp_error() it's cool. */ event->type = 0; - xfree (data, UChar_Binary *); + xfree (data, Rawbyte *); } unbind_to (count); @@ -969,14 +969,14 @@ static void x_get_window_property (Display *display, Window window, Atom property, - UChar_Binary **data_ret, Bytecount *bytes_ret, + Rawbyte **data_ret, Bytecount *bytes_ret, Atom *actual_type_ret, int *actual_format_ret, unsigned long *actual_size_ret, int delete_p) { Bytecount total_size; unsigned long bytes_remaining; Bytecount offset = 0; - UChar_Binary *tmp_data = 0; + Rawbyte *tmp_data = 0; int result; Bytecount buffer_size = SELECTION_QUANTUM (display); if (buffer_size > MAX_SELECTION_QUANTUM) buffer_size = MAX_SELECTION_QUANTUM; @@ -1004,7 +1004,7 @@ } total_size = bytes_remaining + 1; - *data_ret = (UChar_Binary *) xmalloc (total_size); + *data_ret = xnew_rawbytes (total_size); /* Now read, until we've gotten it all. */ while (bytes_remaining) @@ -1041,7 +1041,7 @@ /* this one is for error messages only */ Lisp_Object UNUSED (target_type), Bytecount min_size_bytes, - UChar_Binary **data_ret, + Rawbyte **data_ret, Bytecount *size_bytes_ret, Atom *type_ret, int *format_ret, unsigned long *size_ret) @@ -1050,7 +1050,7 @@ Bytecount offset = 0; int prop_id; *size_bytes_ret = min_size_bytes; - *data_ret = (UChar_Binary *) xmalloc (*size_bytes_ret); + *data_ret = xnew_rawbytes (*size_bytes_ret); #if 0 stderr_out ("\nread INCR %d\n", min_size_bytes); #endif @@ -1066,7 +1066,7 @@ PropertyNewValue); while (1) { - UChar_Binary *tmp_data; + Rawbyte *tmp_data; Bytecount tmp_size_bytes; wait_for_property_change (prop_id); /* expect it again immediately, because x_get_window_property may @@ -1086,7 +1086,7 @@ #endif unexpect_property_change (prop_id); if (tmp_data) - xfree (tmp_data, UChar_Binary *); + xfree (tmp_data, Rawbyte *); break; } #if 0 @@ -1099,11 +1099,11 @@ *size_bytes_ret, offset + tmp_size_bytes); #endif *size_bytes_ret = offset + tmp_size_bytes; - *data_ret = (UChar_Binary *) xrealloc (*data_ret, *size_bytes_ret); + *data_ret = (Rawbyte *) xrealloc (*data_ret, *size_bytes_ret); } memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes); offset += tmp_size_bytes; - xfree (tmp_data, UChar_Binary *); + xfree (tmp_data, Rawbyte *); } } @@ -1120,7 +1120,7 @@ Atom actual_type; int actual_format; unsigned long actual_size; - UChar_Binary *data = NULL; + Rawbyte *data = NULL; Bytecount bytes = 0; Lisp_Object val; struct device *d = get_device_from_display (display); @@ -1152,7 +1152,7 @@ Bytecount min_size_bytes = /* careful here. */ (Bytecount) (* ((unsigned int *) data)); - xfree (data, UChar_Binary *); + xfree (data, Rawbyte *); receive_incremental_selection (display, window, property, target_type, min_size_bytes, &data, &bytes, &actual_type, &actual_format, @@ -1164,7 +1164,7 @@ val = selection_data_to_lisp_data (d, data, bytes, actual_type, actual_format); - xfree (data, UChar_Binary *); + xfree (data, Rawbyte *); return val; } @@ -1268,7 +1268,7 @@ Display *display = DEVICE_X_DISPLAY (d); Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */ Atom cut_buffer_atom; - UChar_Binary *data; + Rawbyte *data; Bytecount bytes; Atom type; int format; @@ -1296,7 +1296,7 @@ memchr (data, 0x1b, bytes) ? Qctext : Qbinary) : Qnil); - xfree (data, UChar_Binary *); + xfree (data, Rawbyte *); return ret; } @@ -1467,8 +1467,6 @@ void vars_of_select_x (void) { - reinit_vars_of_select_x (); - #ifdef CUT_BUFFER_SUPPORT cut_buffers_initialized = 0; Fprovide (intern ("cut-buffer")); diff --text -u 'xemacs-21.5.18/src/sgiplay.c' 'xemacs-21.5.19/src/sgiplay.c' Index: ./src/sgiplay.c --- ./src/sgiplay.c Tue Sep 21 04:19:59 2004 +++ ./src/sgiplay.c Fri Nov 5 08:06:53 2004 @@ -174,8 +174,8 @@ /* Forward declarations */ static Lisp_Object close_sound_file (Lisp_Object); -static AudioContext audio_initialize (UChar_Binary *, int, int); -static int play_internal (UChar_Binary *, int, AudioContext); +static AudioContext audio_initialize (Binbyte *, int, int); +static int play_internal (Binbyte *, int, AudioContext); static void drain_audio_port (AudioContext); static void write_mulaw_8_chunk (void *, void *, AudioContext); static void write_linear_chunk (void *, void *, AudioContext); @@ -205,7 +205,7 @@ { int count = specpdl_depth (); int input_fd; - UChar_Binary buffer[CHUNKSIZE]; + Binbyte buffer[CHUNKSIZE]; int bytes_read; AudioContext ac = (AudioContext) 0; @@ -256,7 +256,7 @@ } int -play_sound_data (UChar_Binary *data, int length, int volume) +play_sound_data (Binbyte *data, int length, int volume) { int count = specpdl_depth (); AudioContext ac; @@ -272,7 +272,7 @@ } static AudioContext -audio_initialize (UChar_Binary *data, int length, int volume) +audio_initialize (Binbyte *data, int length, int volume) { Lisp_Object audio_port_state[3]; static AudioContextRec desc; @@ -316,17 +316,17 @@ } static int -play_internal (UChar_Binary *data, int UNUSED (length), AudioContext ac) +play_internal (Binbyte *data, int UNUSED (length), AudioContext ac) { - UChar_Binary * limit; + Binbyte * limit; if (ac == (AudioContext) 0) return 0; - data = (UChar_Binary *) ac->ac_data; + data = (Binbyte *) ac->ac_data; limit = data + ac->ac_size; while (data < limit) { - UChar_Binary * chunklimit = data + CHUNKSIZE; + Binbyte * chunklimit = data + CHUNKSIZE; if (chunklimit > limit) chunklimit = limit; @@ -371,8 +371,8 @@ static void write_mulaw_8_chunk (void *buffer, void *chunklimit, AudioContext ac) { - UChar_Binary * data = (UChar_Binary *) buffer; - UChar_Binary * limit = (UChar_Binary *) chunklimit; + Binbyte * data = (Binbyte *) buffer; + Binbyte * limit = (Binbyte *) chunklimit; short * obuf, * bufp; long n_samples = limit - data; @@ -394,7 +394,7 @@ switch (ac->ac_format) { case AFlinear16: n_samples = (short *) limit - (short *) data; break; - case AFlinear8: n_samples = (Char_Binary *) limit - (Char_Binary *) data; break; + case AFlinear8: n_samples = (CBinbyte *) limit - (CBinbyte *) data; break; default: n_samples = (long *) limit - (long *) data; break; } ALwritesamps (ac->ac_port, data, (long) n_samples); @@ -607,7 +607,7 @@ int dataFormat; int samplingRate; int channelCount; - Char_Binary info[4]; + CBinbyte info[4]; } SNDSoundStruct; #define SOUND_TO_HOST_INT(x) ntohl(x) @@ -679,8 +679,8 @@ } desc->ac_output_rate = SOUND_TO_HOST_INT (hp->samplingRate); desc->ac_nchan = SOUND_TO_HOST_INT (hp->channelCount); - desc->ac_data = (Char_Binary *) header + SOUND_TO_HOST_INT (hp->dataLocation); - limit = (Char_Binary *) header + length - (Char_Binary *) desc->ac_data; + desc->ac_data = (CBinbyte *) header + SOUND_TO_HOST_INT (hp->dataLocation); + limit = (CBinbyte *) header + length - (CBinbyte *) desc->ac_data; desc->ac_size = SOUND_TO_HOST_INT (hp->dataSize); if (desc->ac_size > limit) desc->ac_size = limit; return 0; diff --text -u 'xemacs-21.5.18/src/signal.c' 'xemacs-21.5.19/src/signal.c' Index: ./src/signal.c --- ./src/signal.c Tue Sep 21 04:20:00 2004 +++ ./src/signal.c Wed Jan 26 19:33:42 2005 @@ -1,6 +1,6 @@ /* Handling asynchronous signals. Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. - Copyright (C) 1995, 1996, 2001, 2002 Ben Wing. + Copyright (C) 1995, 1996, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -258,7 +258,7 @@ /* If alarm() gets called when polling isn't disabled, it will mess up the asynchronous timeouts, and then C-g checking won't work again. Some libraries call alarm() directly, so we override the standard - library's alarm() and abort() if the caller of the library function + library's alarm() and ABORT() if the caller of the library function didn't wrap in stop_interrupts()/start_interrupts(). NOTE: We could potentially avoid the need to wrap by adding a @@ -311,7 +311,7 @@ case ITIMER_REAL: return setitimer (ITIMER_REAL, itnew, itold); case ITIMER_VIRTUAL: return setitimer (ITIMER_VIRTUAL, itnew, itold); case ITIMER_PROF: return setitimer (ITIMER_PROF, itnew, itold); - default: abort (); return 0; + default: ABORT (); return 0; } #endif } @@ -614,7 +614,7 @@ c = getc (stdin); stdout_out ("Abort (and dump core)? (y or n) "); if (((c = getc (stdin)) & ~040) == 'Y') - abort (); + ABORT (); while (c != '\n') c = getc (stdin); stdout_out ("Continuing...\n"); @@ -642,133 +642,12 @@ /* Control-G 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. */ - -/* OK, 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. - - 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 ^G, then set quit-flag but do not discard the ^G. - The callers of next_event_internal() will do one of two things: - - -- set Vquit_flag to Qnil. (next-event does this.) This will - cause the ^G to be treated as a normal keystroke. - -- 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. +/* - --ben - */ +Info on Control-G checking: + (Info-goto-node "(internals)Control-G (Quit) Checking") +*/ /* Defer all checking or processing of C-g. You can do this, for example, if you want to read C-g's as events. (In that case, you should set @@ -814,163 +693,11 @@ The C-g or Sh-C-g is discarded, so it won't be noticed again. */ + + void check_quit (void) { - /* 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 - -*/ int specdepth; if (dont_check_for_quit) @@ -981,10 +708,28 @@ #ifdef ERROR_CHECK_TRAPPING_PROBLEMS /* Since the code below can call Lisp, make sure that proper wrapping is in place during redisplay. */ +#if 0 assert_with_message (proper_redisplay_wrapping_in_place (), "QUIT called from within redisplay without being properly wrapped"); -#endif +#else + /* FUCKME! It looks like we cannot even check for QUIT, *EVER*, during + redisplay. Checking for quit can dispatch events, which can enter + redisplay recursively, which can trip on + +Fatal error: assertion failed, file c:\xemacs\build\src\redisplay.c, line 5532, +!dy->locked + +Backtrace given in + + (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT") + + */ + assert_with_message + (!in_display, + "QUIT called from within redisplay without being properly wrapped"); +#endif /* 0 */ +#endif /* ERROR_CHECK_TRAPPING_PROBLEMS */ /* Since arbitrary Lisp code may be executed (e.g. through a menu filter, see backtrace directly above), GC might happen, diff --text -u 'xemacs-21.5.18/src/sound.c' 'xemacs-21.5.19/src/sound.c' Index: ./src/sound.c --- ./src/sound.c Wed Sep 22 04:44:27 2004 +++ ./src/sound.c Fri Jan 28 11:36:26 2005 @@ -1,7 +1,7 @@ /* Sound functions. Copyright (C) 1992, 1993, 1994 Lucid Inc. Copyright (C) 1994, 1995 Free Software Foundation, Inc. - Copyright (C) 2002 Ben Wing. + Copyright (C) 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -53,7 +53,7 @@ #ifdef HAVE_ESD_SOUND extern int esd_play_sound_file (Extbyte *file, int vol); -extern int esd_play_sound_data (UChar_Binary *data, size_t length, 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 @@ -68,13 +68,13 @@ #ifdef HAVE_NAS_SOUND extern int nas_play_sound_file (Extbyte *name, int volume); -extern int nas_play_sound_data (UChar_Binary *data, int length, 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 Char_ASCII *string, Lisp_Object data) +report_sound_error (const Ascbyte *string, Lisp_Object data) { report_error_with_errno (Qsound_error, string, data); } @@ -161,20 +161,17 @@ #ifdef HAVE_NATIVE_SOUND if (NILP (Vnative_sound_only_on_console) || DEVICE_ON_CONSOLE_P (d)) { - Extbyte *fileext; - -#ifdef WIN32_NATIVE - /* #### more garbage. we should be passing the internal file name - to play_sound_file. */ - LISP_STRING_TO_EXTERNAL (file, fileext, Qmswindows_tstr); +#ifdef WIN32_ANY + nt_play_sound_file (file, vol); #else - LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name); -#endif + Extbyte *fileext; + LISP_PATHNAME_CONVERT_OUT (file, fileext); /* The sound code doesn't like getting SIGIO interrupts. Unix sucks! */ stop_interrupts (); play_sound_file (fileext, vol); start_interrupts (); +#endif /* WIN32_NATIVE */ QUIT; } #endif /* HAVE_NATIVE_SOUND */ @@ -346,7 +343,7 @@ #ifdef HAVE_NAS_SOUND if (DEVICE_CONNECTED_TO_NAS_P (d) && STRINGP (sound)) { - UChar_Binary *soundext; + Binbyte *soundext; Bytecount soundextlen; TO_EXTERNAL_FORMAT (LISP_STRING, sound, @@ -360,7 +357,7 @@ #ifdef HAVE_ESD_SOUND if (DEVICE_CONNECTED_TO_ESD_P (d) && STRINGP (sound)) { - UChar_Binary *soundext; + Binbyte *soundext; Bytecount soundextlen; int succes; @@ -381,7 +378,7 @@ if ((NILP (Vnative_sound_only_on_console) || DEVICE_ON_CONSOLE_P (d)) && STRINGP (sound)) { - UChar_Binary *soundext; + Binbyte *soundext; Bytecount soundextlen; int succes; diff --text -u 'xemacs-21.5.18/src/sound.h' 'xemacs-21.5.19/src/sound.h' Index: ./src/sound.h --- ./src/sound.h Wed Jun 5 18:57:12 2002 +++ ./src/sound.h Fri Jan 28 11:36:26 2005 @@ -27,7 +27,8 @@ /* Defined in *play.c */ void play_sound_file (Extbyte *name, int volume); -int play_sound_data (UChar_Binary *data, int length, int volume); +void nt_play_sound_file (Lisp_Object name, int volume); +int play_sound_data (Binbyte *data, int length, int volume); # define sound_perror(string) \ do { \ diff --text -u 'xemacs-21.5.18/src/specifier.c' 'xemacs-21.5.19/src/specifier.c' Index: ./src/specifier.c --- ./src/specifier.c Tue Sep 21 04:20:00 2004 +++ ./src/specifier.c Fri Feb 4 01:14:08 2005 @@ -65,8 +65,8 @@ static const struct memory_description ste_description_1[] = { { XD_LISP_OBJECT, offsetof (specifier_type_entry, symbol) }, - { XD_STRUCT_PTR, offsetof (specifier_type_entry, meths), 1, - &specifier_methods_description }, + { XD_BLOCK_PTR, offsetof (specifier_type_entry, meths), 1, + { &specifier_methods_description } }, { XD_END } }; @@ -337,7 +337,7 @@ return retval; } -static unsigned long +static Hashcode specifier_hash (Lisp_Object obj, int depth) { Lisp_Specifier *s = XSPECIFIER (obj); @@ -347,7 +347,7 @@ the most likely places where interesting stuff will be. */ return HASH5 ((HAS_SPECMETH_P (s, hash) ? SPECMETH (s, hash, (obj, depth)) : 0), - (unsigned long) s->methods, + (Hashcode) s->methods, internal_hash (s->global_specs, depth + 1), internal_hash (s->frame_specs, depth + 1), internal_hash (s->buffer_specs, depth + 1)); @@ -396,20 +396,20 @@ }; const struct memory_description specifier_description[] = { - { XD_STRUCT_PTR, offsetof (Lisp_Specifier, methods), 1, - &specifier_methods_description }, + { XD_BLOCK_PTR, offsetof (Lisp_Specifier, methods), 1, + { &specifier_methods_description } }, { XD_LO_LINK, offsetof (Lisp_Specifier, next_specifier) }, { XD_LISP_OBJECT, offsetof (Lisp_Specifier, global_specs) }, { XD_LISP_OBJECT, offsetof (Lisp_Specifier, device_specs) }, { XD_LISP_OBJECT, offsetof (Lisp_Specifier, frame_specs) }, { XD_LISP_OBJECT, offsetof (Lisp_Specifier, window_specs) }, { XD_LISP_OBJECT, offsetof (Lisp_Specifier, buffer_specs) }, - { XD_STRUCT_PTR, offsetof (Lisp_Specifier, caching), 1, - &specifier_caching_description }, + { XD_BLOCK_PTR, offsetof (Lisp_Specifier, caching), 1, + { &specifier_caching_description } }, { XD_LISP_OBJECT, offsetof (Lisp_Specifier, magic_parent) }, { XD_LISP_OBJECT, offsetof (Lisp_Specifier, fallback) }, - { XD_STRUCT_ARRAY, offsetof (Lisp_Specifier, data), 1, - specifier_extra_description_map }, + { XD_BLOCK_ARRAY, offsetof (Lisp_Specifier, data), 1, + { specifier_extra_description_map } }, { XD_END } }; @@ -1775,7 +1775,7 @@ tem = nconc2 (*orig_inst_list, list_to_build_up); else { - abort (); + ABORT (); tem = Qnil; } @@ -2567,7 +2567,7 @@ No. Errors are handled in Lisp primitives implementation. Invalid domain is a design error here - kkm. */ - abort (); + ABORT (); if (NILP (buffer) && !NILP (window)) buffer = WINDOW_BUFFER (XWINDOW (window)); @@ -3183,10 +3183,8 @@ ; else if (CONSP (instantiator)) { - Lisp_Object tail; - EXTERNAL_LIST_LOOP (tail, instantiator) + EXTERNAL_LIST_LOOP_2 (car, instantiator) { - Lisp_Object car = XCAR (tail); if (!VALID_SINGLE_DISPTABLE_INSTANTIATOR_P (car)) goto lose; } @@ -3295,7 +3293,7 @@ specifier_type_create (void) { the_specifier_type_entry_dynarr = Dynarr_new (specifier_type_entry); - dump_add_root_struct_ptr (&the_specifier_type_entry_dynarr, &sted_description); + dump_add_root_block_ptr (&the_specifier_type_entry_dynarr, &sted_description); Vspecifier_type_list = Qnil; staticpro (&Vspecifier_type_list); diff --text -u 'xemacs-21.5.18/src/specifier.h' 'xemacs-21.5.19/src/specifier.h' Index: ./src/specifier.h --- ./src/specifier.h Sun Jan 12 20:08:21 2003 +++ ./src/specifier.h Wed Jan 26 19:22:28 2005 @@ -115,7 +115,7 @@ If this function is not present, hashing behaves as if it returned zero. */ - unsigned long (*hash_method) (Lisp_Object specifier, int depth); + Hashcode (*hash_method) (Lisp_Object specifier, int depth); /* Validate method: Given an instantiator, verify that it's valid for this specifier type. If not, signal an error. @@ -330,7 +330,7 @@ &specifier_empty_extra_description; \ defsymbol_nodump (&type##_specifier_methods->predicate_symbol, pred_sym); \ add_entry_to_specifier_type_list (Q##type, type##_specifier_methods); \ - dump_add_root_struct_ptr (&type##_specifier_methods, \ + dump_add_root_block_ptr (&type##_specifier_methods, \ &specifier_methods_description); \ } while (0) @@ -434,7 +434,7 @@ /* #### get image instances out of domains! */ -/* #### I think the following should abort() rather than return nil +/* #### I think the following should ABORT() rather than return nil when an invalid domain is given; much more likely we'll catch design errors early. --ben */ diff --text -u 'xemacs-21.5.18/src/strftime.c' 'xemacs-21.5.19/src/strftime.c' Index: ./src/strftime.c --- ./src/strftime.c Fri Mar 29 13:48:37 2002 +++ ./src/strftime.c Tue Jan 25 08:34:10 2005 @@ -197,7 +197,7 @@ char buf[40]; if (sizeof (num) > 16) - abort (); + ABORT (); sprintf (buf, "%lu", (unsigned long) num); return add_str (string, buf, max); } diff --text -u 'xemacs-21.5.18/src/sunplay.c' 'xemacs-21.5.19/src/sunplay.c' Index: ./src/sunplay.c --- ./src/sunplay.c Wed Mar 13 17:52:59 2002 +++ ./src/sunplay.c Tue Jan 25 08:34:10 2005 @@ -42,7 +42,7 @@ static Audio_hdr dev_hdr; static int -init_device (int volume, UChar_Binary *data, int fd, +init_device (int volume, Binbyte *data, int fd, unsigned int *header_length) { #ifdef SUNOS4_0_3 @@ -54,7 +54,7 @@ reset_volume_p = 0; reset_device_p = 0; - if (data && fd) abort (); /* one or the other */ + if (data && fd) ABORT (); /* one or the other */ if (AUDIO_SUCCESS != audio_get_play_config (audio_fd, &dev_hdr)) { @@ -130,7 +130,7 @@ play_sound_file (Extbyte *sound_file, int volume) { int rrtn, wrtn; - UChar_Binary buf [255]; + Binbyte buf [255]; int file_fd; audio_fd = audio_open (); @@ -152,12 +152,12 @@ goto END_OF_PLAY; } - if (init_device (volume, (UChar_Binary *) 0, file_fd, (unsigned int *) 0)) + if (init_device (volume, (Binbyte *) 0, file_fd, (unsigned int *) 0)) goto END_OF_PLAY; while (1) { - rrtn = read (file_fd, (Char_Binary *) buf, sizeof (buf)); + rrtn = read (file_fd, (CBinbyte *) buf, sizeof (buf)); if (rrtn < 0) { sound_perror ("read"); @@ -168,7 +168,7 @@ while (1) { - wrtn = write (audio_fd, (Char_Binary *) buf, rrtn); + wrtn = write (audio_fd, (CBinbyte *) buf, rrtn); if (wrtn < 0) { sound_perror ("write"); @@ -206,7 +206,7 @@ int -play_sound_data (UChar_Binary *data, int length, int volume) +play_sound_data (Binbyte *data, int length, int volume) { int wrtn, start = 0; unsigned int ilen; @@ -217,7 +217,7 @@ if (length == 0) return 0; /* this is just to get a better error message */ - if (strncmp (".snd\0", (Char_Binary *) data, 4)) + if (strncmp (".snd\0", (CBinbyte *) data, 4)) { sound_warn ("Not valid audio data (bad magic number)"); goto END_OF_PLAY; @@ -246,7 +246,7 @@ while (1) { - wrtn = write (audio_fd, (Char_Binary *) (data+start), length-start); + wrtn = write (audio_fd, (CBinbyte *) (data+start), length-start); if (wrtn < 0) { sound_perror ("write"); diff --text -u 'xemacs-21.5.18/src/symbols.c' 'xemacs-21.5.19/src/symbols.c' Index: ./src/symbols.c --- ./src/symbols.c Tue Sep 21 04:20:00 2004 +++ ./src/symbols.c Tue Jan 25 08:34:11 2005 @@ -1113,7 +1113,7 @@ return valcontents; default: - abort (); + ABORT (); } return Qnil; /* suppress compiler warning */ } @@ -1289,7 +1289,7 @@ return; default: - abort (); + ABORT (); } } } @@ -1914,7 +1914,7 @@ break; } default: - abort (); + ABORT (); } store_symval_forwarding (symbol, valcontents, newval); @@ -2100,9 +2100,8 @@ (args)) { /* This function can GC */ - Lisp_Object symbol, tail, val = Qnil; int nargs; - struct gcpro gcpro1; + Lisp_Object retval = Qnil; GET_LIST_LENGTH (args, nargs); @@ -2110,16 +2109,15 @@ Fsignal (Qwrong_number_of_arguments, list2 (Qsetq_default, make_int (nargs))); - GCPRO1 (val); - - PROPERTY_LIST_LOOP (tail, symbol, val, args) + GC_PROPERTY_LIST_LOOP_3 (symbol, val, args) { val = Feval (val); Fset_default (symbol, val); + retval = val; } - UNGCPRO; - return val; + END_GC_PROPERTY_LIST_LOOP (symbol); + return retval; } /* Lisp functions for creating and removing buffer-local variables. */ @@ -2183,7 +2181,7 @@ return variable; default: - abort (); + ABORT (); } } @@ -2292,7 +2290,7 @@ } default: - abort (); + ABORT (); } } @@ -2366,7 +2364,7 @@ break; default: - abort (); + ABORT (); } } @@ -2684,7 +2682,7 @@ case SYMVAL_UNBOUND_MARKER: return Qnil; default: - abort (); return Qnil; + ABORT (); return Qnil; } } @@ -2914,7 +2912,7 @@ return MAGIC_HANDLER_MAKE_LOCAL; if (abort_if_not_found) - abort (); + ABORT (); invalid_argument ("Unrecognized symbol-value function", funsym); RETURN_NOT_REACHED (MAGIC_HANDLER_MAX); } @@ -3492,7 +3490,7 @@ if (!UNBOUNDP (f) && (!CONSP (f) || !EQ (XCAR (f), Qautoload))) \ signal_ferror (Qdll_error, "Attempt to redefine %s", subr_name (subr)); \ \ - newsubr = (Lisp_Subr *) xmalloc (sizeof (Lisp_Subr)); \ + newsubr = xnew (Lisp_Subr); \ memcpy (newsubr, subr, sizeof (Lisp_Subr)); \ subr->doc = (const char *)newsubr; \ subr = newsubr; \ diff --text -u 'xemacs-21.5.18/src/symsinit.h' 'xemacs-21.5.19/src/symsinit.h' Index: ./src/symsinit.h --- ./src/symsinit.h Tue Apr 6 07:49:56 2004 +++ ./src/symsinit.h Fri Jan 28 11:36:26 2005 @@ -26,13 +26,14 @@ /* Earliest environment initializations (dump-time and run-time). */ +void init_win32_very_very_early (void); + void init_data_very_early (void); void init_floatfns_very_early (void); void init_free_hook (void); void init_process_times_very_early (void); void init_ralloc (void); void init_signals_very_early (void); -void init_win32_very_early (void); void init_mswindows_dde_very_early (void); /* Early Lisp-engine initialization -- dump-time only for init, dump-time @@ -284,8 +285,7 @@ void init_provide_once (void); /* Initialize most variables (dump-time for vars_, dump-time and - post-pdump-load-time for reinit_vars). #### The reinit_() functions - should be called from emacs.c, not the corresponding vars_of_(). */ + post-pdump-load-time for reinit_vars). */ void vars_of_abbrev (void); void vars_of_alloc (void); @@ -406,6 +406,7 @@ void vars_of_process_unix (void); void vars_of_profile (void); void vars_of_ralloc (void); +void vars_of_realpath (void); void vars_of_redisplay (void); void vars_of_regex (void); void vars_of_scrollbar_x (void); @@ -429,7 +430,6 @@ void vars_of_undo (void); void reinit_vars_of_undo (void); void vars_of_unicode (void); -void reinit_vars_of_unicode (void); void vars_of_window (void); void reinit_vars_of_window (void); void vars_of_win32 (void); @@ -500,7 +500,6 @@ void init_lread (void); void init_macros (void); void init_mswindows_environment (void); -void init_mule_charset (void); void init_nt (void); void init_postgresql_from_environment (void); void init_redisplay (void); diff --text -u 'xemacs-21.5.18/src/syntax.c' 'xemacs-21.5.19/src/syntax.c' Index: ./src/syntax.c --- ./src/syntax.c Wed Sep 22 11:06:51 2004 +++ ./src/syntax.c Wed Jan 26 14:11:12 2005 @@ -448,8 +448,8 @@ tmp_table = get_char_property (pos, Qsyntax_table, cache->object, EXTENT_AT_AFTER, 0); - lim = next_single_property_change (pos, Qsyntax_table, cache->object, - -1); + lim = next_previous_single_property_change (pos, Qsyntax_table, + cache->object, -1, 1, 0); if (lim < 0) { next = buffer_or_string_absolute_end_byte (cache->object); @@ -460,8 +460,8 @@ if (pos < buffer_or_string_absolute_end_byte (cache->object)) pos = next_bytexpos (cache->object, pos); - lim = previous_single_property_change (pos, Qsyntax_table, cache->object, - -1); + lim = next_previous_single_property_change (pos, Qsyntax_table, + cache->object, -1, 0, 0); if (lim < 0) { prev = buffer_or_string_absolute_begin_byte (cache->object); diff --text -u 'xemacs-21.5.18/src/sysdep.c' 'xemacs-21.5.19/src/sysdep.c' Index: ./src/sysdep.c --- ./src/sysdep.c Wed Oct 20 02:19:07 2004 +++ ./src/sysdep.c Fri Jan 28 11:36:27 2005 @@ -1,7 +1,7 @@ /* Interfaces to system-dependent kernel and library entries. Copyright (C) 1985-1988, 1992-1995 Free Software Foundation, Inc. Copyright (C) 1995 Tinker Systems. - Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -616,7 +616,7 @@ dir = Funhandled_file_name_directory (dir); dir = expand_and_dir_to_file (dir, Qnil); - str = (Ibyte *) ALLOCA (XSTRING_LENGTH (dir) + 2); + str = alloca_ibytes (XSTRING_LENGTH (dir) + 2); len = XSTRING_LENGTH (dir); memcpy (str, XSTRING_DATA (dir), len); if (!IS_ANY_SEP (str[len - 1])) @@ -628,7 +628,7 @@ if (sh == 0) sh = (Ibyte *) "sh"; - C_STRING_TO_EXTERNAL (sh, shext, Qfile_name); + PATHNAME_CONVERT_OUT (sh, shext); UNGCPRO; @@ -638,7 +638,10 @@ qxe_chdir (str); /* Waits for process completion */ - if (_spawnlp (_P_WAIT, shext, shext, NULL) != 0) + if (XEUNICODE_P ? + _wspawnlp (_P_WAIT, (const wchar_t *) shext, + (const wchar_t *) shext, NULL) != 0 : + _spawnlp (_P_WAIT, shext, shext, NULL) != 0) report_process_error ("Can't spawn subshell", Qunbound); else return; /* we're done, no need to wait for termination */ @@ -958,7 +961,7 @@ sg.sg_ospeed = B9600; if (ioctl (input_fd, TIOCGETP, &sg) < 0) - abort (); + ABORT (); DEVICE_TTY_DATA (d)->ospeed = sg.sg_ospeed; #endif } @@ -2299,6 +2302,7 @@ Vsystem_name = build_string (uts.nodename); #else /* HAVE_GETHOSTNAME */ int hostname_size = 256; + /* !!#### Needs review */ char *hostname = (char *) ALLOCA (hostname_size); /* Try to get the host name; if the buffer is too short, try @@ -2315,6 +2319,7 @@ break; hostname_size <<= 1; + /* !!#### Needs review */ hostname = (char *) ALLOCA (hostname_size); } # if defined( HAVE_SOCKETS) @@ -2356,6 +2361,7 @@ if (*alias) fqdn = *alias; } + /* !!#### Needs review */ hostname = (char *) ALLOCA (strlen (fqdn) + 1); strcpy (hostname, fqdn); } @@ -2373,6 +2379,7 @@ hints.ai_protocol = 0; if (!getaddrinfo (hostname, NULL, &hints, &res)) { + /* !!#### Needs review */ hostname = (char *) ALLOCA (strlen (res->ai_canonname) + 1); strcpy (hostname, res->ai_canonname); @@ -2533,18 +2540,6 @@ /* Encapsulations of system calls */ /************************************************************************/ -/* The documentation in VC++ claims that the pathname library functions - accept strings in the current locale-specific encoding, but that's - false, because they just call the native Win32 routines directly, which - always use the system-default encoding (which is what Qmswindows_tstr - will give us when not XEUNICODE_P). */ -#ifdef WIN32_NATIVE -#define PATHNAME_CONVERT_OUT(path, pathout) C_STRING_TO_TSTR (path, pathout) -#else -#define PATHNAME_CONVERT_OUT(path, pathout) \ - C_STRING_TO_EXTERNAL (path, pathout, Qfile_name) -#endif - /***************** low-level calls ****************/ /* @@ -2578,7 +2573,8 @@ #endif /* WIN32_NATIVE */ -/* Just one call with normal open() semantics. */ +/* Just call open() with normal open() semantics, with some fixups for + problems under Windows. */ static int underlying_open (const Extbyte *path, int oflag, int mode) @@ -2599,18 +2595,9 @@ #endif /* WIN32_NATIVE */ } -/* Like qxe_open() below but operates on externally-encoded filenames. */ - -int XCDECL -retry_open (const Extbyte *path, int oflag, ...) +static int +retry_open_1 (const Extbyte *path, int oflag, int mode) { - int mode; - va_list ap; - - va_start (ap, oflag); - mode = va_arg (ap, int); - va_end (ap); - #ifdef INTERRUPTIBLE_OPEN { int rtnval; @@ -2624,6 +2611,44 @@ #endif } +/* A version of open() that retries when interrupted. Operates on + externally-encoded filenames. */ + +int XCDECL +retry_open (const Extbyte *path, int oflag, ...) +{ + int mode; + va_list ap; + + va_start (ap, oflag); + mode = va_arg (ap, int); + va_end (ap); + + return retry_open_1 (path, oflag, mode); +} + +#if defined (WIN32_NATIVE) && defined (WEXTTEXT_IS_WIDE) + +/* Like retry_open() but operate on Wexttext filenames. */ + +int XCDECL +wext_retry_open (const Wexttext *path, int oflag, ...) +{ + int mode; + va_list ap; + + va_start (ap, oflag); + mode = va_arg (ap, int); + va_end (ap); + + if (!XEUNICODE_P) + return retry_open_1 (WEXTTEXT_TO_MULTIBYTE (path), oflag, mode); + else + return retry_open_1 ((Extbyte *) path, oflag, mode); +} + +#endif + /* The basic external entry point to open(). Handles conversion to external encoding, interruptions, etc. */ @@ -2784,12 +2809,12 @@ #### Should conceivably encapsulate getchar() etc. What a pain! */ FILE * -retry_fopen (const Extbyte *path, const Char_ASCII *mode) +retry_fopen (const Extbyte *path, const Ascbyte *mode) { #ifdef WIN32_NATIVE int fd; int oflag; - const Char_ASCII *mode_save = mode; + const Ascbyte *mode_save = mode; /* Force all file handles to be non-inheritable. This is necessary to ensure child processes don't unwittingly inherit handles that might @@ -2839,7 +2864,7 @@ } FILE * -qxe_fopen (const Ibyte *path, const Char_ASCII *mode) +qxe_fopen (const Ibyte *path, const Ascbyte *mode) { Extbyte *pathout; PATHNAME_CONVERT_OUT (path, pathout); @@ -3105,7 +3130,7 @@ } } #else - Extbyte chingame_limitos_arbitrarios[PATH_MAX]; + Extbyte chingame_limitos_arbitrarios[PATH_MAX_EXTERNAL]; Ibyte *ret2; if (!getwd (chingame_limitos_arbitrarios)) @@ -3146,6 +3171,51 @@ In that case, use ordinary stat instead. */ #ifndef S_IFLNK return qxe_stat (path, buf); +#elif defined (WIN32_NATIVE) + if (mswindows_shortcuts_are_symlinks) + { + /* We want to resolve the directory component and leave the rest + alone. */ + Ibyte *dirend = find_end_of_directory_component (path, qxestrlen (path)); + Bytecount len; + + if (dirend != path) + { + Ibyte *resdir; + Ichar lastch; + DECLARE_EISTRING (resname); + DECLARE_EISTRING (dir); + + eicpy_raw (dir, path, dirend - path); + PATHNAME_RESOLVE_LINKS (eidata (dir), resdir); + eicpy_rawz (resname, resdir); + lastch = eigetch_char (resname, eicharlen (resname) - 1); + if (!IS_DIRECTORY_SEP (lastch)) + eicat_ch (resname, '\\'); + eicat_rawz (resname, dirend); + path = eidata (resname); + } + + /* However, if what we are trying to stat is a link, we need to add + the .LNK so that the actual file is statted. */ + len = qxestrlen (path); + if (len > 4 && qxestrcasecmp_ascii (path + len - 4, ".LNK")) + { + DECLARE_EISTRING (name2); + Ibyte *resolved; + + eicpy_rawz (name2, path); + eicat_ascii (name2, ".LNK"); + resolved = mswindows_read_link (eidata (name2)); + if (resolved) + { + xfree (resolved, Ibyte *); + return mswindows_stat (eidata (name2), buf); + } + } + } + + return mswindows_stat (path, buf); #else Extbyte *pathout; PATHNAME_CONVERT_OUT (path, pathout); @@ -3193,7 +3263,9 @@ qxe_stat (const Ibyte *path, struct stat *buf) { #ifdef WIN32_NATIVE - return mswindows_stat (path, buf); + Ibyte *resolved; + PATHNAME_RESOLVE_LINKS (path, resolved); + return mswindows_stat (resolved, buf); #else /* not WIN32_NATIVE */ Extbyte *pathout; PATHNAME_CONVERT_OUT (path, pathout); @@ -3417,7 +3489,7 @@ #ifndef HAVE_WCHAR_H size_t -wcslen(const wchar_t *s) +wcslen (const wchar_t *s) { const wchar_t *p = s; diff --text -u 'xemacs-21.5.18/src/sysfile.h' 'xemacs-21.5.19/src/sysfile.h' Index: ./src/sysfile.h --- ./src/sysfile.h Fri May 9 18:50:42 2003 +++ ./src/sysfile.h Fri Jan 28 11:36:27 2005 @@ -1,6 +1,6 @@ /* Copyright (C) 1995 Free Software Foundation, Inc. - Copyright (C) 2000, 2001, 2002 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -238,6 +238,13 @@ #undef S_ISSOCK #endif /* STAT_MACROS_BROKEN. */ +#ifdef WIN32_NATIVE +/* This is the standard value for S_IFLNK. All of the S_... flags that + exist in the MSVCRT have standard values, so their bit tests will + magically work. */ +#define S_IFLNK 0120000 +#endif + #if !defined(S_ISBLK) && defined(S_IFBLK) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #endif @@ -267,19 +274,42 @@ #define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) #endif -/* Client .c files should simply use `PATH_MAX'. */ -#ifndef PATH_MAX -# if defined (_MAX_PATH) +/* Determining the maximum pathname length. + + NOTE: IN GENERAL, YOU SHOULD NOT USE THIS. + If at all possible, avoid using fixed-length buffers of any sort. + You cannot guarantee on many systems that pathnames won't exceed + these limits for one reason or another. + + Unfortunately, there is no universal agreement over whether these + values should include a final null-terminator or not. Even recent + versions of Linux (circa 2002) are switching from the not-including- + terminator kind to the including-terminator kind. So we assume that + the including-terminator kind will be even (usually is), and round + up as necessary. */ + +#define ROUND_UP_TO_EVEN_NUMBER(val) (((val + 1) >> 1) << 1) +#ifdef PATH_MAX +# define QXE_PATH_MAX ROUND_UP_TO_EVEN_NUMBER (PATH_MAX) +#elif defined (_MAX_PATH) /* MS Win -- and preferable to _POSIX_PATH_MAX, which is also defined */ -# define PATH_MAX _MAX_PATH -# elif defined (_POSIX_PATH_MAX) -# define PATH_MAX _POSIX_PATH_MAX -# elif defined (MAXPATHLEN) -# define PATH_MAX MAXPATHLEN -# else -# define PATH_MAX 1024 -# endif -#endif +# define QXE_PATH_MAX ROUND_UP_TO_EVEN_NUMBER (_MAX_PATH) +#elif defined (_POSIX_PATH_MAX) +# define QXE_PATH_MAX ROUND_UP_TO_EVEN_NUMBER (_POSIX_PATH_MAX) +#elif defined (MAXPATHLEN) +# define QXE_PATH_MAX ROUND_UP_TO_EVEN_NUMBER (MAXPATHLEN) +#else +# define QXE_PATH_MAX 1024 +#endif + +/* Client .c files should use PATH_MAX_INTERNAL or PATH_MAX_EXTERNAL + if they must use either one at all. */ + +/* Use for internally formatted text, which can potentially have up to + four bytes per character */ +#define PATH_MAX_INTERNAL (QXE_PATH_MAX * MAX_ICHAR_LEN) +/* Use for externally formatted text. */ +#define PATH_MAX_EXTERNAL (QXE_PATH_MAX * MAX_XETCHAR_SIZE) /* The following definitions are needed under Windows, at least */ #ifndef X_OK @@ -341,8 +371,8 @@ size_t retry_fread (void *, size_t, size_t, FILE *); size_t retry_fwrite (const void *, size_t, size_t, FILE *); -FILE *retry_fopen (const Extbyte *path, const Char_ASCII *mode); -FILE *qxe_fopen (const Ibyte *path, const Char_ASCII *mode); +FILE *retry_fopen (const Extbyte *path, const Ascbyte *mode); +FILE *qxe_fopen (const Ibyte *path, const Ascbyte *mode); int retry_fclose (FILE *); /* encapsulations: file-information calls */ @@ -353,7 +383,8 @@ int qxe_readlink (const Ibyte *path, Ibyte *buf, size_t bufsiz); int qxe_fstat (int fd, struct stat *buf); int qxe_stat (const Ibyte *path, struct stat *buf); -Ibyte *qxe_realpath (const Ibyte *path, Ibyte resolved_path []); +Ibyte *qxe_realpath (const Ibyte *path, Ibyte resolved_path [], + Boolint links_only); /* encapsulations: file-manipulation calls */ @@ -376,6 +407,10 @@ on systems like SCO 3.2v5 */ void filemodestring (struct stat *, char *); +#ifdef WIN32_ANY +extern int mswindows_shortcuts_are_symlinks; +#endif + #endif /* emacs */ @@ -484,6 +519,50 @@ #endif /* WIN32_ANY */ +#if defined (WIN32_NATIVE) +#define PATHNAME_RESOLVE_LINKS(path, pathout) \ +do \ +{ \ + if (mswindows_shortcuts_are_symlinks) \ + { \ + Ibyte *_prl_path_ = (Ibyte *) (path); \ + Ibyte _prl_path2_[PATH_MAX_INTERNAL]; \ + \ + if (!qxe_realpath (_prl_path_, _prl_path2_, 1)) \ + (pathout) = _prl_path_; \ + else \ + IBYTE_STRING_TO_ALLOCA (_prl_path2_, pathout); \ + } \ + else (pathout) = (Ibyte *) (path); \ +} while (0) +#else +#define PATHNAME_RESOLVE_LINKS(path, pathout) ((pathout) = (Ibyte *) (path)) +#endif + +#define LISP_PATHNAME_RESOLVE_LINKS(path, pathout) \ + PATHNAME_RESOLVE_LINKS (XSTRING_DATA (path), pathout) + +/* The documentation in VC++ claims that the pathname library functions + accept strings in the current locale-specific encoding, but that's + false, because they just call the native Win32 routines directly, which + always use the system-default encoding (which is what Qmswindows_tstr + will give us when not XEUNICODE_P). */ +#ifdef WIN32_NATIVE +# define PATHNAME_CONVERT_OUT(path, pathout) \ +do \ +{ \ + const Ibyte *_pco_path_; \ + PATHNAME_RESOLVE_LINKS (path, _pco_path_); \ + C_STRING_TO_TSTR (_pco_path_, pathout); \ +} while (0) +#else +# define PATHNAME_CONVERT_OUT(path, pathout) \ + C_STRING_TO_EXTERNAL (path, pathout, Qfile_name) +#endif + +#define LISP_PATHNAME_CONVERT_OUT(path, pathout) \ + PATHNAME_CONVERT_OUT (XSTRING_DATA (path), pathout) + #endif /* emacs */ #endif /* INCLUDED_sysfile_h_ */ diff --text -u 'xemacs-21.5.18/src/sysproc.h' 'xemacs-21.5.19/src/sysproc.h' Index: ./src/sysproc.h --- ./src/sysproc.h Tue Sep 21 04:20:02 2004 +++ ./src/sysproc.h Fri Feb 4 12:01:21 2005 @@ -41,10 +41,6 @@ This is not true with visual c though. The trick below works with VC4.2b, 5.0 and 6.0. It assumes that VC is installed in a kind of standard way, so include path ends with /include. - NOTE: We also include this same file in s/windowsnt.h, to avoid problems - because this file prototypes abort() and then lisp.h defines it as a - macro, which must happen after the prototype. DO NOT remove the include - here just because you "know" it's somewhere else as well. */ #include <../include/process.h> #endif diff --text -u 'xemacs-21.5.18/src/syswindows.h' 'xemacs-21.5.19/src/syswindows.h' Index: ./src/syswindows.h --- ./src/syswindows.h Tue Oct 14 14:03:07 2003 +++ ./src/syswindows.h Fri Jan 28 11:36:27 2005 @@ -1,5 +1,5 @@ /* Copyright (C) 2000 Free Software Foundation, Inc. - Copyright (C) 2000, 2001, 2002 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -39,24 +39,7 @@ #ifndef INCLUDED_syswindows_h_ #define INCLUDED_syswindows_h_ -/* There are two different general Windows-related include files in src. - - Uses are approximately: - - syswindows.h: Wrapper around <windows.h>, 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. -*/ - -/* See s/windowsnt.h for a description of what exactly the various - constants such as WIN32_NATIVE, HAVE_MS_WINDOWS, CYGWIN, and MINGW - mean, and how they relate to each other. */ +/* See win32.c for info about the different Windows files in XEmacs. */ /* ------------------------- Basic includes ------------------------- */ @@ -519,7 +502,7 @@ /* ------------------------- Unicode encapsulation ------------------------- */ -/* See intl-encap-win32.c for more information about Unicode-encapsulation */ +/* See intl-win32.c for more information about Unicode-encapsulation */ #define ERROR_WHEN_NONINTERCEPTED_FUNS_USED @@ -596,6 +579,38 @@ #endif BOOL qxeUpdateICMRegKey (DWORD arg1, Extbyte * arg2, Extbyte * arg3, UINT arg4); +/* would be encapsulatable but for header changes in different versions of VC++ */ + +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef EnumResourceTypes +#define EnumResourceTypes error_use_qxeEnumResourceTypes_or_EnumResourceTypesA_and_EnumResourceTypesW +#endif +#if MSC_VERSION >= 1300 +BOOL qxeEnumResourceTypes (HMODULE hModule, ENUMRESTYPEPROCW lpEnumFunc, LONG lParam); +#else +BOOL qxeEnumResourceTypes (HMODULE hModule, ENUMRESTYPEPROC lpEnumFunc, LONG lParam); +#endif + +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef EnumResourceNames +#define EnumResourceNames error_use_qxeEnumResourceNames_or_EnumResourceNamesA_and_EnumResourceNamesW +#endif +#if MSC_VERSION >= 1300 +BOOL qxeEnumResourceNames (HMODULE hModule, const Extbyte * lpType, ENUMRESNAMEPROCW lpEnumFunc, LONG lParam); +#else +BOOL qxeEnumResourceNames (HMODULE hModule, const Extbyte * lpType, ENUMRESNAMEPROC lpEnumFunc, LONG lParam); +#endif + +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef EnumResourceLanguages +#define EnumResourceLanguages error_use_qxeEnumResourceLanguages_or_EnumResourceLanguagesA_and_EnumResourceLanguagesW +#endif +#if MSC_VERSION >= 1300 +BOOL qxeEnumResourceLanguages (HMODULE hModule, const Extbyte * lpType, const Extbyte * lpName, ENUMRESLANGPROCW lpEnumFunc, LONG lParam); +#else +BOOL qxeEnumResourceLanguages (HMODULE hModule, const Extbyte * lpType, const Extbyte * lpName, ENUMRESLANGPROC lpEnumFunc, LONG lParam); +#endif + /* files */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef FindFirstFile @@ -695,17 +710,33 @@ #endif HFONT qxeCreateFontIndirect (CONST LOGFONTW *lplf); +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ImmSetCompositionFont #define ImmSetCompositionFont error use qxeImmSetCompositionFont or ImmSetCompositionFontA/ImmSetCompositionFontW #endif BOOL qxeImmSetCompositionFont (HIMC imc, LOGFONTW *lplf); +#endif /* defined (HAVE_MS_WINDOWS) */ +#if defined (HAVE_MS_WINDOWS) #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef ImmGetCompositionFont #define ImmGetCompositionFont error use qxeImmGetCompositionFont or ImmGetCompositionFontA/ImmGetCompositionFontW #endif BOOL qxeImmGetCompositionFont (HIMC imc, LOGFONTW *lplf); +#endif /* defined (HAVE_MS_WINDOWS) */ + +#if defined (HAVE_MS_WINDOWS) +#ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED +#undef ImmSetCompositionString +#define ImmSetCompositionString error_use_qxeImmSetCompositionString_or_ImmSetCompositionStringA_and_ImmSetCompositionStringW +#endif +#if MSC_VERSION >= 1300 +BOOL qxeImmSetCompositionString (HIMC arg1, DWORD dwIndex, LPVOID lpComp, DWORD arg4, LPCVOID lpRead, DWORD arg6); +#else +BOOL qxeImmSetCompositionString (HIMC arg1, DWORD dwIndex, LPCVOID lpComp, DWORD arg4, LPCVOID lpRead, DWORD arg6); +#endif +#endif /* defined (HAVE_MS_WINDOWS) */ #ifdef ERROR_WHEN_NONINTERCEPTED_FUNS_USED #undef GetObject @@ -762,7 +793,7 @@ /* Set early in command-line processing, when -nuni or --no-unicode-lib-calls is seen. */ extern int no_mswin_unicode_lib_calls; -/* Set early, in init_win32_very_early(). */ +/* Set early, in init_win32_very_very_early(). */ extern int mswindows_windows9x_p; #define XEUNICODE_P (!mswindows_windows9x_p && !no_mswin_unicode_lib_calls) @@ -777,26 +808,26 @@ #define XETEXT(arg) XETEXT1(arg) #define XECOPY_TCHAR(ptr, ch) \ (XEUNICODE_P ? (* (LPWSTR) (ptr) = L##ch) : (* (LPSTR) (ptr) = (ch))) -#define xetcslen(arg) \ +#define qxetcslen(arg) \ (XEUNICODE_P ? wcslen ((wchar_t *) arg) : strlen (arg)) -#define xetcsbytelen(arg) \ +#define qxetcsbytelen(arg) \ (XEUNICODE_P ? wcslen ((wchar_t *) arg) * XETCHAR_SIZE : strlen (arg)) -#define xetcscmp(s1, s2) \ +#define qxetcscmp(s1, s2) \ (XEUNICODE_P ? wcscmp ((wchar_t *) s1, (wchar_t *) s2) \ : strcmp (s1, s2)) -#define xetcscpy(s1, s2) \ +#define qxetcscpy(s1, s2) \ (XEUNICODE_P ? (char *) wcscpy ((wchar_t *) s1, (wchar_t *) s2) \ : strcpy (s1, s2)) -#define xetcsncpy(s1, s2, n) \ +#define qxetcsncpy(s1, s2, n) \ (XEUNICODE_P ? (char *) wcsncpy ((wchar_t *) s1, (wchar_t *) s2, n) \ : strncpy (s1, s2, n)) -#define xetcschr(s, ch) \ +#define qxetcschr(s, ch) \ (XEUNICODE_P ? (char *) wcschr ((wchar_t *) s, (WCHAR) ch) \ : strchr (s, ch)) -#define xetcsrchr(s, ch) \ +#define qxetcsrchr(s, ch) \ (XEUNICODE_P ? (char *) wcsrchr ((wchar_t *) s, (WCHAR) ch) \ : strrchr (s, ch)) -#define xetcsdup(s) \ +#define qxetcsdup(s) \ (XEUNICODE_P ? (char *) wcsdup ((wchar_t *) s) \ : xstrdup (s)) @@ -810,7 +841,7 @@ EXTERNAL_TO_C_STRING_MALLOC (in, out, Qmswindows_tstr) #define build_tstr_string(in) \ - make_ext_string (in, xetcsbytelen ((Extbyte *) in), Qmswindows_tstr) + make_ext_string (in, qxetcsbytelen ((Extbyte *) in), Qmswindows_tstr) #define MAX_ANSI_CHAR_LEN 1 #define MAX_UNICODE_CHAR_LEN 2 @@ -832,11 +863,58 @@ Extbyte *convert_multibyte_to_unicode_malloc (const Extbyte *src, Bytecount n, int cp, Bytecount *size_out); +Extbyte *convert_unicode_to_multibyte_malloc (const Extbyte *src, + Bytecount n, + int cp, Bytecount *size_out); Ibyte *convert_multibyte_to_internal_malloc (const Extbyte *src, Bytecount n, int cp, Bytecount *size_out); void convert_multibyte_to_unicode_dynarr (const Extbyte *src, Bytecount n, int cp, unsigned_char_dynarr *dst); +void convert_unicode_to_multibyte_dynarr (const Extbyte *src, Bytecount n, + int cp, unsigned_char_dynarr *dst); + +Bytecount unicode_multibyte_convert_size (const char *srctext, const void *src, + Bytecount src_size, int to_unicode, + int cp); +void *unicode_multibyte_convert_copy_data (const char *srctext, + void *alloca_data); + +/* NOTE: If you make two invocations of the following functions in the same + subexpression and use the exact same expression for the source in both + cases, you will lose. In this unlikely case, you may get an abort, and + need to rewrite the code. + + We need to use ALLOCA_FUNCALL_OK here, see NEW_DFC in text.h. +*/ + +#ifdef WEXTTEXT_IS_WIDE +#define MULTIBYTE_TO_WEXTTEXT(str) \ + ((Wexttext *) \ + unicode_multibyte_convert_copy_data \ + (#str, ALLOCA_FUNCALL_OK (unicode_multibyte_convert_size \ + (#str, str, strlen (str) + 1, 1, CP_ACP)))) + +#define WEXTTEXT_TO_MULTIBYTE(str) \ + ((Extbyte *) \ + unicode_multibyte_convert_copy_data \ + (#str, ALLOCA_FUNCALL_OK (unicode_multibyte_convert_size \ + (#str, str, \ + (wcslen (str) + 1) * sizeof (WCHAR), 0, \ + CP_ACP)))) +#else +#define MULTIBYTE_TO_WEXTTEXT(str) ((Wexttext *) (str)) +#define WEXTTEXT_TO_MULTIBYTE(str) ((Extbyte *) (str)) +#endif + +/* #### mbstowcs() uses MB_ERR_INVALID_CHARS in addition to MB_PRECOMPOSED. + Should we do this? But then we have to handle errors. + #### Do we already check for invalid sequences in the coding system? */ +#define MBTOWC_OPTIONS MB_PRECOMPOSED /* | MB_ERR_INVALID_CHARS */ + /* The following options are what wcstombs() uses in the CRT. It uses + NULL in place of "~". */ +#define WCTOMB_OPTIONS WC_COMPOSITECHECK | WC_SEPCHARS +#define WCTOMB_INVALID_STRING "~" /* ------------------------- Other Mule stuff ------------------------- */ @@ -861,10 +939,10 @@ #define LOCAL_FILE_FORMAT_TO_TSTR(path, out) \ do { \ - Ibyte *lttff; \ + Ibyte *lttff; \ \ LOCAL_TO_WIN32_FILE_FORMAT (XSTRING_DATA (path), lttff); \ - C_STRING_TO_TSTR (lttff, out); \ + PATHNAME_CONVERT_OUT (lttff, out); \ } while (0) Lisp_Object tstr_to_local_file_format (Extbyte *pathout); @@ -895,7 +973,7 @@ { \ int ltwff2 = \ cygwin_posix_to_win32_path_list_buf_size ((char *) ltwffp); \ - pathout = (Ibyte *) ALLOCA (ltwff2); \ + pathout = alloca_ibytes (ltwff2); \ cygwin_posix_to_win32_path_list ((char *) ltwffp, (char *) pathout); \ } \ } while (0) @@ -912,7 +990,7 @@ Ibyte *wtlff1 = (path); \ int wtlff2 = \ cygwin_win32_to_posix_path_list_buf_size ((char *) wtlff1); \ - Ibyte *wtlff3 = (Ibyte *) ALLOCA (wtlff2); \ + Ibyte *wtlff3 = alloca_ibytes (wtlff2); \ cygwin_win32_to_posix_path_list ((char *) wtlff1, (char *) wtlff3); \ (pathout) = wtlff3; \ } while (0) @@ -928,40 +1006,40 @@ #ifdef CYGWIN -#define LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR(lispstr, pathout) \ -do \ -{ \ - Ibyte *lffmutt_fname1; \ - Ibyte *lffmutt_pathint = XSTRING_DATA (lispstr); \ - \ - if ((lffmutt_fname1 = qxestrchr (lffmutt_pathint, ':')) != NULL \ - && *++lffmutt_fname1 == '/' && *++lffmutt_fname1 == '/') \ - { \ - /* If URL style file, the innards may have Cygwin mount points and \ - the like. so separate out the innards, process them, and put back \ - together. */ \ - if (qxestrncasecmp_c (lffmutt_pathint, "file://", 7) == 0) \ - { \ - Ibyte *lffmutt_path1, *lffmutt_path2; \ - LOCAL_TO_WIN32_FILE_FORMAT (lffmutt_pathint + 7, lffmutt_path1); \ - if (lffmutt_path1 == lffmutt_pathint + 7) /* Optimization */ \ - lffmutt_path2 = lffmutt_pathint; \ - else \ - { \ +#define LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR(lispstr, pathout) \ +do \ +{ \ + Ibyte *lffmutt_fname1; \ + Ibyte *lffmutt_pathint = XSTRING_DATA (lispstr); \ + \ + if ((lffmutt_fname1 = qxestrchr (lffmutt_pathint, ':')) != NULL \ + && *++lffmutt_fname1 == '/' && *++lffmutt_fname1 == '/') \ + { \ + /* If URL style file, the innards may have Cygwin mount points and \ + the like. so separate out the innards, process them, and put back \ + together. */ \ + if (qxestrncasecmp_ascii (lffmutt_pathint, "file://", 7) == 0) \ + { \ + Ibyte *lffmutt_path1, *lffmutt_path2; \ + LOCAL_TO_WIN32_FILE_FORMAT (lffmutt_pathint + 7, lffmutt_path1); \ + if (lffmutt_path1 == lffmutt_pathint + 7) /* Optimization */ \ + lffmutt_path2 = lffmutt_pathint; \ + else \ + { \ lffmutt_path2 = alloca_ibytes (7 + qxestrlen (lffmutt_path1) \ - + 1); \ - qxestrncpy (lffmutt_path2, lffmutt_pathint, 7); \ - qxestrcpy (lffmutt_path2 + 7, lffmutt_path1); \ - } \ - C_STRING_TO_TSTR (lffmutt_path2, pathout); \ - } \ - else \ - /* A straight URL, just convert */ \ - LISP_STRING_TO_TSTR (lispstr, pathout); \ - } \ - else \ - /* Not URL-style, must be a straight filename. */ \ - LOCAL_FILE_FORMAT_TO_TSTR (lispstr, pathout); \ + + 1); \ + qxestrncpy (lffmutt_path2, lffmutt_pathint, 7); \ + qxestrcpy (lffmutt_path2 + 7, lffmutt_path1); \ + } \ + C_STRING_TO_TSTR (lffmutt_path2, pathout); \ + } \ + else \ + /* A straight URL, just convert */ \ + LISP_STRING_TO_TSTR (lispstr, pathout); \ + } \ + else \ + /* Not URL-style, must be a straight filename. */ \ + LOCAL_FILE_FORMAT_TO_TSTR (lispstr, pathout); \ } while (0) #else /* not CYGWIN */ @@ -1098,6 +1176,7 @@ Lisp_Object data, int errnum)); Lisp_Object mswindows_lisp_error (int errnum); +Ibyte *mswindows_read_link (const Ibyte *fname); /* in intl-win32.c */ extern Lisp_Object Qmswindows_tstr, Qmswindows_unicode; diff --text -u 'xemacs-21.5.18/src/text.c' 'xemacs-21.5.19/src/text.c' Index: ./src/text.c --- ./src/text.c Fri Oct 15 02:26:25 2004 +++ ./src/text.c Tue Jan 25 08:34:12 2005 @@ -1,6 +1,6 @@ -/* Buffer manipulation primitives for XEmacs. +/* Text manipulation primitives for XEmacs. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2004 Ben Wing. Copyright (C) 1999 Martin Buchholz. This file is part of XEmacs. @@ -39,536 +39,138 @@ /* long comments */ /************************************************************************/ -/* - ========================================================================== - 1. Intro to Characters, Character Sets, and Encodings - ========================================================================== +/* NB: Everything below was written by Ben Wing except as otherwise noted. */ + +/************************************************************************/ +/* */ +/* */ +/* Part A: More carefully-written documentation */ +/* */ +/* */ +/************************************************************************/ - A character (which is, BTW, a surprisingly complex concept) is, in a - written representation of text, the most basic written unit that has a - meaning of its own. It's comparable to a phoneme when analyzing words - in spoken speech (for example, the sound of `t' in English, which in - fact has different pronunciations in different words -- aspirated in - `time', unaspirated in `stop', unreleased or even pronounced as a - glottal stop in `button', etc. -- but logically is a single concept). - Like a phoneme, a character is an abstract concept defined by its - *meaning*. The character `lowercase f', for example, can always be used - to represent the first letter in the word `fill', regardless of whether - it's drawn upright or italic, whether the `fi' combination is drawn as a - single ligature, whether there are serifs on the bottom of the vertical - stroke, etc. (These different appearances of a single character are - often called "graphs" or "glyphs".) Our concern when representing text - is on representing the abstract characters, and not on their exact - appearance. - - A character set (or "charset"), as we define it, is a set of characters, - each with an associated number (or set of numbers -- see below), called - a "code point". It's important to understand that a character is not - defined by any number attached to it, but by its meaning. For example, - ASCII and EBCDIC are two charsets containing exactly the same characters - (lowercase and uppercase letters, numbers 0 through 9, particular - punctuation marks) but with different numberings. The `comma' character - in ASCII and EBCDIC, for instance, is the same character despite having - a different numbering. Conversely, when comparing ASCII and JIS-Roman, - which look the same except that the latter has a yen sign substituted - for the backslash, we would say that the backslash and yen sign are - *not* the same characters, despite having the same number (95) and - despite the fact that all other characters are present in both charsets, - with the same numbering. ASCII and JIS-Roman, then, do *not* have - exactly the same characters in them (ASCII has a backslash character but - no yen-sign character, and vice-versa for JIS-Roman), unlike ASCII and - EBCDIC, even though the numberings in ASCII and JIS-Roman are closer. - - It's also important to distinguish between charsets and encodings. For - a simple charset like ASCII, there is only one encoding normally used -- - each character is represented by a single byte, with the same value as - its code point. For more complicated charsets, however, things are not - so obvious. Unicode version 2, for example, is a large charset with - thousands of characters, each indexed by a 16-bit number, often - represented in hex, e.g. 0x05D0 for the Hebrew letter "aleph". One - obvious encoding uses two bytes per character (actually two encodings, - depending on which of the two possible byte orderings is chosen). This - encoding is convenient for internal processing of Unicode text; however, - it's incompatible with ASCII, so a different encoding, e.g. UTF-8, is - usually used for external text, for example files or e-mail. UTF-8 - represents Unicode characters with one to three bytes (often extended to - six bytes to handle characters with up to 31-bit indices). Unicode - characters 00 to 7F (identical with ASCII) are directly represented with - one byte, and other characters with two or more bytes, each in the range - 80 to FF. +/* Authorship: Ben Wing - In general, a single encoding may be able to represent more than one - charset. - See also man/lispref/mule.texi. - ========================================================================== - 2. Character Sets + 7. Handling non-default formats ========================================================================== - A particular character in a charset is indexed using one or - more "position codes", which are non-negative integers. - The number of position codes needed to identify a particular - character in a charset is called the "dimension" of the - charset. In XEmacs/Mule, all charsets have 1 or 2 dimensions, - and the size of all charsets (except for a few special cases) - is either 94, 96, 94 by 94, or 96 by 96. The range of - position codes used to index characters from any of these - types of character sets is as follows: - - Charset type Position code 1 Position code 2 - ------------------------------------------------------------ - 94 33 - 126 N/A - 96 32 - 127 N/A - 94x94 33 - 126 33 - 126 - 96x96 32 - 127 32 - 127 - - Note that in the above cases position codes do not start at - an expected value such as 0 or 1. The reason for this will - become clear later. - - For example, Latin-1 is a 96-character charset, and JISX0208 - (the Japanese national character set) is a 94x94-character - charset. - - [Note that, although the ranges above define the *valid* - position codes for a charset, some of the slots in a particular - charset may in fact be empty. This is the case for JISX0208, - for example, where (e.g.) all the slots whose first - position code is in the range 118 - 127 are empty.] - - There are three charsets that do not follow the above rules. - All of them have one dimension, and have ranges of position - codes as follows: - - Charset name Position code 1 - ------------------------------------ - ASCII 0 - 127 - Control-1 0 - 31 - Composite 0 - some large number - - (The upper bound of the position code for composite characters - has not yet been determined, but it will probably be at - least 16,383). - - ASCII is the union of two subsidiary character sets: - Printing-ASCII (the printing ASCII character set, - consisting of position codes 33 - 126, like for a standard - 94-character charset) and Control-ASCII (the non-printing - characters that would appear in a binary file with codes 0 - - 32 and 127). - - Control-1 contains the non-printing characters that would - appear in a binary file with codes 128 - 159. - - Composite contains characters that are generated by - overstriking one or more characters from other charsets. - - Note that some characters in ASCII, and all characters - in Control-1, are "control" (non-printing) characters. - These have no printed representation but instead control - some other function of the printing (e.g. TAB or 8 moves - the current character position to the next tab stop). - All other characters in all charsets are "graphic" - (printing) characters. - - When a binary file is read in, the bytes in the file are - assigned to character sets as follows: - - Bytes Character set Range - -------------------------------------------------- - 0 - 127 ASCII 0 - 127 - 128 - 159 Control-1 0 - 31 - 160 - 255 Latin-1 32 - 127 - - This is a bit ad-hoc but gets the job done. - - ========================================================================== - 3. Encodings - ========================================================================== - - An "encoding" is a way of numerically representing - characters from one or more character sets. If an encoding - only encompasses one character set, then the position codes - for the characters in that character set could be used - directly. This is not possible, however, if more than one - character set is to be used in the encoding. - - For example, the conversion detailed above between bytes in - a binary file and characters is effectively an encoding - that encompasses the three character sets ASCII, Control-1, - and Latin-1 in a stream of 8-bit bytes. - - Thus, an encoding can be viewed as a way of encoding - characters from a specified group of character sets using a - stream of bytes, each of which contains a fixed number of - bits (but not necessarily 8, as in the common usage of - "byte"). - - Here are descriptions of a couple of common - encodings: - - - A. Japanese EUC (Extended Unix Code) - - This encompasses the character sets: - - Printing-ASCII, - - Katakana-JISX0201 (half-width katakana, the right half of JISX0201). - - Japanese-JISX0208 - - Japanese-JISX0212 - It uses 8-bit bytes. - - Note that Printing-ASCII and Katakana-JISX0201 are 94-character - charsets, while Japanese-JISX0208 is a 94x94-character charset. - - The encoding is as follows: - - Character set Representation (PC == position-code) - ------------- -------------- - Printing-ASCII PC1 - Japanese-JISX0208 PC1 + 0x80 | PC2 + 0x80 - Katakana-JISX0201 0x8E | PC1 + 0x80 - - - B. JIS7 - - This encompasses the character sets: - - Printing-ASCII - - Latin-JISX0201 (the left half of JISX0201; this character set is - very similar to Printing-ASCII and is a 94-character charset) - - Japanese-JISX0208 - - Katakana-JISX0201 - It uses 7-bit bytes. - - Unlike Japanese EUC, this is a "modal" encoding, which - means that there are multiple states that the encoding can - be in, which affect how the bytes are to be interpreted. - Special sequences of bytes (called "escape sequences") - are used to change states. - - The encoding is as follows: - - Character set Representation - ------------- -------------- - Printing-ASCII PC1 - Latin-JISX0201 PC1 - Katakana-JISX0201 PC1 - Japanese-JISX0208 PC1 | PC2 - - Escape sequence ASCII equivalent Meaning - --------------- ---------------- ------- - 0x1B 0x28 0x42 ESC ( B invoke Printing-ASCII - 0x1B 0x28 0x4A ESC ( J invoke Latin-JISX0201 - 0x1B 0x28 0x49 ESC ( I invoke Katakana-JISX0201 - 0x1B 0x24 0x42 ESC $ B invoke Japanese-JISX0208 - - Initially, Printing-ASCII is invoked. - - ========================================================================== - 4. Internal Mule Encodings - ========================================================================== - - In XEmacs/Mule, each character set is assigned a unique number, - called a "leading byte". This is used in the encodings of a - character. Leading bytes are in the range 0x80 - 0xFF - (except for ASCII, which has a leading byte of 0), although - some leading bytes are reserved. - - Charsets whose leading byte is in the range 0x80 - 0x9F are - called "official" and are used for built-in charsets. - Other charsets are called "private" and have leading bytes - in the range 0xA0 - 0xFF; these are user-defined charsets. - - More specifically: - - Character set Leading byte - ------------- ------------ - ASCII 0 (0x7F in arrays indexed by leading byte) - Composite 0x8D - Dimension-1 Official 0x80 - 0x8C/0x8D - (0x8E is free) - Control 0x8F - Dimension-2 Official 0x90 - 0x99 - (0x9A - 0x9D are free) - Dimension-1 Private Marker 0x9E - Dimension-2 Private Marker 0x9F - Dimension-1 Private 0xA0 - 0xEF - Dimension-2 Private 0xF0 - 0xFF - - There are two internal encodings for characters in XEmacs/Mule. - One is called "string encoding" and is an 8-bit encoding that - is used for representing characters in a buffer or string. - It uses 1 to 4 bytes per character. The other is called - "character encoding" and is a 19-bit encoding that is used - for representing characters individually in a variable. - - (In the following descriptions, we'll ignore composite - characters for the moment. We also give a general (structural) - overview first, followed later by the exact details.) - - A. Internal String Encoding - - ASCII characters are encoded using their position code directly. - Other characters are encoded using their leading byte followed - by their position code(s) with the high bit set. Characters - in private character sets have their leading byte prefixed with - a "leading byte prefix", which is either 0x9E or 0x9F. (No - character sets are ever assigned these leading bytes.) Specifically: - - Character set Encoding (PC == position-code) - ------------- -------- (LB == leading-byte) - ASCII PC1 | - Control-1 LB | PC1 + 0xA0 - Dimension-1 official LB | PC1 + 0x80 - Dimension-1 private 0x9E | LB | PC1 + 0x80 - Dimension-2 official LB | PC1 | PC2 + 0x80 - Dimension-2 private 0x9F | LB | PC1 + 0x80 | PC2 + 0x80 - - The basic characteristic of this encoding is that the first byte - of all characters is in the range 0x00 - 0x9F, and the second and - following bytes of all characters is in the range 0xA0 - 0xFF. - This means that it is impossible to get out of sync, or more - specifically: - - 1. Given any byte position, the beginning of the character it is - within can be determined in constant time. - 2. Given any byte position at the beginning of a character, the - beginning of the next character can be determined in constant - time. - 3. Given any byte position at the beginning of a character, the - beginning of the previous character can be determined in constant - time. - 4. Textual searches can simply treat encoded strings as if they - were encoded in a one-byte-per-character fashion rather than - the actual multi-byte encoding. - - None of the standard non-modal encodings meet all of these - conditions. For example, EUC satisfies only (2) and (3), while - Shift-JIS and Big5 (not yet described) satisfy only (2). (All - non-modal encodings must satisfy (2), in order to be unambiguous.) - - B. Internal Character Encoding - - One 19-bit word represents a single character. The word is - separated into three fields: - - Bit number: 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 - <------------> <------------------> <------------------> - Field: 1 2 3 - - Note that fields 2 and 3 hold 7 bits each, while field 1 holds 5 bits. - - Character set Field 1 Field 2 Field 3 - ------------- ------- ------- ------- - ASCII 0 0 PC1 - range: (00 - 7F) - Control-1 0 1 PC1 - range: (00 - 1F) - Dimension-1 official 0 LB - 0x7F PC1 - range: (01 - 0D) (20 - 7F) - Dimension-1 private 0 LB - 0x80 PC1 - range: (20 - 6F) (20 - 7F) - Dimension-2 official LB - 0x8F PC1 PC2 - range: (01 - 0A) (20 - 7F) (20 - 7F) - Dimension-2 private LB - 0xE1 PC1 PC2 - range: (0F - 1E) (20 - 7F) (20 - 7F) - Composite 0x1F ? ? - - Note that character codes 0 - 255 are the same as the "binary encoding" - described above. - - Most of the code in XEmacs knows nothing of the representation of a - character other than that values 0 - 255 represent ASCII, Control 1, - and Latin 1. - - WARNING WARNING WARNING: The Boyer-Moore code in search.c, and the - code in search_buffer() that determines whether that code can be used, - knows that "field 3" in a character always corresponds to the last - byte in the textual representation of the character. (This is important - because the Boyer-Moore algorithm works by looking at the last byte - of the search string and &&#### finish this. + We support, at least to some extent, formats other than the default + variable-width format, for speed; all of these alternative formats are + fixed-width. Currently we only handle these non-default formats in + buffers, because access to their text is strictly controlled and thus + the details of the format mostly compartmentalized. The only really + tricky part is the search code -- the regex, Boyer-Moore, and + simple-search algorithms in search.c and regex.c. All other code that + knows directly about the buffer representation is the basic code to + modify or retrieve the buffer text. + + Supporting fixed-width formats in Lisp strings is harder, but possible + -- FSF currently does this, for example. In this case, however, + probably only 8-bit-fixed is reasonable for Lisp strings -- getting + non-ASCII-compatible fixed-width formats to work is much, much harder + because a lot of code assumes that strings are ASCII-compatible + (i.e. ASCII + other characters represented exclusively using high-bit + bytes) and a lot of code mixes Lisp strings and non-Lisp strings freely. + + The different possible fixed-width formats are 8-bit fixed, 16-bit + fixed, and 32-bit fixed. The latter can represent all possible + characters, but at a substantial memory penalty. The other two can + represent only a subset of the possible characters. How these subsets + are defined can be simple or very tricky. + + Currently we support only the default format and the 8-bit fixed format, + and in the latter, we only allow these to be the first 256 characters in + an Ichar (ASCII and Latin 1). + + One reasonable approach for 8-bit fixed is to allow the upper half to + represent any 1-byte charset, which is specified on a per-buffer basis. + This should work fairly well in practice since most documents are in + only one foreign language (possibly with some English mixed in). I + think FSF does something like this; or at least, they have something + called nonascii-translation-table and use it when converting from + 8-bit-fixed text ("unibyte text") to default text ("multibyte text"). + With 16-bit fixed, you could do something like assign chunks of the 64K + worth of characters to charsets as they're encountered in documents. + This should work well with most Asian documents. + + If/when we switch to using Unicode internally, we might have formats more + like this: + + -- UTF-8 or some extension as the default format. Perl uses an + extension that handles 64-bit chars and requires as much as 13 bytes per + char, vs. the standard of 31-bit chars and 6 bytes max. UTF-8 has the + same basic properties as our own variable-width format (see text.c, + Internal String Encoding) and so most code would not need to be changed. + + -- UTF-16 as a "pseudo-fixed" format (i.e. 16-bit fixed plus surrogates + for representing characters not in the BMP, aka >= 65536). The vast + majority of documents will have no surrogates in them so byte/char + conversion will be very fast. + + -- an 8-bit fixed format, like currently. + + -- possibly, UCS-4 as a 32-bit fixed format. + + The fixed-width formats essentially treat the buffer as an array of + 8-bit, 16-bit or 32-bit integers. This means that how they are stored + in memory (in particular, big-endian or little-endian) depends on the + native format of the machine's processor. It also means we have to + worry a bit about alignment (basically, we just need to keep the gap an + integral size of the character size, and get things aligned properly + when converting the buffer between formats). ========================================================================== - 5. Buffer Positions and Other Typedefs + 8. Using UTF-16 as the default text format ========================================================================== - A. Buffer Positions - - There are three possible ways to specify positions in a buffer. All - of these are one-based: the beginning of the buffer is position or - index 1, and 0 is not a valid position. - - As a "buffer position" (typedef Charbpos): - - This is an index specifying an offset in characters from the - beginning of the buffer. Note that buffer positions are - logically *between* characters, not on a character. The - difference between two buffer positions specifies the number of - characters between those positions. Buffer positions are the - only kind of position externally visible to the user. - - As a "byte index" (typedef Bytebpos): - - This is an index over the bytes used to represent the characters - in the buffer. If there is no Mule support, this is identical - to a buffer position, because each character is represented - using one byte. However, with Mule support, many characters - require two or more bytes for their representation, and so a - byte index may be greater than the corresponding buffer - position. - - As a "memory index" (typedef Membpos): - - This is the byte index adjusted for the gap. For positions - before the gap, this is identical to the byte index. For - positions after the gap, this is the byte index plus the gap - size. There are two possible memory indices for the gap - position; the memory index at the beginning of the gap should - always be used, except in code that deals with manipulating the - gap, where both indices may be seen. The address of the - character "at" (i.e. following) a particular position can be - obtained from the formula - - buffer_start_address + memory_index(position) - 1 - - except in the case of characters at the gap position. - - B. Other Typedefs - - Ichar: - ------ - This typedef represents a single Emacs character, which can be - ASCII, ISO-8859, or some extended character, as would typically - be used for Kanji. Note that the representation of a character - as an Ichar is *not* the same as the representation of that - same character in a string; thus, you cannot do the standard - C trick of passing a pointer to a character to a function that - expects a string. - - An Ichar takes up 19 bits of representation and (for code - compatibility and such) is compatible with an int. This - representation is visible on the Lisp level. The important - characteristics of the Ichar representation are - - -- values 0x00 - 0x7f represent ASCII. - -- values 0x80 - 0xff represent the right half of ISO-8859-1. - -- values 0x100 and up represent all other characters. - - This means that Ichar values are upwardly compatible with - the standard 8-bit representation of ASCII/ISO-8859-1. - - Ibyte: - ------ - The data in a buffer or string is logically made up of Ibyte - objects, where a Ibyte takes up the same amount of space as a - char. (It is declared differently, though, to catch invalid - usages.) Strings stored using Ibytes are said to be in - "internal format". The important characteristics of internal - format are - - -- ASCII characters are represented as a single Ibyte, - in the range 0 - 0x7f. - -- All other characters are represented as a Ibyte in - the range 0x80 - 0x9f followed by one or more Ibytes - in the range 0xa0 to 0xff. - - This leads to a number of desirable properties: - - -- Given the position of the beginning of a character, - you can find the beginning of the next or previous - character in constant time. - -- When searching for a substring or an ASCII character - within the string, you need merely use standard - searching routines. - - Extbyte: - -------- - Strings that go in or out of Emacs are in "external format", - typedef'ed as an array of char or a char *. There is more - than one external format (JIS, EUC, etc.) but they all - have similar properties. They are modal encodings, - which is to say that the meaning of particular bytes is - not fixed but depends on what "mode" the string is currently - in (e.g. bytes in the range 0 - 0x7f might be - interpreted as ASCII, or as Hiragana, or as 2-byte Kanji, - depending on the current mode). The mode starts out in - ASCII/ISO-8859-1 and is switched using escape sequences -- - for example, in the JIS encoding, 'ESC $ B' switches to a - mode where pairs of bytes in the range 0 - 0x7f - are interpreted as Kanji characters. - - External-formatted data is generally desirable for passing - data between programs because it is upwardly compatible - with standard ASCII/ISO-8859-1 strings and may require - less space than internal encodings such as the one - described above. In addition, some encodings (e.g. JIS) - keep all characters (except the ESC used to switch modes) - in the printing ASCII range 0x20 - 0x7e, which results in - a much higher probability that the data will avoid being - garbled in transmission. Externally-formatted data is - generally not very convenient to work with, however, and - for this reason is usually converted to internal format - before any work is done on the string. - - NOTE: filenames need to be in external format so that - ISO-8859-1 characters come out correctly. - - Charcount: - ---------- - This typedef represents a count of characters, such as - a character offset into a string or the number of - characters between two positions in a buffer. The - difference between two Charbpos's is a Charcount, and - character positions in a string are represented using - a Charcount. - - Bytecount: - ---------- - Similar to a Charcount but represents a count of bytes. - The difference between two Bytebpos's is a Bytecount. - - - C. Usage of the Various Representations - - Memory indices are used in low-level functions in insdel.c and for - extent endpoints and marker positions. The reason for this is that - this way, the extents and markers don't need to be updated for most - insertions, which merely shrink the gap and don't move any - characters around in memory. - - (The beginning-of-gap memory index simplifies insertions w.r.t. - markers, because text usually gets inserted after markers. For - extents, it is merely for consistency, because text can get - inserted either before or after an extent's endpoint depending on - the open/closedness of the endpoint.) - - Byte indices are used in other code that needs to be fast, - such as the searching, redisplay, and extent-manipulation code. - - Buffer positions are used in all other code. This is because this - representation is easiest to work with (especially since Lisp - code always uses buffer positions), necessitates the fewest - changes to existing code, and is the safest (e.g. if the text gets - shifted underneath a buffer position, it will still point to a - character; if text is shifted under a byte index, it might point - to the middle of a character, which would be bad). - - Similarly, Charcounts are used in all code that deals with strings - except for code that needs to be fast, which used Bytecounts. - - Strings are always passed around internally using internal format. - Conversions between external format are performed at the time - that the data goes in or out of Emacs. - - D. Working With the Various Representations - - We write things this way because it's very important the - MAX_BYTEBPOS_GAP_SIZE_3 is a multiple of 3. (As it happens, - 65535 is a multiple of 3, but this may not always be the - case. #### unfinished + NOTE: The Eistring API is (or should be) Mule-correct even without + an ASCII-compatible internal representation. + + #### Currently, the assumption that text units are one byte in size is + embedded throughout XEmacs, and `Ibyte *' is used where `Itext *' should + be. The way to fix this is to (among other things) + + (a) review all places referencing `Ibyte' and `Ibyte *', change them to + use Itext, and fix up the code. + (b) change XSTRING_DATA to be of type Itext * + (c) review all uses of XSTRING_DATA + (d) eliminate XSTRING_LENGTH, splitting it into XSTRING_BYTE_LENGTH and + XSTRING_TEXT_LENGTH and reviewing all places referencing this + (e) make similar changes to other API's that refer to the "length" of + something, such as qxestrlen() and eilen() + (f) review all use of `CIbyte *'. Currently this is usually a way of + passing literal ASCII text strings in places that want internal text. + Either create separate _ascii() and _itext() versions of the + functions taking CIbyte *, or make use of something like the + WEXTTEXT() macro, which will generate wide strings as appropriate. + (g) review all uses of Bytecount and see which ones should be Textcount. + (h) put in error-checking code that will be tripped as often as possible + when doing anything with internal text, and check to see that ASCII + text has not mistakenly filtered in. This should be fairly easy as + ASCII text will generally be entirely spaces and letters whereas every + second byte of Unicode text will generally be a null byte. Either we + abort if the second bytes are entirely letters and numbers, or, + perhaps better, do the equivalent of a non-MULE build, where we should + be dealing entirely with 8-bit characters, and assert that the high + bytes of each pair are null. + (i) review places where xmalloc() is called. If we convert each use of + xmalloc() to instead be xnew_array() or some other typed routine, + then we will find every place that allocates space for Itext and + assumes it is based on one-byte units. + (j) encourage the use of ITEXT_ZTERM_SIZE instead of '+ 1' whenever we + are adding space for a zero-terminator, to emphasize what we are + doing and make sure the calculations are correct. Similarly for + EXTTEXT_ZTERM_SIZE. + (k) Note that the qxestr*() functions, among other things, will need to + be rewritten. + + Note that this is a lot of work, and is not high on the list of priorities + currently. ========================================================================== - 6. Miscellaneous + 9. Miscellaneous ========================================================================== A. Unicode Support @@ -621,8 +223,1051 @@ Or you could use 0x8D C1 C2 C3 C4, allowing for about 85 million (slightly over 2^26) composite characters. + ========================================================================== + 10. Internal API's + ========================================================================== + + All of these are documented in more detail in text.h. + +@enumerate +@item +Basic internal-format API's + +These are simple functions and macros to convert between text +representation and characters, move forward and back in text, etc. + +@item +The DFC API + +This is for conversion between internal and external text. Note that +there is also the "new DFC" API, which *returns* a pointer to the +converted text (in alloca space), rather than storing it into a +variable. + +@item +The Eistring API + +(This API is currently under-used) When doing simple things with +internal text, the basic internal-format API's are enough. But to do +things like delete or replace a substring, concatenate various strings, +etc. is difficult to do cleanly because of the allocation issues. +The Eistring API is designed to deal with this, and provides a clean +way of modifying and building up internal text. (Note that the former +lack of this API has meant that some code uses Lisp strings to do +similar manipulations, resulting in excess garbage and increased +garbage collection.) + +NOTE: The Eistring API is (or should be) Mule-correct even without +an ASCII-compatible internal representation. +@end enumerate + + ========================================================================== + 11. Other Sources of Documentation + ========================================================================== + + man/lispref/mule.texi +@enumerate +@item +another intro to characters, encodings, etc; #### Merge with the +above info +@item +documentation of ISO-2022 +@item +The charset and coding-system Lisp API's +@item +The CCL conversion language for writing encoding conversions +@item +The Latin-Unity package for unifying Latin charsets +@end enumerate + + man/internals/internals.texi (the Internals manual) +@enumerate +@item +"Coding for Mule" -- how to write Mule-aware code +@item +"Modules for Internationalization" +@item +"The Text in a Buffer" -- more about the different ways of +viewing buffer positions; #### Merge with the above info +@item +"MULE Character Sets and Encodings" -- yet another intro +to characters, encodings, etc; #### Merge with the +above info; also some documentation of Japanese EUC and JIS7, +and CCL internals +@end enumerate + + text.h -- info about specific XEmacs-C API's for handling internal and + external text + + intl-win32.c -- Windows-specific I18N information + + lisp.h -- some info appears alongside the definitions of the basic + character-related types + + unicode.c -- documentation about Unicode translation tables */ + +/************************************************************************/ +/* */ +/* */ +/* Part B: Random proposals for work to be done */ +/* */ +/* */ +/************************************************************************/ + + +/* + + + ========================================================================== + - Mule design issues (ben) + ========================================================================== + +circa 1999 + +Here is a more detailed list of Mule-related projects that we will be +working on. They are more or less ordered according to how we will +proceed, but it's not exact. In particular, there will probably be +time overlap among adjacent projects. + +@enumerate +@item +Modify the internal/external conversion macros to allow for +MS Windows support. + +@item +Modify the buffer macros to allow for more than one internal +representation, e.g. fixed width and variable width. + +@item +Review the existing Mule code, especially the lisp code, for code +quality issues and improve the cleanliness of it. Also work on +creating a specification for the Mule API. + +@item +Write some more automated mule tests. + +@item +Integrate Tomohiko's UTF-2000 code, fixing it up so that nothing is +broken when the UTF-2000 configure option is not enabled. + +@item +Fix up the MS Windows code to be Mule-correct, so that you can +compile with Mule support under MS windows and have a working +XEmacs, at least just with Latin-1. + +@item +Implement a scheme to guarantee no corruption of files, even with +an incorrect coding system - in particular, guarantee no corruption +of binary files. + +@item +Make the text property support in XEmacs robust with respect to +string and text operations, so that the `no corruption' support in +the previous entry works properly, even if a lot of cutting and +pasting is done. + +@item +Improve the handling of auto-detection so that, when there is any +possibility at all of mistake, the user is informed of the detected +encoding and given the choice of choosing other possibilities. + +@item +Improve the support for different language environments in XEmacs, +for example, the priority of coding systems used in auto-detection +should properly reflect the language environment. This probably +necessitates rethinking the current `coding system priority' +scheme. + +@item +Do quality work to improve the existing UTF-2000 implementation. + +@item +Implement preliminary support for 8-bit fixed width +representation. First, we will only implement 7-bit support, and +will fall back to variable width as soon as any non-ASCII +character is encountered. Then we will improve the support to +handle an arbitrary character set in the upper half of the 8-bit space. + +@item +Investigate any remaining hurdles to making --with-mule be the +default configure option. +@end enumerate + + ========================================================================== + - Mule design issues (stephen) + ========================================================================== + +What I see as Mule priorities (in rough benefit order, I am not taking +account of difficulty, nor the fact that some - eg 8 & 10 - will +probably come as packages): + +@enumerate +@item +Fix the autodetect problem (by making the coding priority list +user-configurable, as short as he likes, even null, with "binary" +as the default). +@item +Document the language environments and other Mule "APIs" as +implemented (since there is no real design spec). Check to see +how and where they are broken. +@item +Make the Mule menu useful to non-ISO-2022-literate folks. +@item +Redo the lstreams stuff to make it easy and robust to "pipeline", +eg, libz | gnupg | jis2mule. +@item +Make Custom Mule-aware. (This probably depends on a sensible +fonts model.) +@item +Implement the "literal byte stream" memory feature. +@item +Study the FSF implementation of Mule for background for 7 & 8. +@item +Identify desirable Mule features (eg, i18n-ized messages as above, +collating tables by language environment, etc). (New features +might have priority as high as 9.) +@item +Specify Mule UIs, APIs, etc, and design and (re)implement them. +@item +Implement the 8-bit-wide buffer optimization. +@item +Move the internal encoding to UTF-32 (subject to Olivier's caveats +regarding compose characters), with the variable-width char +buffers using UTF-8. +@item +Implement the 16- and 32-bit-wide buffer optimizations. +@end enumerate + + ========================================================================== + - Mule design issues "short term" (ben) + ========================================================================== + +@enumerate +@item +Finish changes in fixup/directory, get in CVS. + +(Test with and without "quick-build", to see if really faster) +(need autoconf) + +@item +Finish up Windows/Mule changes. Outline of this elsewhere; Do +*minimal* effort. + +@item +Continue work on Windows stability, e.g. go through existing notes +on Windows Mule-ization + extract all info. + +@item +Get Unicode translation tables integrated. + +Finish UCS2/UTF16 coding system. + +@item +Make sure coding system priority list is language-environment specific. + +@item +Consider moving language selection Menu up to be parallel with Mule menu. + +@item +Check to make sure we grok the default locale at startup under +Windows and understand the Windows locales. Finish implementation +of mswindows-multibyte and make sure it groks all the locales. + +@item +Do the above as best as we can without using Unicode tables. + +@item +Start tagging all text with a language text property, +indicating the current language environment when the text was input. + +@item +Make sure we correctly accept input of non-ASCII chars +(probably already do!) + +@item +Implement active language/keyboard switching under Windows. + +@item +Look into implementing support for "MS IME" protocol (Microsoft +fancy built-in Asian input methods). + +@item +Redo implementation of mswindows-multibyte and internal display to +entirely use translation to/from Unicode for increased accuracy. + +@item +Implement buf<->char improvements from FSF. Also implement +my string byte<->char optimization structure. + +@item +Integrate all Mule DOCS from 20.6 or 21.0. Try to add sections +for what we've added. + +@item +Implement 8-bit fixed width optimizations. Then work on 16-bit. +@end enumerate + + ========================================================================== + - Mule design issues (more) (ben) + ========================================================================== + + Get minimal Mule for Windows working using Ikeyama's patches. At + first, rely on his conversion of internal -> external + locale-specific but very soon (as soon as we get translation + tables) can switch to using Unicode versions of display funs, which + will allow many more charsets to be handled and in a more + consistent fashion. + + i.e. to convert an internal string to an external format, at first + we use our own knowledge of the Microsoft locale file formats but + an alternative is to convert to Unicode and use Microsoft's + convert-Unicode-to-locale encoding functions. This gains us a + great deal of generality, since in practice all charset caching + points can be wrapped into Unicode caching points. + + This requires adding UCS2 support, which I'm doing. This support + would let us convert internal -> Unicode, which is exactly what we + want. + + At first, though, I would do the UCS2 support, but leave the + existing way of doing things in redisplay. Meanwhile, I'd go + through and fix up the places in the code that assume we are + dealing with unibytes. + + After this, the font problems will be fixed , we should have a + pretty well working XEmacs + MULE under Windows. The only real + other work is the clipboard code, which should be straightforward. + + ========================================================================== + - Mule design discussion + ========================================================================== + +-------------------------------------------------------------------------- + +Ben + +April 11, 2000 + +Well yes, this was the whole point of my "no lossage" proposal of being +able to undo any coding-system transformation on a buffer. The idea was +to figure out which transformations were definitely reversable, and for +all the others, cache the original text in a text property. This way, you +could probably still do a fairly good job at constructing a good reversal +even after you've gone into the text and added, deleted, and rearranged +some things. + +But you could implement it much more simply and usefully by just +determining, for any text being decoded into mule-internal, can we go back +and read the source again? If not, remember the entire file (GNUS +message, etc) in text properties. Then, implement the UI interface (like +Netscape's) on top of that. This way, you have something that at least +works, but it might be inefficient. All we would need to do is work on +making the +underlying implementation more efficient. + +Are you interested in doing this? It would be a huge win for users. +Hrvoje Niksic wrote: + +> Ben Wing <ben@666.com> writes: +> +> > let me know exactly what "rethink" functionality you want and i'll +> > come up with an interface. perhaps you just want something like +> > netscape's encoding menu, where if you switch encodings, it reloads +> > and reencodes? +> +> It might be a bit more complex than that. In many cases, it's hard or +> impossible to meaningfully "reload" -- for instance, this +> functionality should be available while editing a Gnus message, as +> well as while visiting a file. +> +> For the special case of Latin-N <-> Latin-M conversion, things could +> be done easily -- to convert from N to M, you only need to convert +> internal representation back to N, and then convert it forth to M. + +-------------------------------------------------------------------------- +April 11, 2000 + +Well yes, this was the whole point of my "no lossage" proposal of being +able to undo any coding-system transformation on a buffer. The idea was +to figure out which transformations were definitely reversable, and for +all the others, cache the original text in a text property. This way, you +could probably still do a fairly good job at constructing a good reversal +even after you've gone into the text and added, deleted, and rearranged +some things. + +But you could implement it much more simply and usefully by just +determining, for any text being decoded into mule-internal, can we go back +and read the source again? If not, remember the entire file (GNUS +message, etc) in text properties. Then, implement the UI interface (like +Netscape's) on top of that. This way, you have something that at least +works, but it might be inefficient. All we would need to do is work on +making the +underlying implementation more efficient. + +Are you interested in doing this? It would be a huge win for users. +Hrvoje Niksic wrote: + +> Ben Wing <ben@666.com> writes: +> +> > let me know exactly what "rethink" functionality you want and i'll +> > come up with an interface. perhaps you just want something like +> > netscape's encoding menu, where if you switch encodings, it reloads +> > and reencodes? +> +> It might be a bit more complex than that. In many cases, it's hard or +> impossible to meaningfully "reload" -- for instance, this +> functionality should be available while editing a Gnus message, as +> well as while visiting a file. +> +> For the special case of Latin-N <-> Latin-M conversion, things could +> be done easily -- to convert from N to M, you only need to convert +> internal representation back to N, and then convert it forth to M. + + +------------------------------------------------------------------------ + + ========================================================================== + - Redoing translation macros [old] + ========================================================================== + + Currently the translation macros (the macros with names such as + GET_C_STRING_CTEXT_DATA_ALLOCA) have names that are difficult to parse + or remember, and are not all that general. In the process of + reviewing the Windows code so that it could be muleized, I discovered + that these macros need to be extended in various ways to allow for + the Windows code to be easily muleized. + + Since the macros needed to be changed anyways, I figured it would be a + good time to redo them properly. I propose new macros which have + names like this: + + @itemize @bullet + @item + <A>_TO_EXTERNAL_FORMAT_<B> + @item + <A>_TO_EXTERNAL_FORMAT_<B>_1 + @item + <C>_TO_INTERNAL_FORMAT_<D> + @item + <C>_TO_INTERNAL_FORMAT_<D>_1 + @end itemize + + A and C represent the source of the data, and B and D represent the + sink of the data. + + All of these macros call either the functions + convert_to_external_format or convert_to_internal_format internally, + with some massaging of the arguments. + + All of these macros take the following arguments: + + @itemize @bullet + @item + First, one or two arguments indicating the source of the data. + @item + Second, an argument indicating the coding system. (In order to avoid + an excessive number of macros, we no longer provide separate macros + for specific coding systems.) + @item + Third, one or two arguments indicating the sink of the data. + @item + Fourth, optionally, arguments indicating the error behavior and the + warning class (these arguments are only present in the _1 versions + of the macros). The other, shorter named macros are trivial + interfaces onto these macros with the error behavior being + ERROR_ME_WARN, with the warning class being Vstandard_warning_class. + @end itemize + + <A> can be one of the following: + @itemize @bullet + @item + LISP (which means a Lisp string) Takes one argument, a Lisp Object. + @item + LSTREAM (which indicates an lstream) Takes one argument, an + lstream. The data is read from the lstream until EOF is reached. + @item + DATA (which indicates a raw memory area) Takes two arguments, a + pointer and a length in bytes. + (You must never use this if the source of the data is a Lisp string, + because of the possibility of relocation during garbage collection.) + @end itemize + + <B> can be one of the following: + @itemize @bullet + @item + ALLOCA (which means that the resulting data is stored in alloca()ed + memory. Two arguments should be specified, a pointer and a length, + which should be lvalues.) + @item + MALLOC (which means that the resulting data is stored in malloc()ed + memory. Two arguments should be specified, a pointer and a + length. The memory must be free()d by the caller. + @item + OPAQUE (which means the resulting data is stored in an opaque Lisp + Object. This takes one argument, a lvalue Lisp Object. + @item + LSTREAM. The data is written to an lstream. + @end itemize + + <C> can be one of the : + @itemize @bullet + @item + DATA + @item + LSTREAM + @end itemize + (just like <A> above) + + <D> can be one of + @itemize @bullet + @item + ALLOCA + @item + MALLOC + @item + LISP This means a Lisp String. + @item + BUFFER The resulting data is inserted into a buffer at the buffer's + value of point. + @item + LSTREAM The data is written to the lstream. + @end itemize + + + Note that I have eliminated the FORMAT argument of previous macros, + and replaced it with a coding system. This was made possible by + coding system aliases. In place of old `format's, we use a `virtual + coding system', which is aliased to the actual coding system. + + The value of the coding system argument can be anything that is legal + input to get_coding_system, i.e. a symbol or a coding system object. + + ========================================================================== + - creation of generic macros for accessing internally formatted data [old] + ========================================================================== + + I have a design; it's all written down (I did it in Tsukuba), and I just have + to have it transcribed. It's higher level than the macros, though; it's Lisp + primitives that I'm designing. + + As for the design of the macros, don't worry so much about all files having to + get included (which is inevitable with macros), but about how the files are + separated. Your design might go like this: + + @enumerate + @item + you have generic macro interfaces, which specify a particular + behavior but not an implementation. these generic macros have + complementary versions for buffers and for strings (and the buffer + or string is an argument to all of the macros), and do such things + as convert between byte and char indices, retrieve the character at + a particular byte or char index, increment or decrement a byte + index to the beginning of the next or previous character, indicate + the number of bytes occupied by the character at a particular byte + or character index, etc. These are similar to what's already out + there except that they confound buffers and strings and that they + can also work with actual char *'s, which I think is a really bad + idea because it encourages code to "assume" that the representation + is ASCII compatible, which is might not be (e.g. 16-bit fixed + width). In fact, one thing I'm planning on doing is redefining + Bufbyte as a struct, for debugging purposes, to catch all places + that cavalierly compare them with ASCII char's. Note also that I + really want to rename Bufpos and Bytind, which are confusing and + wrong in that they also apply to strings. They should be Bytepos + and Charpos, or something like that, to go along with Bytecount and + Charcount. Similarly, Bufbyte is similarly a misnomer and should be + Intbyte -- a byte in the internal string representation (any of the + internal representations) of a string or buffer. Corresponding to + this is Extbyte (which we already have), a byte in any external + string representation. We also have Extcount, which makes sense, + and we might possibly want Extcharcount, the number of characters + in an external string representation; but that gets sticky in modal + encodings, and it's not clear how useful it would be. + + @item + for all generic macro interfaces, there are specific versions of + each of them for each possible representation (pure ASCII in the + non-Mule world, Mule standard, UTF-8, 8-bit fixed, 16-bit fixed, + 32-bit fixed, etc.; there may well be more than one possible 16-bit + fixed version, as well). Each representation has a corresponding + prefix, e.g. MULE_ or FIXED16_ or whatever, which is prefixed onto + the generic macro names. The resulting macros perform the + operation defined for the macro, but assume, and only work + correctly with, text in the corresponding representation. + + @item + The definition of the generic versions merely conditionalizes on + the appropriate things (i.e. bit flags in the buffer or string + object) and calls the appropriate representation-specific version. + There may be more than one definition (protected by ifdefs, of + course), or one definition that amalgamated out of many ifdef'ed + sections. + + @item + You should probably put each different representation in its own + header file, e.g. charset-mule.h or charset-fixed16.h or + charset-ascii.h or whatever. Then put the main macros into + charset.h, and conditionalize in this file appropriately to include + the other ones. That way, code that actually needs to play around + with internal-format text at this level can include "charset.h" + (certainly a much better place than buffer.h), and everyone else + uses higher-level routines. The representation-specific macros + should not normally be used *directly* at all; they are invoked + automatically from the generic macros. However, code that needs to + be highly, highly optimized might choose to take a loop and write + two versions of it, one for each representation, to avoid the + per-loop-iteration cost of a comparison. Until the macro interface + is rock stable and solid, we should strongly discourage such + nanosecond optimizations. + @end enumerate + + ========================================================================== + - UTF-16 compatible representation + ========================================================================== + +NOTE: One possible default internal representation that was compatible +with UTF16 but allowed all possible chars in UCS4 would be to take a +more-or-less unused range of 2048 chars (not from the private area +because Microsoft actually uses up most or all of it with EUDC chars). +Let's say we picked A400 - ABFF. Then, we'd have: + +0000 - FFFF Simple chars + +D[8-B]xx D[C-F]xx Surrogate char, represents 1M chars + +A[4-B]xx D[C-F]xx D[C-F]xx Surrogate char, represents 2G chars + +This is exactly the same number of chars as UCS-4 handles, and it follows the +same property as UTF8 and Mule-internal: + +@enumerate +@item +There are two disjoint groupings of units, one representing leading units +and one representing non-leading units. +@item +Given a leading unit, you immediately know how many units follow to make +up a valid char, irrespective of any other context. +@end enumerate + +Note that A4xx is actually currently assigned to Yi. Since this is an +internal representation, we could just move these elsewhere. + +An alternative is to pick two disjoint ranges, e.g. 2D00 - 2DFF and +A500 - ABFF. + + ========================================================================== + New API for char->font mapping + ========================================================================== +- ; supersedes charset-registry and CCL; + supports all windows systems; powerful enough for Unicode; etc. + + (charset-font-mapping charset) + +font-mapping-specifier string + +char-font-mapping-table + + char-table, specifier; elements of char table are either strings (which + specify a registry or comparable font property, or vectors of a string + (same) followed by keyword-value pairs (optional). The only allowable + keyword currently is :ccl-program, which specifies a CCL program to map + the characters into font indices. Other keywords may be added + e.g. allowing Elisp fragments instead of CCL programs, also allowed is + [inherit], which inherits from the next less-specific char-table in the + specifier. + + The preferred interface onto this mapping (which should be portable + across Emacsen) is + + (set-char-font-mapping key value &optional locale tag-set how-to-add) + + where key is a char, range or charset (as for put-char-table), value is + as above, and the other arguments are standard for specifiers. This + automatically creates a char table in the locale, as necessary (all + elements default to [inherit]). On GNU Emacs, some specifiers arguments + may be unimplemented. + + (char-font-mapping key value &optional locale) +works vaguely like get-specifier? But does inheritance processing. +locale should clearly default here to current-buffer + +#### should get-specifier as well? Would make it work most like +#### buffer-local variables. + +NB. set-charset-registry and set-charset-ccl-program are obsoleted. + + ========================================================================== + Implementing fixed-width 8,16,32 bit buffer optimizations + ========================================================================== + +Add set-buffer-optimization (buffer &rest keywords) for +controlling these things. + +Also, put in hack so that correct arglist can be retrieved by +Lisp code. + +Look at the way keyword primitives are currently handled; make +sure it works and is documented, etc. + +Implement 8-bit fixed width optimization. Take the things that +know about the actual implementation and put them in a single +file, in essence creating an abstraction layer to allow +pluggable internal representations. Implement a fairly general +scheme for mapping between character codes in the 8 bits or 16 +bits representation and on actual charset characters. As part of +set-buffer-optimization, you can specify a list of character sets +to be used in the 8 bit to 16 bit, etc. world. You can also +request that the buffer be in 8, 16, etc. if possible. + +-> set defaults wrt this. +-> perhaps this should be just buffer properties. +-> this brings up the idea of default properties on an object. +-> Implement default-put, default-get, etc. + +What happens when a character not assigned in the range gets +added? Then, must convert to variable width of some sort. + +Note: at first, possibly we just convert whole hog to get things +right. Then we'd have to poy alternative to characters that got +added + deleted that were unassigned in the fixed width. When +this goes to zero and there's been enough time (heuristics), we +go back to fixed. + +Side note: We could dynamically build up the set of assigned +chars as they go. Conceivably this could even go down to the +single char level: Just keep a big array of mapping from 16 bit +values to chars, and add empty time, a char has been encountered +that wasn't there before. Problem need inverse mapping. + +-> Possibility; chars are actual objects, not just numbers. +Then you could keep track of such info in the chars itself. +*Think about this.* + +Eventually, we might consider allowing mixed fixed-width, +variable-width buffer encodings. Then, we use range tables to +indicate which sections are fixed and which variable and INC_CHAR does +something like this: binary search to find the current range, which +indicates whether it's fixed or variable, and tells us what the +increment is. We can cache this info and use it next time to speed +up. + +-> We will then have two partially shared range tables - one for +overall fixed width vs. variable width, and possibly one containing +this same info, but partitioning the variable width in one. Maybe +need fancier nested range table model. + + ========================================================================== + Expansion of display table and case mapping table support for all + chars, not just ASCII/Latin1. + ========================================================================== + + ========================================================================== + Improved flexibility for display tables, and evaluation of its + features to make sure it meshes with and complements the char<->font + mapping API mentioned earlier + ========================================================================== + + ========================================================================== + String access speedup: + ========================================================================== + + For strings larger than some size in bytes (10?), keep extra fields of + info: length in chars, and a (char, byte) pair in the middle to speed + up sequential access. + + (Better idea: do this for any size string, but only if it contains + non-ASCII chars. Then if info is missing, we know string is + ASCII-only.) + + Use a string-extra-info object, replacing string property slot and + containing fields for string mod tick, string extents, string props, + and string char length, and cached (char,byte) pair. + string-extra-info (or string-auxiliary?) objects could be in frob + blocks, esp. if creating frob blocks is easy + worth it. + +- Caching of char<->byte conversions in strings - should make nearly + all operations on strings O(N) + + ========================================================================== + Improvements in buffer char<->byte mapping + ========================================================================== + + - Range table implementation - especially when there are few runs of + different widths, e.g. recently converted from fixed-width + optimization to variable width + + Range Tables to speed up Bufpos <-> Bytind caching + ================================================== + + This describes an alternative implementation using ranges. We + maintain a range table of all spans of characters of a fixed width. + Updating this table could take time if there are a large number of + spans; but constant factors of operations should be quick. This method really wins + when you have 8-bit buffers just converted to variable width, where + there will be few spans. More specifically, lookup in this range + table is O(log N) and can be done with simple binary search, which is + very fast. If we maintain the ranges using a gap array, updating this + table will be fast for local operations, which is most of the time. + + We will also provide (at first, at least) a Lisp function to set the + caching mechanism explicitly - either range tables or the existing + implementation. Eventually, we want to improve things, to the point + where we automatically pick the right caching for the situation and + have more caching schemes implemented. + + ========================================================================== + - Robustify Text Properties + ========================================================================== + + ========================================================================== + Support for unified internal representation, e.g. Unicode + ========================================================================== + + Start tagging all text with a language text property, + indicating the current language environment when the text was input. + (needs "Robustify Text Properties") + + ========================================================================== + - Generalized Coding Systems + ========================================================================== + + - Lisp API for Defining Coding Systems + + User-defined coding systems. + + (define-coding-system-type 'type + :encode-function fun + :decode-function fun + :detect-function fun + :buffering (number = at least this many chars + line = buffer up to end of line + regexp = buffer until this regexp is found in match + source data. match data will be appropriate when fun is + called + + encode fun is called as + + (encode instream outstream) + + should read data from instream and write converted result onto + outstream. Can leave some data stuff in stream, it will reappear + next time. Generally, there is a finite amount of data in instream + and further attempts to read lead to would-block errors or retvals. + Can use instream properties to record state. May use read-stream + functionality to read everything into a vector or string. + + ->Need vectors + string exposed to resizing of Lisp implementation + where necessary. + + ========================================================================== + Support Windows Active Kbd Switching, Far East IME API (done already?) + ========================================================================== + + ========================================================================== + - UI/design changes for Coding System Pipelining + ========================================================================== + + ------------------------------------------------------------------ + CODING-SYSTEM CHAINS + ------------------------------------------------------------------ + + sjt sez: + + There should be no elementary coding systems in the Lisp API, only + chains. Chains should be declared, not computed, as a sequence of coding + formats. (Probably the internal representation can be a vector for + efficiency but programmers would probably rather work with lists.) A + stream has a token type. Most streams are octet streams. Text is a + stream of characters (in _internal_ format; a file on disk is not text!) + An octet-stream has no implicit semantics, so its format must always be + specified. The only type currently having semantics is characters. This + means that the chain [euc-jp -> internal -> shift_jis) may be specified + (euc-jp, shift_jis), and if no euc-jp -> shift_jis converter is + available, then the chain is automatically constructed. (N.B. I f we + have fixed width buffers in the future, then we could have ASCII -> 8-bit + char -> 16-bit char -> ISO-2022-JP (with escape sequences). + + EOL handling is a char <-> char coding. It should not be part of another + coding system except as a convenience for users. For text coding, + automatically insert EOL handlers between char <-> octet boundaries. + + ------------------------------------------------------------------ + ABOUT DETECTION + ------------------------------------------------------------------ + + + ------------------------------------------------------------------ + EFFICIENCY OF CODING CONVERSION WITH MULTIPLE COPIES/CHAINS + ------------------------------------------------------------------ + + A comment in encode_decode_coding_region(): + + The chain of streams looks like this: + + [BUFFER] <----- (( read from/send to loop )) + ------> [CHAR->BYTE i.e. ENCODE AS BINARY if source is + in bytes] + ------> [ENCODE/DECODE AS SPECIFIED] + ------> [BYTE->CHAR i.e. DECODE AS BINARY + if sink is in bytes] + ------> [AUTODETECT EOL if + we're decoding and + coding system calls + for this] + ------> [BUFFER] + + sjt (?) responds: + + Of course, this is just horrible. BYTE<->CHAR should only be available + to I/O routines. It should not be visible to Mule proper. + + A comment on the implementation. Hrvoje and Kyle worry about the + inefficiency of repeated copying among buffers that chained coding + systems entail. But this may not be as time inefficient as it appears + in the Mule ("house rules") context. The issue is how do you do chain + coding systems without copying? In theory you could have + + IChar external_to_raw (ExtChar *cp, State *s); + IChar decode_utf16 (IChar c, State *s); + IChar decode_crlf (ExtChar *cp, State *s); + + typedef Ichar (*Converter[]) (Ichar, State*); + + Converter utf16[2] = { &decode_utf16, &decode_crlf }; + + void convert (ExtChar *inbuf, IChar *outbuf, Converter cvtr) + { + int i; + ExtChar c; + State s; + + while (c = external_to_raw (*inbuf++, &s)) + { + for (i = 0; i < sizeof(cvtr)/sizeof(Converter); ++i) + if (s.ready) + c = (*cvtr[i]) (c, &s); + } + if (s.ready) + *outbuf++ = c; + } + + But this is a lot of function calls; what Ben is doing is basically + reducing this to one call per buffer-full. The only way to avoid this + is to hardcode all the "interesting" coding systems, maybe using + inline or macros to give structure. But this is still a huge amount + of work, and code. + + One advantage to the call-per-char approach is that we might be able + to do something about the marker/extent destruction that coding + normally entails. + + ben sez: + + it should be possible to preserve the markers/extents without + switching completely to one-call-per-char -- we could at least do one + call per "run", where a run is more or less the maximal stretch of + text not overlapping any markers or extent boundaries. (It's a bit + more complicated if we want to properly support the different extent + begins/ends; in some cases we might have to pump a single character + adjacent to where two extents meet.) The "stateless" way that I wrote + all of the conversion routines may be a real hassle but it allows + something like this to work without too much problem -- pump in one + run at a time into one end of the chain, do a flush after each + iteration, and stick what comes out the other end in its place. + + ------------------------------------------------------------------ + 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.) + + -------------------------------------------------------------------------- + ABOUT PDUMP, UNICODE, AND RUNNING XEMACS FROM A DIRECTORY WITH WEIRD CHARS + -------------------------------------------------------------------------- + +-- 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. + + + ========================================================================== + - Generalized language appropriate word wrapping (requires + layout-exposing API defined in BIDI section) + ========================================================================== + + ========================================================================== + - Make Custom Mule-aware + ========================================================================== + + ========================================================================== + - Composite character support + ========================================================================== + + ========================================================================== + - Language appropriate sorting and searching + ========================================================================== + + ========================================================================== + - Glyph shaping for Arabic and Devanagari + ========================================================================== + +- (needs to be handled mostly + at C level, as part of layout; luckily it's entirely local in its + changes, as this is not hard) + + + ========================================================================== + Consider moving language selection Menu up to be parallel with Mule menu + ========================================================================== + +*/ + + /************************************************************************/ /* declarations */ @@ -695,7 +1340,7 @@ int retval; va_start (args, format); - retval = vsprintf ((char *) buffer, format, args); + retval = vsprintf ((Chbyte *) buffer, format, args); va_end (args); return retval; @@ -760,13 +1405,13 @@ } int -ascii_strcasecmp (const Char_ASCII *s1, const Char_ASCII *s2) +ascii_strcasecmp (const Ascbyte *s1, const Ascbyte *s2) { return qxestrcasecmp ((const Ibyte *) s1, (const Ibyte *) s2); } int -qxestrcasecmp_c (const Ibyte *s1, const Char_ASCII *s2) +qxestrcasecmp_ascii (const Ibyte *s1, const Ascbyte *s2) { return qxestrcasecmp (s1, (const Ibyte *) s2); } @@ -814,13 +1459,13 @@ } int -ascii_strncasecmp (const Char_ASCII *s1, const Char_ASCII *s2, Bytecount len) +ascii_strncasecmp (const Ascbyte *s1, const Ascbyte *s2, Bytecount len) { return qxestrncasecmp ((const Ibyte *) s1, (const Ibyte *) s2, len); } int -qxestrncasecmp_c (const Ibyte *s1, const Char_ASCII *s2, Bytecount len) +qxestrncasecmp_ascii (const Ibyte *s1, const Ascbyte *s2, Bytecount len) { return qxestrncasecmp (s1, (const Ibyte *) s2, len); } @@ -1034,6 +1679,37 @@ XSTRING_DATA (s2), XSTRING_LENGTH (s2)); } +/* Compare a wide string with an ASCII string */ + +int +wcscmp_ascii (const wchar_t *s1, const Ascbyte *s2) +{ + while (*s1 && *s2) + { + if (*s1 != *s2) + break; + s1++, s2++; + } + + return *s1 - *s2; +} + +int +wcsncmp_ascii (const wchar_t *s1, const Ascbyte *s2, Charcount len) +{ + while (len--) + { + int diff = *s1 - *s2; + if (diff != 0) + return diff; + if (!*s1) + return 0; + s1++, s2++; + } + + return 0; +} + /************************************************************************/ /* conversion between textual representations */ @@ -1043,7 +1719,7 @@ void convert_ibyte_string_into_ichar_dynarr (const Ibyte *str, Bytecount len, - Ichar_dynarr *dyn) + Ichar_dynarr *dyn) { const Ibyte *strend = str + len; @@ -1057,7 +1733,7 @@ Charcount convert_ibyte_string_into_ichar_string (const Ibyte *str, Bytecount len, - Ichar *arr) + Ichar *arr) { const Ibyte *strend = str + len; Charcount newlen = 0; @@ -1099,7 +1775,7 @@ Bytecount *len_out) { /* Damn zero-termination. */ - Ibyte *str = (Ibyte *) ALLOCA (nels * MAX_ICHAR_LEN + 1); + Ibyte *str = alloca_ibytes (nels * MAX_ICHAR_LEN + 1); Ibyte *strorig = str; Bytecount len; @@ -1109,7 +1785,7 @@ str += set_itext_ichar (str, arr[i]); *str = '\0'; len = str - strorig; - str = (Ibyte *) xmalloc (1 + len); + str = xnew_ibytes (1 + len); memcpy (str, strorig, 1 + len); if (len_out) *len_out = len; @@ -1440,14 +2116,14 @@ ei->max_size_allocated_ = eifind_large_enough_buffer (0, ei->bytelen_ + 1); - newdata = (Ibyte *) xmalloc (ei->max_size_allocated_); + newdata = xnew_ibytes (ei->max_size_allocated_); memcpy (newdata, ei->data_, ei->bytelen_ + 1); ei->data_ = newdata; } if (ei->extdata_) { - Extbyte *newdata = (Extbyte *) xmalloc (ei->extlen_ + 2); + Extbyte *newdata = xnew_extbytes (ei->extlen_ + 2); memcpy (newdata, ei->extdata_, ei->extlen_); /* Double null-terminate in case of Unicode data */ @@ -1460,7 +2136,7 @@ int eicmp_1 (Eistring *ei, Bytecount off, Charcount charoff, Bytecount len, Charcount charlen, const Ibyte *data, - const Eistring *ei2, int is_c, int fold_case) + const Eistring *ei2, int is_ascii, int fold_case) { assert ((off < 0) != (charoff < 0)); if (off < 0) @@ -1477,7 +2153,7 @@ assert (off >= 0 && off <= ei->bytelen_); assert (len >= 0 && off + len <= ei->bytelen_); assert ((data == 0) != (ei == 0)); - assert ((is_c != 0) == (data != 0)); + assert ((is_ascii != 0) == (data != 0)); assert (fold_case >= 0 && fold_case <= 2); { @@ -1495,8 +2171,8 @@ dstlen = ei2->bytelen_; } - if (is_c) - EI_ASSERT_ASCII ((Char_ASCII *) dst, dstlen); + if (is_ascii) + ASSERT_ASCTEXT_ASCII_LEN ((Ascbyte *) dst, dstlen); return (fold_case == 0 ? qxememcmp4 (src, len, dst, dstlen) : fold_case == 1 ? qxememcasecmp4 (src, len, dst, dstlen) : @@ -1527,12 +2203,6 @@ #ifdef MULE -/* Skip as many ASCII bytes as possible in the memory block [PTR, END). - Return pointer to the first non-ASCII byte. optimized for long - stretches of ASCII. */ -inline static const Ibyte * -skip_ascii (const Ibyte *ptr, const Ibyte *end) -{ #ifdef EFFICIENT_INT_128_BIT # define STRIDE_TYPE INT_128_BIT # define HIGH_BIT_MASK \ @@ -1550,6 +2220,12 @@ #define ALIGNED(ptr) ((((EMACS_UINT) ptr) & ALIGN_BITS) == 0) #define STRIDE sizeof (STRIDE_TYPE) +/* Skip as many ASCII bytes as possible in the memory block [PTR, END). + Return pointer to the first non-ASCII byte. optimized for long + stretches of ASCII. */ +inline static const Ibyte * +skip_ascii (const Ibyte *ptr, const Ibyte *end) +{ const unsigned STRIDE_TYPE *ascii_end; /* Need to do in 3 sections -- before alignment start, aligned chunk, @@ -1572,6 +2248,34 @@ return ptr; } +/* Skip as many ASCII bytes as possible in the memory block [END, PTR), + going downwards. Return pointer to the location above the first + non-ASCII byte. Optimized for long stretches of ASCII. */ +inline static const Ibyte * +skip_ascii_down (const Ibyte *ptr, const Ibyte *end) +{ + const unsigned STRIDE_TYPE *ascii_end; + + /* Need to do in 3 sections -- before alignment start, aligned chunk, + after alignment end. */ + while (!ALIGNED (ptr)) + { + if (ptr == end || !byte_ascii_p (*(ptr - 1))) + return ptr; + ptr--; + } + ascii_end = (const unsigned STRIDE_TYPE *) ptr - 1; + /* This loop screams, because we can detect ASCII + characters 4 or 8 at a time. */ + while ((const Ibyte *) ascii_end >= end + && !(*ascii_end & HIGH_BIT_MASK)) + ascii_end--; + ptr = (Ibyte *) (ascii_end + 1); + while (ptr > end && byte_ascii_p (*(ptr - 1))) + ptr--; + return ptr; +} + /* Function equivalents of bytecount_to_charcount/charcount_to_bytecount. These work on strings of all sizes but are more efficient than a simple loop on large strings and probably less efficient on sufficiently small @@ -1631,6 +2335,31 @@ return newptr - ptr; } +/* Function equivalent of charcount_to_bytecount_down. This works on strings + of all sizes but is more efficient than a simple loop on large strings + and probably less efficient on sufficiently small strings. */ + +Bytecount +charcount_to_bytecount_down_fun (const Ibyte *ptr, Charcount len) +{ + const Ibyte *newptr = ptr; + while (1) + { + const Ibyte *newnewptr = skip_ascii_down (newptr, newptr - len); + len -= newptr - newnewptr; + newptr = newnewptr; + /* Skip over all non-ASCII chars, counting the length and + stopping if it's zero */ + while (len && !byte_ascii_p (*(newptr - 1))) + if (ibyte_first_byte_p (*--newptr)) + len--; + if (!len) + break; + } + text_checking_assert (ptr - newptr >= 0); + return ptr - newptr; +} + /* The next two functions are the actual meat behind the charbpos-to-bytebpos and bytebpos-to-charbpos conversions. Currently the method they use is fairly unsophisticated; see buffer.h. @@ -1641,36 +2370,281 @@ Similar considerations apply to bytebpos_to_charbpos_func(), although less so because the function is not called so often. + */ + +/* - #### At some point this should use a more sophisticated method; - see buffer.h. */ +Info on Byte-Char conversion: + (Info-goto-node "(internals)Byte-Char Position Conversion") +*/ + +#ifdef OLD_BYTE_CHAR static int not_very_random_number; +#endif /* OLD_BYTE_CHAR */ + +#define OLD_LOOP + +/* If we are this many characters away from any known position, cache the + new position in the buffer's char-byte cache. */ +#define FAR_AWAY_DISTANCE 5000 + +/* Converting between character positions and byte positions. */ + +/* There are several places in the buffer where we know + the correspondence: BEG, BEGV, PT, GPT, ZV and Z, + and everywhere there is a marker. So we find the one of these places + that is closest to the specified position, and scan from there. */ + +/* This macro is a subroutine of charbpos_to_bytebpos_func. + Note that it is desirable that BYTEPOS is not evaluated + except when we really want its value. */ + +#define CONSIDER(CHARPOS, BYTEPOS) \ +do \ +{ \ + Charbpos this_charpos = (CHARPOS); \ + int changed = 0; \ + \ + if (this_charpos == x) \ + { \ + retval = (BYTEPOS); \ + goto done; \ + } \ + else if (this_charpos > x) \ + { \ + if (this_charpos < best_above) \ + { \ + best_above = this_charpos; \ + best_above_byte = (BYTEPOS); \ + changed = 1; \ + } \ + } \ + else if (this_charpos > best_below) \ + { \ + best_below = this_charpos; \ + best_below_byte = (BYTEPOS); \ + changed = 1; \ + } \ + \ + if (changed) \ + { \ + if (best_above - best_below == best_above_byte - best_below_byte) \ + { \ + retval = best_below_byte + (x - best_below); \ + goto done; \ + } \ + } \ +} \ +while (0) + Bytebpos charbpos_to_bytebpos_func (struct buffer *buf, Charbpos x) { +#ifdef OLD_BYTE_CHAR Charbpos bufmin; Charbpos bufmax; Bytebpos bytmin; Bytebpos bytmax; int size; int forward_p; - Bytebpos retval; int diff_so_far; int add_to_cache = 0; - PROFILE_DECLARE (); +#endif /* OLD_BYTE_CHAR */ - /* Check for some cached positions, for speed. */ - if (x == BUF_PT (buf)) - return BYTE_BUF_PT (buf); - if (x == BUF_ZV (buf)) - return BYTE_BUF_ZV (buf); - if (x == BUF_BEGV (buf)) - return BYTE_BUF_BEGV (buf); + Charbpos best_above, best_below; + Bytebpos best_above_byte, best_below_byte; + int i; + struct buffer_text *t; + Bytebpos retval; + + PROFILE_DECLARE (); PROFILE_RECORD_ENTERING_SECTION (QSin_char_byte_conversion); + best_above = BUF_Z (buf); + best_above_byte = BYTE_BUF_Z (buf); + + /* In this case, we simply have all one-byte characters. But this should + have been intercepted before, in charbpos_to_bytebpos(). */ + text_checking_assert (best_above != best_above_byte); + + best_below = BUF_BEG (buf); + best_below_byte = BYTE_BUF_BEG (buf); + + /* We find in best_above and best_above_byte + the closest known point above CHARPOS, + and in best_below and best_below_byte + the closest known point below CHARPOS, + + If at any point we can tell that the space between those + two best approximations is all single-byte, + we interpolate the result immediately. */ + + CONSIDER (BUF_PT (buf), BYTE_BUF_PT (buf)); + CONSIDER (BUF_GPT (buf), BYTE_BUF_GPT (buf)); + CONSIDER (BUF_BEGV (buf), BYTE_BUF_BEGV (buf)); + CONSIDER (BUF_ZV (buf), BYTE_BUF_ZV (buf)); + + t = buf->text; + CONSIDER (t->cached_charpos, t->cached_bytepos); + + /* Check the most recently entered positions first */ + + for (i = t->next_cache_pos - 1; i >= 0; i--) + { + CONSIDER (t->mule_charbpos_cache[i], t->mule_bytebpos_cache[i]); + + /* If we are down to a range of 50 chars, + don't bother checking any other markers; + scan the intervening chars directly now. */ + if (best_above - best_below < 50) + break; + } + + /* We get here if we did not exactly hit one of the known places. + We have one known above and one known below. + Scan, counting characters, from whichever one is closer. */ + + if (x - best_below < best_above - x) + { + int record = x - best_below > FAR_AWAY_DISTANCE; + +#ifdef OLD_LOOP /* old code */ + while (best_below != x) + { + best_below++; + INC_BYTEBPOS (buf, best_below_byte); + } +#else + text_checking_assert (BUF_FORMAT (buf) == FORMAT_DEFAULT); + /* The gap should not occur between best_below and x, or we will be + screwed in using charcount_to_bytecount(). It should not be exactly + at x either, because we already should have caught that. */ + text_checking_assert + (BUF_CEILING_OF_IGNORE_ACCESSIBLE (buf, best_below) > x); + + /* Using charcount_to_bytecount() is potentially a lot faster than a + simple loop using INC_BYTEBPOS() because (a) the checks for gap + and buffer format are factored out instead of getting checked + every time; (b) the checking goes 4 or 8 bytes at a time in ASCII + text. + */ + best_below_byte += + charcount_to_bytecount + (BYTE_BUF_BYTE_ADDRESS (buf, best_below_byte), x - best_below); + best_below = x; +#endif /* 0 */ + + /* If this position is quite far from the nearest known position, + cache the correspondence. + + NB FSF does this: "... by creating a marker here. + It will last until the next GC." + */ + + if (record) + { + /* If we have run out of positions to record, discard some of the + old ones. I used to use a circular buffer, which avoids the + need to block-move any memory. But it makes it more difficult + to keep track of which positions haven't been used -- commonly + we haven't yet filled out anywhere near the whole set of + positions and don't want to check them all. We should not be + recording that often, and block-moving is extremely fast in + any case. --ben */ + if (t->next_cache_pos == NUM_CACHED_POSITIONS) + { + memmove (t->mule_charbpos_cache, + t->mule_charbpos_cache + NUM_MOVED_POSITIONS, + sizeof (Charbpos) * + (NUM_CACHED_POSITIONS - NUM_MOVED_POSITIONS)); + memmove (t->mule_bytebpos_cache, + t->mule_bytebpos_cache + NUM_MOVED_POSITIONS, + sizeof (Bytebpos) * + (NUM_CACHED_POSITIONS - NUM_MOVED_POSITIONS)); + t->next_cache_pos -= NUM_MOVED_POSITIONS; + } + t->mule_charbpos_cache[t->next_cache_pos] = best_below; + t->mule_bytebpos_cache[t->next_cache_pos] = best_below_byte; + t->next_cache_pos++; + } + + t->cached_charpos = best_below; + t->cached_bytepos = best_below_byte; + + retval = best_below_byte; + text_checking_assert (best_below_byte >= best_below); + goto done; + } + else + { + int record = best_above - x > FAR_AWAY_DISTANCE; + +#ifdef OLD_LOOP + while (best_above != x) + { + best_above--; + DEC_BYTEBPOS (buf, best_above_byte); + } +#else + text_checking_assert (BUF_FORMAT (buf) == FORMAT_DEFAULT); + /* The gap should not occur between best_above and x, or we will be + screwed in using charcount_to_bytecount_down(). It should not be + exactly at x either, because we already should have caught + that. */ + text_checking_assert + (BUF_FLOOR_OF_IGNORE_ACCESSIBLE (buf, best_above) < x); + + /* Using charcount_to_bytecount_down() is potentially a lot faster + than a simple loop using DEC_BYTEBPOS(); see above. */ + best_above_byte -= + charcount_to_bytecount_down + /* BYTE_BUF_BYTE_ADDRESS will return a value on the high side of the + gap if we are at the gap, which is the wrong side. So do the + following trick instead. */ + (BYTE_BUF_BYTE_ADDRESS_BEFORE (buf, best_above_byte) + 1, + best_above - x); + best_above = x; +#endif /* SLEDGEHAMMER_CHECK_TEXT */ + + + /* If this position is quite far from the nearest known position, + cache the correspondence. + + NB FSF does this: "... by creating a marker here. + It will last until the next GC." + */ + if (record) + { + if (t->next_cache_pos == NUM_CACHED_POSITIONS) + { + memmove (t->mule_charbpos_cache, + t->mule_charbpos_cache + NUM_MOVED_POSITIONS, + sizeof (Charbpos) * + (NUM_CACHED_POSITIONS - NUM_MOVED_POSITIONS)); + memmove (t->mule_bytebpos_cache, + t->mule_bytebpos_cache + NUM_MOVED_POSITIONS, + sizeof (Bytebpos) * + (NUM_CACHED_POSITIONS - NUM_MOVED_POSITIONS)); + t->next_cache_pos -= NUM_MOVED_POSITIONS; + } + t->mule_charbpos_cache[t->next_cache_pos] = best_above; + t->mule_bytebpos_cache[t->next_cache_pos] = best_above_byte; + t->next_cache_pos++; + } + + t->cached_charpos = best_above; + t->cached_bytepos = best_above_byte; + + retval = best_above_byte; + text_checking_assert (best_above_byte >= best_above); + goto done; + } + +#ifdef OLD_BYTE_CHAR + bufmin = buf->text->mule_bufmin; bufmax = buf->text->mule_bufmax; bytmin = buf->text->mule_bytmin; @@ -1735,7 +2709,7 @@ } #ifdef ERROR_CHECK_TEXT else if (x >= bufmin) - abort (); + ABORT (); #endif else { @@ -1789,7 +2763,7 @@ /* I considered keeping the positions ordered. This would speed up this loop, but updating the cache would take longer, so it doesn't seem like it would really matter. */ - for (i = 0; i < 16; i++) + for (i = 0; i < NUM_CACHED_POSITIONS; i++) { int diff = buf->text->mule_charbpos_cache[i] - x; @@ -1921,38 +2895,249 @@ buf->text->mule_bytebpos_cache[replace_loc] = retval; } +#endif /* OLD_BYTE_CHAR */ + +done: PROFILE_RECORD_EXITING_SECTION (QSin_char_byte_conversion); return retval; } +#undef CONSIDER + +/* bytepos_to_charpos returns the char position corresponding to BYTEPOS. */ + +/* This macro is a subroutine of bytebpos_to_charbpos_func. + It is used when BYTEPOS is actually the byte position. */ + +#define CONSIDER(BYTEPOS, CHARPOS) \ +do \ +{ \ + Bytebpos this_bytepos = (BYTEPOS); \ + int changed = 0; \ + \ + if (this_bytepos == x) \ + { \ + retval = (CHARPOS); \ + goto done; \ + } \ + else if (this_bytepos > x) \ + { \ + if (this_bytepos < best_above_byte) \ + { \ + best_above = (CHARPOS); \ + best_above_byte = this_bytepos; \ + changed = 1; \ + } \ + } \ + else if (this_bytepos > best_below_byte) \ + { \ + best_below = (CHARPOS); \ + best_below_byte = this_bytepos; \ + changed = 1; \ + } \ + \ + if (changed) \ + { \ + if (best_above - best_below == best_above_byte - best_below_byte) \ + { \ + retval = best_below + (x - best_below_byte); \ + goto done; \ + } \ + } \ +} \ +while (0) + /* The logic in this function is almost identical to the logic in the previous function. */ Charbpos bytebpos_to_charbpos_func (struct buffer *buf, Bytebpos x) { +#ifdef OLD_BYTE_CHAR Charbpos bufmin; Charbpos bufmax; Bytebpos bytmin; Bytebpos bytmax; int size; int forward_p; - Charbpos retval; int diff_so_far; int add_to_cache = 0; - PROFILE_DECLARE (); +#endif /* OLD_BYTE_CHAR */ + + Charbpos best_above, best_above_byte; + Bytebpos best_below, best_below_byte; + int i; + struct buffer_text *t; + Charbpos retval; - /* Check for some cached positions, for speed. */ - if (x == BYTE_BUF_PT (buf)) - return BUF_PT (buf); - if (x == BYTE_BUF_ZV (buf)) - return BUF_ZV (buf); - if (x == BYTE_BUF_BEGV (buf)) - return BUF_BEGV (buf); + PROFILE_DECLARE (); PROFILE_RECORD_ENTERING_SECTION (QSin_char_byte_conversion); + best_above = BUF_Z (buf); + best_above_byte = BYTE_BUF_Z (buf); + + /* In this case, we simply have all one-byte characters. But this should + have been intercepted before, in bytebpos_to_charbpos(). */ + text_checking_assert (best_above != best_above_byte); + + best_below = BUF_BEG (buf); + best_below_byte = BYTE_BUF_BEG (buf); + + CONSIDER (BYTE_BUF_PT (buf), BUF_PT (buf)); + CONSIDER (BYTE_BUF_GPT (buf), BUF_GPT (buf)); + CONSIDER (BYTE_BUF_BEGV (buf), BUF_BEGV (buf)); + CONSIDER (BYTE_BUF_ZV (buf), BUF_ZV (buf)); + + t = buf->text; + CONSIDER (t->cached_bytepos, t->cached_charpos); + + /* Check the most recently entered positions first */ + + for (i = t->next_cache_pos - 1; i >= 0; i--) + { + CONSIDER (t->mule_bytebpos_cache[i], t->mule_charbpos_cache[i]); + + /* If we are down to a range of 50 chars, + don't bother checking any other markers; + scan the intervening chars directly now. */ + if (best_above - best_below < 50) + break; + } + + /* We get here if we did not exactly hit one of the known places. + We have one known above and one known below. + Scan, counting characters, from whichever one is closer. */ + + if (x - best_below_byte < best_above_byte - x) + { + int record = x - best_below_byte > 5000; + +#ifdef OLD_LOOP /* old code */ + while (best_below_byte < x) + { + best_below++; + INC_BYTEBPOS (buf, best_below_byte); + } +#else + text_checking_assert (BUF_FORMAT (buf) == FORMAT_DEFAULT); + /* The gap should not occur between best_below and x, or we will be + screwed in using charcount_to_bytecount(). It should not be exactly + at x either, because we already should have caught that. */ + text_checking_assert + (BYTE_BUF_CEILING_OF_IGNORE_ACCESSIBLE (buf, best_below_byte) > x); + + /* Using bytecount_to_charcount() is potentially a lot faster than + a simple loop above using INC_BYTEBPOS(); see above. + */ + best_below += + bytecount_to_charcount + (BYTE_BUF_BYTE_ADDRESS (buf, best_below_byte), x - best_below_byte); + best_below_byte = x; +#endif + + /* If this position is quite far from the nearest known position, + cache the correspondence. + + NB FSF does this: "... by creating a marker here. + It will last until the next GC." + */ + + if (record) + { + if (t->next_cache_pos == NUM_CACHED_POSITIONS) + { + memmove (t->mule_charbpos_cache, + t->mule_charbpos_cache + NUM_MOVED_POSITIONS, + sizeof (Charbpos) * + (NUM_CACHED_POSITIONS - NUM_MOVED_POSITIONS)); + memmove (t->mule_bytebpos_cache, + t->mule_bytebpos_cache + NUM_MOVED_POSITIONS, + sizeof (Bytebpos) * + (NUM_CACHED_POSITIONS - NUM_MOVED_POSITIONS)); + t->next_cache_pos -= NUM_MOVED_POSITIONS; + } + t->mule_charbpos_cache[t->next_cache_pos] = best_below; + t->mule_bytebpos_cache[t->next_cache_pos] = best_below_byte; + t->next_cache_pos++; + } + + + t->cached_charpos = best_below; + t->cached_bytepos = best_below_byte; + + retval = best_below; + text_checking_assert (best_below_byte >= best_below); + goto done; + } + else + { + int record = best_above_byte - x > 5000; + +#ifdef OLD_LOOP /* old code */ + while (best_above_byte > x) + { + best_above--; + DEC_BYTEBPOS (buf, best_above_byte); + } +#else + text_checking_assert (BUF_FORMAT (buf) == FORMAT_DEFAULT); + /* The gap should not occur between best_above and x, or we will be + screwed in using bytecount_to_charcount_down(). It should not be + exactly at x either, because we already should have caught + that. */ + text_checking_assert + (BYTE_BUF_FLOOR_OF_IGNORE_ACCESSIBLE (buf, best_above_byte) < x); + + /* Using bytecount_to_charcount_down() is potentially a lot faster + than a simple loop using INC_BYTEBPOS(); see above. */ + best_above -= + bytecount_to_charcount_down + /* BYTE_BUF_BYTE_ADDRESS will return a value on the high side of the + gap if we are at the gap, which is the wrong side. So do the + following trick instead. */ + (BYTE_BUF_BYTE_ADDRESS_BEFORE (buf, best_above_byte) + 1, + best_above_byte - x); + best_above_byte = x; +#endif + + + /* If this position is quite far from the nearest known position, + cache the correspondence. + + NB FSF does this: "... by creating a marker here. + It will last until the next GC." + */ + if (record) + { + if (t->next_cache_pos == NUM_CACHED_POSITIONS) + { + memmove (t->mule_charbpos_cache, + t->mule_charbpos_cache + NUM_MOVED_POSITIONS, + sizeof (Charbpos) * + (NUM_CACHED_POSITIONS - NUM_MOVED_POSITIONS)); + memmove (t->mule_bytebpos_cache, + t->mule_bytebpos_cache + NUM_MOVED_POSITIONS, + sizeof (Bytebpos) * + (NUM_CACHED_POSITIONS - NUM_MOVED_POSITIONS)); + t->next_cache_pos -= NUM_MOVED_POSITIONS; + } + t->mule_charbpos_cache[t->next_cache_pos] = best_above; + t->mule_bytebpos_cache[t->next_cache_pos] = best_above_byte; + t->next_cache_pos++; + } + + t->cached_charpos = best_above; + t->cached_bytepos = best_above_byte; + + retval = best_above; + text_checking_assert (best_above_byte >= best_above); + goto done; + } + +#ifdef OLD_BYTE_CHAR + bufmin = buf->text->mule_bufmin; bufmax = buf->text->mule_bufmax; bytmin = buf->text->mule_bytmin; @@ -2017,7 +3202,7 @@ } #ifdef ERROR_CHECK_TEXT else if (x >= bytmin) - abort (); + ABORT (); #endif else { @@ -2071,7 +3256,7 @@ /* I considered keeping the positions ordered. This would speed up this loop, but updating the cache would take longer, so it doesn't seem like it would really matter. */ - for (i = 0; i < 16; i++) + for (i = 0; i < NUM_CACHED_POSITIONS; i++) { int diff = buf->text->mule_bytebpos_cache[i] - x; @@ -2202,7 +3387,9 @@ buf->text->mule_charbpos_cache[replace_loc] = retval; buf->text->mule_bytebpos_cache[replace_loc] = x; } +#endif /* OLD_BYTE_CHAR */ +done: PROFILE_RECORD_EXITING_SECTION (QSin_char_byte_conversion); return retval; @@ -2216,11 +3403,13 @@ Bytecount bytelength, Charcount charlength) { +#ifdef OLD_BYTE_CHAR int size = (1 << buf->text->mule_shifter) + !!buf->text->mule_three_p; +#endif /* OLD_BYTE_CHAR */ int i; /* Adjust the cache of known positions. */ - for (i = 0; i < 16; i++) + for (i = 0; i < buf->text->next_cache_pos; i++) { if (buf->text->mule_charbpos_cache[i] > start) @@ -2230,6 +3419,15 @@ } } + /* Adjust the special cached position. */ + + if (buf->text->cached_charpos > start) + { + buf->text->cached_charpos += charlength; + buf->text->cached_bytepos += bytelength; + } + +#ifdef OLD_BYTE_CHAR if (start >= buf->text->mule_bufmax) return; @@ -2304,6 +3502,7 @@ } } } +#endif /* OLD_BYTE_CHAR */ } /* Text from START to END (equivalent in Bytebpos's: from BYTE_START to @@ -2317,7 +3516,7 @@ int i; /* Adjust the cache of known positions. */ - for (i = 0; i < 16; i++) + for (i = 0; i < buf->text->next_cache_pos; i++) { /* After the end; gets shoved backward */ if (buf->text->mule_charbpos_cache[i] > end) @@ -2333,6 +3532,22 @@ } } + /* Adjust the special cached position. */ + + /* After the end; gets shoved backward */ + if (buf->text->cached_charpos > end) + { + buf->text->cached_charpos -= end - start; + buf->text->cached_bytepos -= byte_end - byte_start; + } + /* In the range; moves to start of range */ + else if (buf->text->cached_charpos > start) + { + buf->text->cached_charpos = start; + buf->text->cached_bytepos = byte_start; + } + +#ifdef OLD_BYTE_CHAR /* We don't care about any text after the end of the known region. */ end = min (end, buf->text->mule_bufmax); @@ -2355,6 +3570,7 @@ buf->text->mule_bufmin -= end - start; buf->text->mule_bytmin -= byte_end - byte_start; } +#endif /* OLD_BYTE_CHAR */ } #endif /* MULE */ @@ -2833,6 +4049,7 @@ Extbyte_dynarr *conversion_out_dynarr; PROFILE_DECLARE (); + assert (!inhibit_non_essential_conversion_operations); PROFILE_RECORD_ENTERING_SECTION (QSin_internal_external_conversion); count = begin_gc_forbidden (); @@ -3036,8 +4253,10 @@ places. */ int count; Ibyte_dynarr *conversion_in_dynarr; + Lisp_Object underlying_cs; PROFILE_DECLARE (); + assert (!inhibit_non_essential_conversion_operations); PROFILE_RECORD_ENTERING_SECTION (QSin_internal_external_conversion); count = begin_gc_forbidden (); @@ -3059,18 +4278,37 @@ internal_bind_int (&dfc_convert_to_internal_format_in_use, dfc_convert_to_internal_format_in_use + 1); - coding_system = get_coding_system_for_text_file (coding_system, 1); + /* The second call does the equivalent of both calls, but we need + the result after the first call (which wraps just a to-text + converter) as well as the result after the second call (which + also wraps an EOL-detection converter). */ + underlying_cs = get_coding_system_for_text_file (coding_system, 0); + coding_system = get_coding_system_for_text_file (underlying_cs, 1); if (source_type != DFC_TYPE_LISP_LSTREAM && sink_type != DFC_TYPE_LISP_LSTREAM && - coding_system_is_binary (coding_system)) + coding_system_is_binary (underlying_cs)) { #ifdef MULE - const Ibyte *ptr = (const Ibyte *) source->data.ptr; + const Ibyte *ptr; Bytecount len = source->data.len; - const Ibyte *end = ptr + len; + const Ibyte *end; + + /* Make sure no EOL conversion is needed. With a little work we + could handle EOL conversion as well but it may not be needed as an + optimization. */ + if (!EQ (coding_system, underlying_cs)) + { + for (ptr = (const Ibyte *) source->data.ptr, end = ptr + len; + ptr < end; ptr++) + { + if (*ptr == '\r' || *ptr == '\n') + goto the_hard_way; + } + } - for (; ptr < end; ptr++) + for (ptr = (const Ibyte *) source->data.ptr, end = ptr + len; + ptr < end; ptr++) { Ibyte c = *ptr; @@ -3096,25 +4334,38 @@ involved */ else if (source_type != DFC_TYPE_LISP_LSTREAM && sink_type != DFC_TYPE_LISP_LSTREAM && - dfc_coding_system_is_unicode (coding_system)) + dfc_coding_system_is_unicode (underlying_cs)) { - const Ibyte *ptr = (const Ibyte *) source->data.ptr + 1; + const Ibyte *ptr; Bytecount len = source->data.len; - const Ibyte *end = ptr + len; + const Ibyte *end; if (len & 1) goto the_hard_way; - for (; ptr < end; ptr += 2) + /* Make sure only ASCII/Latin-1 is involved */ + for (ptr = (const Ibyte *) source->data.ptr + 1, end = ptr + len; + ptr < end; ptr += 2) { if (*ptr) goto the_hard_way; } - ptr = (const Ibyte *) source->data.ptr; - end = ptr + len; + /* Make sure no EOL conversion is needed. With a little work we + could handle EOL conversion as well but it may not be needed as an + optimization. */ + if (!EQ (coding_system, underlying_cs)) + { + for (ptr = (const Ibyte *) source->data.ptr, end = ptr + len; + ptr < end; ptr += 2) + { + if (*ptr == '\r' || *ptr == '\n') + goto the_hard_way; + } + } - for (; ptr < end; ptr += 2) + for (ptr = (const Ibyte *) source->data.ptr, end = ptr + len; + ptr < end; ptr += 2) { Ibyte c = *ptr; @@ -3142,9 +4393,9 @@ Lisp_Object instream, outstream; Lstream *reader, *writer; -#ifdef WIN32_ANY +#if defined (WIN32_ANY) || defined (MULE) the_hard_way: -#endif /* WIN32_ANY */ +#endif delete_count = 0; if (source_type == DFC_TYPE_LISP_LSTREAM) instream = source->lisp_object; @@ -3223,6 +4474,55 @@ } /* ----------------------------------------------------------------------- */ +/* Alloca-conversion helpers */ +/* ----------------------------------------------------------------------- */ + +/* For alloca(), things are trickier because the calling function needs to + allocate. This means that the caller needs to do the following: + + (a) invoke us to do the conversion, remember the data and return the size. + (b) alloca() the proper size. + (c) invoke us again to copy the data. + + We need to handle the possibility of two or more invocations of the + converter in the same expression. In such cases it's conceivable that + the evaluation of the sub-expressions will be overlapping (e.g. one size + function called, then the other one called, then the copy functions + called). To handle this, we keep a list of active data, indexed by the + src expression. (We use the stringize operator to avoid evaluating the + expression multiple times.) If the caller uses the exact same src + expression twice in two converter calls in the same subexpression, we + will lose, but at least we can check for this and ABORT(). We could + conceivably try to index on other parameters as well, but there is not + really any point. */ + +alloca_convert_vals_dynarr *active_alloca_convert; + +int +find_pos_of_existing_active_alloca_convert (const char *srctext) +{ + alloca_convert_vals *vals = NULL; + int i; + + if (!active_alloca_convert) + active_alloca_convert = Dynarr_new (alloca_convert_vals); + + for (i = 0; i < Dynarr_length (active_alloca_convert); i++) + { + vals = Dynarr_atp (active_alloca_convert, i); + /* On my system, two different occurrences of the same stringized + argument always point to the same string. However, on someone + else's system, that wasn't the case. We check for equality + first, since it seems systems work my way more than the other + way. */ + if (vals->srctext == srctext || !strcmp (vals->srctext, srctext)) + return i; + } + + return -1; +} + +/* ----------------------------------------------------------------------- */ /* New-style DFC converters (data is returned rather than stored into var) */ /* ----------------------------------------------------------------------- */ @@ -3273,103 +4573,56 @@ break; default: - abort (); + ABORT (); } -} - -void * -new_dfc_convert_malloc (const void *src, Bytecount src_size, - enum new_dfc_src_type type, Lisp_Object codesys) -{ - void *dst; - Bytecount dst_size; - new_dfc_convert_now_damn_it (src, src_size, type, &dst, &dst_size, codesys); - return dst; + /* The size is always + 2 because we have double zero-termination at the + end of all data (for Unicode-correctness). */ + *dst_size += 2; } -/* For alloca(), things are trickier because the calling function needs to - allocate. This means that the caller needs to do the following: - - (a) invoke us to do the conversion, remember the data and return the size. - (b) alloca() the proper size. - (c) invoke us again to copy the data. - - We need to handle the possibility of two or more invocations of the - converter in the same expression. In such cases it's conceivable that - the evaluation of the sub-expressions will be overlapping (e.g. one size - function called, then the other one called, then the copy functions - called). To handle this, we keep a list of active data, indexed by the - src expression. (We use the stringize operator to avoid evaluating the - expression multiple times.) If the caller uses the exact same src - expression twice in two converter calls in the same subexpression, we - will lose, but at least we can check for this and abort(). We could - conceivably try to index on other parameters as well, but there is not - really any point. */ - -typedef struct -{ - const char *srctext; - void *dst; - Bytecount dst_size; -} dfc_e2c_vals; - -typedef struct +Bytecount +new_dfc_convert_size (const char *srctext, const void *src, + Bytecount src_size, enum new_dfc_src_type type, + Lisp_Object codesys) { - Dynarr_declare (dfc_e2c_vals); -} dfc_e2c_vals_dynarr; + alloca_convert_vals vals; -static dfc_e2c_vals_dynarr *active_dfc_e2c; + assert (find_pos_of_existing_active_alloca_convert (srctext) < 0); -static int -find_pos_of_existing_active_dfc_e2c (const char *srctext) -{ - dfc_e2c_vals *vals = NULL; - int i; + vals.srctext = srctext; - for (i = 0; i < Dynarr_length (active_dfc_e2c); i++) - { - vals = Dynarr_atp (active_dfc_e2c, i); - if (vals->srctext == srctext) - return i; - } + new_dfc_convert_now_damn_it (src, src_size, type, &vals.dst, &vals.dst_size, + codesys); - return -1; + Dynarr_add (active_alloca_convert, vals); + return vals.dst_size; } void * -new_dfc_convert_alloca (const char *srctext, void *alloca_data) +new_dfc_convert_copy_data (const char *srctext, void *alloca_data) { - dfc_e2c_vals *vals; - int i = find_pos_of_existing_active_dfc_e2c (srctext); + alloca_convert_vals *vals; + int i = find_pos_of_existing_active_alloca_convert (srctext); assert (i >= 0); - vals = Dynarr_atp (active_dfc_e2c, i); + vals = Dynarr_atp (active_alloca_convert, i); assert (alloca_data); - memcpy (alloca_data, vals->dst, vals->dst_size + 2); + memcpy (alloca_data, vals->dst, vals->dst_size); xfree (vals->dst, void *); - Dynarr_delete (active_dfc_e2c, i); + Dynarr_delete (active_alloca_convert, i); return alloca_data; } -Bytecount -new_dfc_convert_size (const char *srctext, const void *src, - Bytecount src_size, enum new_dfc_src_type type, - Lisp_Object codesys) +void * +new_dfc_convert_malloc (const void *src, Bytecount src_size, + enum new_dfc_src_type type, Lisp_Object codesys) { - dfc_e2c_vals vals; - - assert (find_pos_of_existing_active_dfc_e2c (srctext) < 0); - - vals.srctext = srctext; - - new_dfc_convert_now_damn_it (src, src_size, type, &vals.dst, &vals.dst_size, - codesys); + void *dst; + Bytecount dst_size; - Dynarr_add (active_dfc_e2c, vals); - /* The size is always + 2 because we have double zero-termination at the - end of all data (for Unicode-correctness). */ - return vals.dst_size + 2; + new_dfc_convert_now_damn_it (src, src_size, type, &dst, &dst_size, codesys); + return dst; } @@ -3893,7 +5146,6 @@ Ibyte_dynarr *); conversion_out_dynarr_list = Dynarr_new2 (Extbyte_dynarr_dynarr, Extbyte_dynarr *); - active_dfc_e2c = Dynarr_new (dfc_e2c_vals); for (i = 0; i <= MAX_BYTEBPOS_GAP_SIZE_3; i++) three_to_one_table[i] = i / 3; @@ -3902,8 +5154,6 @@ void vars_of_text (void) { - reinit_vars_of_text (); - QSin_char_byte_conversion = build_msg_string ("(in char-byte conversion)"); staticpro (&QSin_char_byte_conversion); QSin_internal_external_conversion = diff --text -u 'xemacs-21.5.18/src/text.h' 'xemacs-21.5.19/src/text.h' Index: ./src/text.h --- ./src/text.h Fri Oct 15 02:26:25 2004 +++ ./src/text.h Fri Jan 28 11:36:27 2005 @@ -1,7 +1,7 @@ /* Header file for text manipulation primitives and macros. Copyright (C) 1985-1995 Free Software Foundation, Inc. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -166,73 +166,8 @@ #endif /* not MULE */ -/* ---------------- Handling non-default formats ----------------- */ +/* For more discussion, see text.c, "handling non-default formats" */ -/* We support, at least to some extent, formats other than the default - variable-width format, for speed; all of these alternative formats are - fixed-width. Currently we only handle these non-default formats in - buffers, because access to their text is strictly controlled and thus - the details of the format mostly compartmentalized. The only really - tricky part is the search code -- the regex, Boyer-Moore, and - simple-search algorithms in search.c and regex.c. All other code that - knows directly about the buffer representation is the basic code to - modify or retrieve the buffer text. - - Supporting fixed-width formats in Lisp strings is harder, but possible - -- FSF currently does this, for example. In this case, however, - probably only 8-bit-fixed is reasonable for Lisp strings -- getting - non-ASCII-compatible fixed-width formats to work is much, much harder - because a lot of code assumes that strings are ASCII-compatible - (i.e. ASCII + other characters represented exclusively using high-bit - bytes) and a lot of code mixes Lisp strings and non-Lisp strings freely. - - The different possible fixed-width formats are 8-bit fixed, 16-bit - fixed, and 32-bit fixed. The latter can represent all possible - characters, but at a substantial memory penalty. The other two can - represent only a subset of the possible characters. How these subsets - are defined can be simple or very tricky. - - Currently we support only the default format and the 8-bit fixed format, - and in the latter, we only allow these to be the first 256 characters in - an Ichar (ASCII and Latin 1). - - One reasonable approach for 8-bit fixed is to allow the upper half to - represent any 1-byte charset, which is specified on a per-buffer basis. - This should work fairly well in practice since most documents are in - only one foreign language (possibly with some English mixed in). I - think FSF does something like this; or at least, they have something - called nonascii-translation-table and use it when converting from - 8-bit-fixed text ("unibyte text") to default text ("multibyte text"). - With 16-bit fixed, you could do something like assign chunks of the 64K - worth of characters to charsets as they're encountered in documents. - This should work well with most Asian documents. - - If/when we switch to using Unicode internally, we might have formats more - like this: - - -- UTF-8 or some extension as the default format. Perl uses an - extension that handles 64-bit chars and requires as much as 13 bytes per - char, vs. the standard of 31-bit chars and 6 bytes max. UTF-8 has the - same basic properties as our own variable-width format (see text.c, - Internal String Encoding) and so most code would not need to be changed. - - -- UTF-16 as a "pseudo-fixed" format (i.e. 16-bit fixed plus surrogates - for representing characters not in the BMP, aka >= 65536). The vast - majority of documents will have no surrogates in them so byte/char - conversion will be very fast. - - -- an 8-bit fixed format, like currently. - - -- possibly, UCS-4 as a 32-bit fixed format. - - The fixed-width formats essentially treat the buffer as an array of - 8-bit, 16-bit or 32-bit integers. This means that how they are stored - in memory (in particular, big-endian or little-endian) depends on the - native format of the machine's processor. It also means we have to - worry a bit about alignment (basically, we just need to keep the gap an - integral size of the character size, and get things aligned properly - when converting the buffer between formats). - */ typedef enum internal_format { FORMAT_DEFAULT, @@ -603,6 +538,26 @@ #endif /* MULE */ +#ifdef ERROR_CHECK_TEXT +#define ASSERT_ASCTEXT_ASCII_LEN(ptr, len) \ +do { \ + int aia2; \ + const Ascbyte *aia2ptr = (ptr); \ + int aia2len = (len); \ + \ + for (aia2 = 0; aia2 < aia2len; aia2++) \ + assert (aia2ptr[aia2] >= 0x00 && aia2ptr[aia2] < 0x7F); \ +} while (0) +#define ASSERT_ASCTEXT_ASCII(ptr) \ +do { \ + const Ascbyte *aiaz2 = (ptr); \ + ASSERT_ASCTEXT_ASCII_LEN (aiaz2, strlen (aiaz2)); \ +} while (0) +#else +#define ASSERT_ASCTEXT_ASCII_LEN(ptr, len) +#define ASSERT_ASCTEXT_ASCII(ptr) +#endif + /* -------------------------------------------------------------- */ /* Working with the length (in bytes and characters) of a */ /* section of internally-formatted text */ @@ -672,6 +627,68 @@ return charcount_to_bytecount_fun (ptr, len); } +MODULE_API Bytecount +charcount_to_bytecount_down_fun (const Ibyte *ptr, Charcount len); + +/* Given a pointer to a text string and a length in bytes, return + the equivalent length in characters of the stretch [PTR - LEN, PTR). */ + +DECLARE_INLINE_HEADER ( +Charcount +bytecount_to_charcount_down (const Ibyte *ptr, Bytecount len) +) +{ + /* No need to be clever here */ + return bytecount_to_charcount (ptr - len, len); +} + +/* Given a pointer to a text string and a length in characters, return the + equivalent length in bytes of the stretch of characters of that length + BEFORE the pointer. +*/ + +DECLARE_INLINE_HEADER ( +Bytecount +charcount_to_bytecount_down (const Ibyte *ptr, Charcount len) +) +{ +#define SLEDGEHAMMER_CHECK_TEXT +#ifdef SLEDGEHAMMER_CHECK_TEXT + Charcount len1 = len; + Bytecount ret1, ret2; + + /* To test the correctness of the function version, always do the + calculation both ways and check that the values are the same. */ + text_checking_assert (len >= 0); + { + const Ibyte *newptr = ptr; + while (len1 > 0) + { + DEC_IBYTEPTR (newptr); + len1--; + } + ret1 = ptr - newptr; + } + ret2 = charcount_to_bytecount_down_fun (ptr, len); + text_checking_assert (ret1 == ret2); + return ret1; +#else + text_checking_assert (len >= 0); + if (len < 20) /* See above */ + { + const Ibyte *newptr = ptr; + while (len > 0) + { + DEC_IBYTEPTR (newptr); + len--; + } + return ptr - newptr; + } + else + return charcount_to_bytecount_down_fun (ptr, len); +#endif /* SLEDGEHAMMER_CHECK_TEXT */ +} + /* Given a pointer to a text string in the specified format and a length in bytes, return the equivalent length in characters. */ @@ -991,7 +1008,7 @@ /* ---------------------------- */ -/* Working with Ichars */ +/* Working with Ichars */ /* ---------------------------- */ /* NOTE: There are other functions/macros for working with Ichars in @@ -1100,24 +1117,10 @@ do { \ Ibyte **_lta_ = (Ibyte **) &(lval); \ Lisp_Object _lta_2 = (s); \ - *_lta_ = alloca_array (Ibyte, 1 + XSTRING_LENGTH (_lta_2)); \ + *_lta_ = alloca_ibytes (1 + XSTRING_LENGTH (_lta_2)); \ memcpy (*_lta_, XSTRING_DATA (_lta_2), 1 + XSTRING_LENGTH (_lta_2)); \ } while (0) -/* Make an alloca'd copy of a Ibyte * */ -#define IBYTE_STRING_TO_ALLOCA(p, lval) \ -do { \ - Ibyte **_bsta_ = (Ibyte **) &(lval); \ - const Ibyte *_bsta_2 = (p); \ - Bytecount _bsta_3 = qxestrlen (_bsta_2); \ - *_bsta_ = alloca_array (Ibyte, 1 + _bsta_3); \ - memcpy (*_bsta_, _bsta_2, 1 + _bsta_3); \ -} while (0) - - -#define alloca_ibytes(num) alloca_array (Ibyte, num) -#define alloca_extbytes(num) alloca_array (Extbyte, num) - void resize_string (Lisp_Object s, Bytecount pos, Bytecount delta); /* Convert a byte index into a string into a char index. */ @@ -1335,19 +1338,20 @@ variable section: DECLARE_EISTRING (name); - Declare a new Eistring. This is a standard local variable declaration - and can go anywhere in the variable declaration section. NAME itself - is declared as an Eistring *, and its storage declared on the stack. + Declare a new Eistring and initialize it to the empy string. This + is a standard local variable declaration and can go anywhere in the + variable declaration section. NAME itself is declared as an + Eistring *, and its storage declared on the stack. DECLARE_EISTRING_MALLOC (name); - Declare a new Eistring, which uses malloc()ed instead of ALLOCA()ed - data. This is a standard local variable declaration and can go - anywhere in the variable declaration section. Once you initialize - the Eistring, you will have to free it using eifree() to avoid - memory leaks. You will need to use this form if you are passing - an Eistring to any function that modifies it (otherwise, the - modified data may be in stack space and get overwritten when the - function returns). + Declare and initialize a new Eistring, which uses malloc()ed + instead of ALLOCA()ed data. This is a standard local variable + declaration and can go anywhere in the variable declaration + section. Once you initialize the Eistring, you will have to free + it using eifree() to avoid memory leaks. You will need to use this + form if you are passing an Eistring to any function that modifies + it (otherwise, the modified data may be in stack space and get + overwritten when the function returns). or use @@ -1416,12 +1420,12 @@ ... from raw internal-format data in the specified format that is "null-terminated" (the meaning of this depends on the nature of the specific format). - void eicpy_c (Eistring *eistr, const Char_ASCII *c_string); + void eicpy_ascii (Eistring *eistr, const Ascbyte *ascstr); ... from an ASCII null-terminated string. Non-ASCII characters in - the string are *ILLEGAL* (read abort() with error-checking defined). - void eicpy_c_len (Eistring *eistr, const Char_ASCII *c_string, len); + the string are *ILLEGAL* (read ABORT() with error-checking defined). + void eicpy_ascii_len (Eistring *eistr, const Ascbyte *ascstr, len); ... from an ASCII string, with length specified. Non-ASCII characters - in the string are *ILLEGAL* (read abort() with error-checking defined). + in the string are *ILLEGAL* (read ABORT() with error-checking defined). void eicpy_ext (Eistring *eistr, const Extbyte *extdata, Lisp_Object codesys); ... from external null-terminated data, with coding system specified. @@ -1559,9 +1563,9 @@ void eicat_ei (Eistring *eistr, Eistring *eistr2); ... from another Eistring. - void eicat_c (Eistring *eistr, Char_ASCII *c_string); + void eicat_ascii (Eistring *eistr, Ascbyte *ascstr); ... from an ASCII null-terminated string. Non-ASCII characters in - the string are *ILLEGAL* (read abort() with error-checking defined). + the string are *ILLEGAL* (read ABORT() with error-checking defined). void eicat_raw (ei, const Ibyte *data, Bytecount len); ... from raw internal-format data in the default internal format. void eicat_rawz (ei, const Ibyte *data); @@ -1588,10 +1592,10 @@ void eisub_ei (Eistring *eistr, Bytecount off, Charcount charoff, Bytecount len, Charcount charlen, Eistring *eistr2); ... with another Eistring. - void eisub_c (Eistring *eistr, Bytecount off, Charcount charoff, - Bytecount len, Charcount charlen, Char_ASCII *c_string); + void eisub_ascii (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, Ascbyte *ascstr); ... with an ASCII null-terminated string. Non-ASCII characters in - the string are *ILLEGAL* (read abort() with error-checking defined). + the string are *ILLEGAL* (read ABORT() with error-checking defined). void eisub_ch (Eistring *eistr, Bytecount off, Charcount charoff, Bytecount len, Charcount charlen, Ichar ch); ... with an Ichar. @@ -1656,17 +1660,17 @@ Charcount eirstr_ei_off_char (Eistring *eistr, Eistring *eistr2, Bytecount off, Charcount charoff); - Bytecount eistr_c (Eistring *eistr, Char_ASCII *c_string); - Charcount eistr_c_char (Eistring *eistr, Char_ASCII *c_string); - Bytecount eistr_c_off (Eistring *eistr, Char_ASCII *c_string, Bytecount off, + Bytecount eistr_ascii (Eistring *eistr, Ascbyte *ascstr); + Charcount eistr_ascii_char (Eistring *eistr, Ascbyte *ascstr); + Bytecount eistr_ascii_off (Eistring *eistr, Ascbyte *ascstr, Bytecount off, Charcount charoff); - Charcount eistr_c_off_char (Eistring *eistr, Char_ASCII *c_string, + Charcount eistr_ascii_off_char (Eistring *eistr, Ascbyte *ascstr, Bytecount off, Charcount charoff); - Bytecount eirstr_c (Eistring *eistr, Char_ASCII *c_string); - Charcount eirstr_c_char (Eistring *eistr, Char_ASCII *c_string); - Bytecount eirstr_c_off (Eistring *eistr, Char_ASCII *c_string, + Bytecount eirstr_ascii (Eistring *eistr, Ascbyte *ascstr); + Charcount eirstr_ascii_char (Eistring *eistr, Ascbyte *ascstr); + Bytecount eirstr_ascii_off (Eistring *eistr, Ascbyte *ascstr, Bytecount off, Charcount charoff); - Charcount eirstr_c_off_char (Eistring *eistr, Char_ASCII *c_string, + Charcount eirstr_ascii_off_char (Eistring *eistr, Ascbyte *ascstr, Bytecount off, Charcount charoff); @@ -1707,17 +1711,17 @@ Charcount charoff, Bytecount len, Charcount charlen, Eistring *eistr2); - int eicmp_c (Eistring *eistr, Char_ASCII *c_string); - int eicmp_off_c (Eistring *eistr, Bytecount off, Charcount charoff, - Bytecount len, Charcount charlen, Char_ASCII *c_string); - int eicasecmp_c (Eistring *eistr, Char_ASCII *c_string); - int eicasecmp_off_c (Eistring *eistr, Bytecount off, Charcount charoff, + int eicmp_ascii (Eistring *eistr, Ascbyte *ascstr); + int eicmp_off_ascii (Eistring *eistr, Bytecount off, Charcount charoff, + Bytecount len, Charcount charlen, Ascbyte *ascstr); + int eicasecmp_ascii (Eistring *eistr, Ascbyte *ascstr); + int eicasecmp_off_ascii (Eistring *eistr, Bytecount off, Charcount charoff, Bytecount len, Charcount charlen, - Char_ASCII *c_string); - int eicasecmp_i18n_c (Eistring *eistr, Char_ASCII *c_string); - int eicasecmp_i18n_off_c (Eistring *eistr, Bytecount off, Charcount charoff, + Ascbyte *ascstr); + int eicasecmp_i18n_ascii (Eistring *eistr, Ascbyte *ascstr); + int eicasecmp_i18n_off_ascii (Eistring *eistr, Bytecount off, Charcount charoff, Bytecount len, Charcount charlen, - Char_ASCII *c_string); + Ascbyte *ascstr); ********************************************** @@ -1899,7 +1903,7 @@ /* We don't have realloc, so ALLOCA() more space and copy the \ data into it. */ \ Ibyte *ei1oldeidata = (ei)->data_; \ - (ei)->data_ = (Ibyte *) ALLOCA (ei1newsize); \ + (ei)->data_ = alloca_ibytes (ei1newsize); \ if (ei1oldeidata) \ memcpy ((ei)->data_, ei1oldeidata, ei1oldeibytelen + 1); \ } \ @@ -1916,27 +1920,6 @@ memcpy ((ei)->data_, data, (ei)->bytelen_); \ } while (0) -#ifdef ERROR_CHECK_TEXT -#define EI_ASSERT_ASCII(ptr, len) \ -do { \ - int ei5; \ - const Char_ASCII *ei5ptr = (ptr); \ - int ei5len = (len); \ - \ - for (ei5 = 0; ei5 < ei5len; ei5++) \ - assert (ei5ptr[ei5] >= 0x00 && ei5ptr[ei5] < 0x7F); \ -} while (0) -#define EI_ASSERT_ASCIIZ(ptr) \ -do { \ - const Char_ASCII *ei5p1 = (ptr); \ - EI_ASSERT_ASCII (ei5p1, strlen (ei5p1)); \ -} while (0) -#else -#define EI_ASSERT_ASCII(ptr, len) -#define EI_ASSERT_ASCIIZ(ptr) -#endif - - /* ----- Initialization ----- */ #define eicpy_ei(ei, eicpy) \ @@ -1999,20 +1982,20 @@ EI_ALLOC_AND_COPY (ei, ei12p2, ei12p2len, 1); \ } while (0) -#define eicpy_c(ei, c_string) \ +#define eicpy_ascii(ei, ascstr) \ do { \ - const Char_ASCII *ei4 = (c_string); \ + const Ascbyte *ei4 = (ascstr); \ \ - EI_ASSERT_ASCIIZ (ei4); \ + ASSERT_ASCTEXT_ASCII (ei4); \ eicpy_ext (ei, ei4, Qbinary); \ } while (0) -#define eicpy_c_len(ei, c_string, c_len) \ +#define eicpy_ascii_len(ei, ascstr, c_len) \ do { \ - const Char_ASCII *ei6 = (c_string); \ + const Ascbyte *ei6 = (ascstr); \ int ei6len = (c_len); \ \ - EI_ASSERT_ASCII (ei6, ei6len); \ + ASSERT_ASCTEXT_ASCII_LEN (ei6, ei6len); \ eicpy_ext_len (ei, ei6, ei6len, Qbinary); \ } while (0) @@ -2078,7 +2061,7 @@ assert (ei23fmt == FORMAT_DEFAULT); \ \ *ei23lenout = (eistr)->bytelen_; \ - *ei23ptrout = alloca_array (Ibyte, (eistr)->bytelen_ + 1); \ + *ei23ptrout = alloca_ibytes ((eistr)->bytelen_ + 1); \ memcpy (*ei23ptrout, (eistr)->data_, (eistr)->bytelen_ + 1); \ } while (0) @@ -2114,7 +2097,7 @@ \ (ei)->max_size_allocated_ = \ eifind_large_enough_buffer (0, (ei)->bytelen_ + 1); \ - ei13newdata = (Ibyte *) ALLOCA ((ei)->max_size_allocated_); \ + ei13newdata = alloca_ibytes ((ei)->max_size_allocated_); \ memcpy (ei13newdata, (ei)->data_, (ei)->bytelen_ + 1); \ xfree ((ei)->data_, Ibyte *); \ (ei)->data_ = ei13newdata; \ @@ -2122,7 +2105,7 @@ \ if ((ei)->extdata_) \ { \ - Extbyte *ei13newdata = (Extbyte *) ALLOCA ((ei)->extlen_ + 2); \ + Extbyte *ei13newdata = alloca_extbytes ((ei)->extlen_ + 2); \ \ memcpy (ei13newdata, (ei)->extdata_, (ei)->extlen_); \ /* Double null-terminate in case of Unicode data */ \ @@ -2224,12 +2207,12 @@ eicat_1 (ei, ei9->data_, ei9->bytelen_, ei9->charlen_); \ } while (0) -#define eicat_c(ei, c_string) \ +#define eicat_ascii(ei, ascstr) \ do { \ - const Char_ASCII *ei15 = (c_string); \ + const Ascbyte *ei15 = (ascstr); \ int ei15len = strlen (ei15); \ \ - EI_ASSERT_ASCII (ei15, ei15len); \ + ASSERT_ASCTEXT_ASCII_LEN (ei15, ei15len); \ eicat_1 (ei, ei15, ei15len, \ bytecount_to_charcount ((Ibyte *) ei15, ei15len)); \ } while (0) @@ -2303,11 +2286,11 @@ ei19->charlen_); \ } while (0) -#define eisub_c(ei, off, charoff, len, charlen, c_string) \ +#define eisub_ascii(ei, off, charoff, len, charlen, ascstr) \ do { \ - const Char_ASCII *ei20 = (c_string); \ + const Ascbyte *ei20 = (ascstr); \ int ei20len = strlen (ei20); \ - EI_ASSERT_ASCII (ei20, ei20len); \ + ASSERT_ASCTEXT_ASCII_LEN (ei20, ei20len); \ eisub_1 (ei, off, charoff, len, charlen, ei20, ei20len, -1); \ } while (0) @@ -2386,21 +2369,21 @@ #define eirstr_ei_off_char(eistr, eistr2, off, charoff) \ NOT YET IMPLEMENTED -#define eistr_c(eistr, c_string) \ +#define eistr_ascii(eistr, ascstr) \ NOT YET IMPLEMENTED -#define eistr_c_char(eistr, c_string) \ +#define eistr_ascii_char(eistr, ascstr) \ NOT YET IMPLEMENTED -#define eistr_c_off(eistr, c_string, off, charoff) \ +#define eistr_ascii_off(eistr, ascstr, off, charoff) \ NOT YET IMPLEMENTED -#define eistr_c_off_char(eistr, c_string, off, charoff) \ +#define eistr_ascii_off_char(eistr, ascstr, off, charoff) \ NOT YET IMPLEMENTED -#define eirstr_c(eistr, c_string) \ +#define eirstr_ascii(eistr, ascstr) \ NOT YET IMPLEMENTED -#define eirstr_c_char(eistr, c_string) \ +#define eirstr_ascii_char(eistr, ascstr) \ NOT YET IMPLEMENTED -#define eirstr_c_off(eistr, c_string, off, charoff) \ +#define eirstr_ascii_off(eistr, ascstr, off, charoff) \ NOT YET IMPLEMENTED -#define eirstr_c_off_char(eistr, c_string, off, charoff) \ +#define eirstr_ascii_off_char(eistr, ascstr, off, charoff) \ NOT YET IMPLEMENTED @@ -2408,7 +2391,7 @@ int eicmp_1 (Eistring *ei, Bytecount off, Charcount charoff, Bytecount len, Charcount charlen, const Ibyte *data, - const Eistring *ei2, int is_c, int fold_case); + const Eistring *ei2, int is_ascii, int fold_case); #define eicmp_ei(eistr, eistr2) \ eicmp_1 (eistr, 0, -1, -1, -1, 0, eistr2, 0, 0) @@ -2423,18 +2406,18 @@ #define eicasecmp_i18n_off_ei(eistr, off, charoff, len, charlen, eistr2) \ eicmp_1 (eistr, off, charoff, len, charlen, 0, eistr2, 0, 2) -#define eicmp_c(eistr, c_string) \ - eicmp_1 (eistr, 0, -1, -1, -1, c_string, 0, 1, 0) -#define eicmp_off_c(eistr, off, charoff, len, charlen, c_string) \ - eicmp_1 (eistr, off, charoff, len, charlen, c_string, 0, 1, 0) -#define eicasecmp_c(eistr, c_string) \ - eicmp_1 (eistr, 0, -1, -1, -1, c_string, 0, 1, 1) -#define eicasecmp_off_c(eistr, off, charoff, len, charlen, c_string) \ - eicmp_1 (eistr, off, charoff, len, charlen, c_string, 0, 1, 1) -#define eicasecmp_i18n_c(eistr, c_string) \ - eicmp_1 (eistr, 0, -1, -1, -1, c_string, 0, 1, 2) -#define eicasecmp_i18n_off_c(eistr, off, charoff, len, charlen, c_string) \ - eicmp_1 (eistr, off, charoff, len, charlen, c_string, 0, 1, 2) +#define eicmp_ascii(eistr, ascstr) \ + eicmp_1 (eistr, 0, -1, -1, -1, (const Ibyte *) ascstr, 0, 1, 0) +#define eicmp_off_ascii(eistr, off, charoff, len, charlen, ascstr) \ + eicmp_1 (eistr, off, charoff, len, charlen, (const Ibyte *) ascstr, 0, 1, 0) +#define eicasecmp_ascii(eistr, ascstr) \ + eicmp_1 (eistr, 0, -1, -1, -1, (const Ibyte *) ascstr, 0, 1, 1) +#define eicasecmp_off_ascii(eistr, off, charoff, len, charlen, ascstr) \ + eicmp_1 (eistr, off, charoff, len, charlen, (const Ibyte *) ascstr, 0, 1, 1) +#define eicasecmp_i18n_ascii(eistr, ascstr) \ + eicmp_1 (eistr, 0, -1, -1, -1, (const Ibyte *) ascstr, 0, 1, 2) +#define eicasecmp_i18n_off_ascii(eistr, off, charoff, len, charlen, ascstr) \ + eicmp_1 (eistr, off, charoff, len, charlen, (const Ibyte *) ascstr, 0, 1, 2) /* ----- Case-changing the Eistring ----- */ @@ -2446,7 +2429,7 @@ do { \ int ei11new_allocmax = (ei)->charlen_ * MAX_ICHAR_LEN + 1; \ Ibyte *ei11storage = \ - (Ibyte *) alloca_array (Ibyte, ei11new_allocmax); \ + (Ibyte *) alloca_ibytes (ei11new_allocmax); \ int ei11newlen = eistr_casefiddle_1 ((ei)->data_, (ei)->bytelen_, \ ei11storage, downp); \ \ @@ -2525,9 +2508,27 @@ Typical use is - TO_EXTERNAL_FORMAT (DATA, (ptr, len), - LISP_BUFFER, buffer, - Qfile_name); + TO_EXTERNAL_FORMAT (LISP_STRING, str, C_STRING_MALLOC, ptr, Qfile_name); + + which means that the contents of the lisp string `str' are written + to a malloc'ed memory area which will be pointed to by `ptr', after the + function returns. The conversion will be done using the `file-name' + coding system (which will be controlled by the user indirectly by + setting or binding the variable `file-name-coding-system'). + + Some sources and sinks require two C variables to specify. We use + some preprocessor magic to allow different source and sink types, and + even different numbers of arguments to specify different types of + sources and sinks. + + So we can have a call that looks like + + TO_INTERNAL_FORMAT (DATA, (ptr, len), + MALLOC, (ptr, len), + coding_system); + + The parenthesized argument pairs are required to make the + preprocessor magic work. NOTE: GC is inhibited during the entire operation of these macros. This is because frequently the data to be converted comes from strings but @@ -2552,6 +2553,12 @@ When specifying the sink, use lvalues, since the macro will assign to them, except when the sink is an lstream or a lisp buffer. + For the sink types `ALLOCA' and `C_STRING_ALLOCA', the resulting text is + stored in a stack-allocated buffer, which is automatically freed on + returning from the function. However, the sink types `MALLOC' and + `C_STRING_MALLOC' return `xmalloc()'ed memory. The caller is responsible + for freeing this memory using `xfree()'. + The macros accept the kinds of sources and sinks appropriate for internal and external data representation. See the type_checking_assert macros below for the actual allowed types. @@ -2607,7 +2614,45 @@ behavior may change in the future, and you cannot rely on this -- the most you can rely on is that sink data in Unicode format will have two terminating nulls, which combine to form one Unicode null - character. */ + character. + + NOTE: You might ask, why are these not written as functions that + *RETURN* the converted string, since that would allow them to be used + much more conveniently, without having to constantly declare temporary + variables? The answer is that in fact I originally did write the + routines that way, but that required either + + (a) calling alloca() inside of a function call, or + (b) using expressions separated by commas and a global temporary variable, or + (c) using the GCC extension ({ ... }). + + Turned out that all of the above had bugs, all caused by GCC (hence the + comments about "those GCC wankers" and "ream gcc up the ass"). As for + (a), some versions of GCC (especially on Intel platforms), which had + buggy implementations of alloca() that couldn't handle being called + inside of a function call -- they just decremented the stack right in the + middle of pushing args. Oops, crash with stack trashing, very bad. (b) + was an attempt to fix (a), and that led to further GCC crashes, esp. when + you had two such calls in a single subexpression, because GCC couldn't be + counted upon to follow even a minimally reasonable order of execution. + True, you can't count on one argument being evaluated before another, but + GCC would actually interleave them so that the temp var got stomped on by + one while the other was accessing it. So I tried (c), which was + problematic because that GCC extension has more bugs in it than a + termite's nest. + + So reluctantly I converted to the current way. Now, that was awhile ago + (c. 1994), and it appears that the bug involving alloca in function calls + has long since been fixed. More recently, I defined the new-dfc routines + down below, which DO allow exactly such convenience of returning your + args rather than store them in temp variables, and I also wrote a + configure check to see whether alloca() causes crashes inside of function + calls, and if so use the portable alloca() implementation in alloca.c. + If you define TEST_NEW_DFC, the old routines get written in terms of the + new ones, and I've had a beta put out with this on and it appeared to + this appears to cause no problems -- so we should consider + switching, and feel no compunctions about writing further such function- + like alloca() routines in lieu of statement-like ones. --ben */ #define TO_EXTERNAL_FORMAT(source_type, source, sink_type, sink, codesys) \ do { \ @@ -2802,24 +2847,24 @@ #define DFC_ALLOCA_USE_CONVERTED_DATA(sink) do { \ void * dfc_sink_ret = ALLOCA (dfc_sink.data.len + 2); \ memcpy (dfc_sink_ret, dfc_sink.data.ptr, dfc_sink.data.len + 2); \ - ((dfc_aliasing_voidpp) &(DFC_CPP_CAR sink))->p = dfc_sink_ret; \ + VOIDP_CAST (DFC_CPP_CAR sink) = dfc_sink_ret; \ (DFC_CPP_CDR sink) = dfc_sink.data.len; \ } while (0) #define DFC_MALLOC_USE_CONVERTED_DATA(sink) do { \ void * dfc_sink_ret = xmalloc (dfc_sink.data.len + 2); \ memcpy (dfc_sink_ret, dfc_sink.data.ptr, dfc_sink.data.len + 2); \ - ((dfc_aliasing_voidpp) &(DFC_CPP_CAR sink))->p = dfc_sink_ret; \ + VOIDP_CAST (DFC_CPP_CAR sink) = dfc_sink_ret; \ (DFC_CPP_CDR sink) = dfc_sink.data.len; \ } while (0) #define DFC_C_STRING_ALLOCA_USE_CONVERTED_DATA(sink) do { \ void * dfc_sink_ret = ALLOCA (dfc_sink.data.len + 2); \ memcpy (dfc_sink_ret, dfc_sink.data.ptr, dfc_sink.data.len + 2); \ - ((dfc_aliasing_voidpp) &(sink))->p = dfc_sink_ret; \ + VOIDP_CAST (sink) = dfc_sink_ret; \ } while (0) #define DFC_C_STRING_MALLOC_USE_CONVERTED_DATA(sink) do { \ void * dfc_sink_ret = xmalloc (dfc_sink.data.len + 2); \ memcpy (dfc_sink_ret, dfc_sink.data.ptr, dfc_sink.data.len + 2); \ - ((dfc_aliasing_voidpp) &(sink))->p = dfc_sink_ret; \ + VOIDP_CAST (sink) = dfc_sink_ret; \ } while (0) #define DFC_LISP_STRING_USE_CONVERTED_DATA(sink) \ sink = make_string ((Ibyte *) dfc_sink.data.ptr, dfc_sink.data.len) @@ -2879,21 +2924,46 @@ #define C_STRING_TO_EXTERNAL_MALLOC(in, out, codesys) \ do { * (Extbyte **) &(out) = \ NEW_C_STRING_TO_EXTERNAL_MALLOC (in, codesys); } while (0) +#define SIZED_C_STRING_TO_EXTERNAL_MALLOC(in, inlen, out, codesys) \ + do { * (Extbyte **) &(out) = \ + NEW_SIZED_C_STRING_TO_EXTERNAL_MALLOC (in, inlen, codesys); } \ + while (0) #define EXTERNAL_TO_C_STRING_MALLOC(in, out, codesys) \ do { * (Ibyte **) &(out) = \ NEW_EXTERNAL_TO_C_STRING_MALLOC (in, codesys); } while (0) +#define SIZED_EXTERNAL_TO_C_STRING_MALLOC(in, inlen, out, codesys) \ + do { * (Ibyte **) &(out) = \ + NEW_SIZED_EXTERNAL_TO_C_STRING_MALLOC (in, inlen, codesys); } \ + while (0) #define LISP_STRING_TO_EXTERNAL_MALLOC(in, out, codesys) \ do { * (Extbyte **) &(out) = \ NEW_LISP_STRING_TO_EXTERNAL_MALLOC (in, codesys); } while (0) #else #define C_STRING_TO_EXTERNAL_MALLOC(in, out, codesys) \ TO_EXTERNAL_FORMAT (C_STRING, in, C_STRING_MALLOC, out, codesys) +#define SIZED_C_STRING_TO_EXTERNAL_MALLOC(in, inlen, out, codesys) \ + TO_EXTERNAL_FORMAT (DATA, (in, inlen), C_STRING_MALLOC, out, codesys) #define EXTERNAL_TO_C_STRING_MALLOC(in, out, codesys) \ TO_INTERNAL_FORMAT (C_STRING, in, C_STRING_MALLOC, out, codesys) +#define SIZED_EXTERNAL_TO_C_STRING_MALLOC(in, inlen, out, codesys) \ + TO_INTERNAL_FORMAT (DATA, (in, inlen), C_STRING_MALLOC, out, codesys) #define LISP_STRING_TO_EXTERNAL_MALLOC(in, out, codesys) \ TO_EXTERNAL_FORMAT (LISP_STRING, in, C_STRING_MALLOC, out, codesys) #endif /* TEST_NEW_DFC */ +#define C_STRING_TO_SIZED_EXTERNAL_MALLOC(in, out, outlen, codesys) \ + TO_EXTERNAL_FORMAT (C_STRING, in, MALLOC, (out, outlen), codesys) +#define SIZED_C_STRING_TO_SIZED_EXTERNAL_MALLOC(in, inlen, out, outlen, \ + codesys) \ + TO_EXTERNAL_FORMAT (DATA, (in, inlen), MALLOC, (out, outlen), codesys) +#define EXTERNAL_TO_SIZED_C_STRING_MALLOC(in, out, outlen, codesys) \ + TO_INTERNAL_FORMAT (C_STRING, in, MALLOC, (out, outlen), codesys) +#define SIZED_EXTERNAL_TO_SIZED_C_STRING_MALLOC(in, inlen, out, outlen, \ + codesys) \ + TO_INTERNAL_FORMAT (DATA, (in, inlen), MALLOC, (out, outlen), codesys) +#define LISP_STRING_TO_SIZED_EXTERNAL_MALLOC(in, out, outlen, codesys) \ + TO_EXTERNAL_FORMAT (LISP_STRING, in, MALLOC, (out, outlen), codesys) + enum new_dfc_src_type { DFC_EXTERNAL, @@ -2906,11 +2976,13 @@ MODULE_API void *new_dfc_convert_malloc (const void *src, Bytecount src_size, enum new_dfc_src_type type, Lisp_Object codesys); -MODULE_API void *new_dfc_convert_alloca (const char *srctext, void *alloca_data); -MODULE_API Bytecount new_dfc_convert_size (const char *srctext, const void *src, +MODULE_API Bytecount new_dfc_convert_size (const char *srctext, + const void *src, Bytecount src_size, enum new_dfc_src_type type, Lisp_Object codesys); +MODULE_API void *new_dfc_convert_copy_data (const char *srctext, + void *alloca_data); END_C_DECLS @@ -2928,11 +3000,11 @@ to choke when alloca() occurs as a funcall argument, and so we check this in configure. Rewriting the expressions below to use a temporary variable, so that the call to alloca() is outside of - new_dfc_convert_alloca(), won't help because the entire NEW_DFC call + new_dfc_convert_copy_data(), won't help because the entire NEW_DFC call could be inside of a function call. */ #define NEW_DFC_CONVERT_1_ALLOCA(src, src_size, type, codesys) \ - new_dfc_convert_alloca \ + new_dfc_convert_copy_data \ (#src, ALLOCA_FUNCALL_OK (new_dfc_convert_size (#src, src, src_size, \ type, codesys))) @@ -2959,15 +3031,76 @@ (Extbyte *) new_dfc_convert_malloc (LISP_TO_VOID (src), -1, \ DFC_LISP_STRING, codesys) -/* Standins for various encodings, until we know them better */ +/* Standins for various encodings. */ +#ifdef WEXTTEXT_IS_WIDE +#define Qcommand_argument_encoding Qmswindows_unicode +#define Qenvironment_variable_encoding Qmswindows_unicode +#else #define Qcommand_argument_encoding Qnative #define Qenvironment_variable_encoding Qnative +#endif #define Qunix_host_name_encoding Qnative #define Qunix_service_name_encoding Qnative #define Qmswindows_host_name_encoding Qmswindows_multibyte #define Qmswindows_service_name_encoding Qmswindows_multibyte -/* Standins for various X encodings, until we know them better. +/* Wexttext functions. The type of Wexttext is selected at compile time + and will sometimes be wchar_t, sometimes char. */ + +int wcscmp_ascii (const wchar_t *s1, const Ascbyte *s2); +int wcsncmp_ascii (const wchar_t *s1, const Ascbyte *s2, Charcount len); + +#ifdef WEXTTEXT_IS_WIDE /* defined under MS Windows i.e. WIN32_NATIVE */ +#define WEXTTEXT_ZTERM_SIZE sizeof (wchar_t) +/* Extra indirection needed in case of manifest constant as arg */ +#define WEXTSTRING_1(arg) L##arg +#define WEXTSTRING(arg) WEXTSTRING_1(arg) +#define wext_strlen wcslen +#define wext_strcmp wcscmp +#define wext_strncmp wcsncmp +#define wext_strcmp_ascii wcscmp_ascii +#define wext_strncmp_ascii wcsncmp_ascii +#define wext_strcpy wcscpy +#define wext_strncpy wcsncpy +#define wext_strchr wcschr +#define wext_strrchr wcsrchr +#define wext_strdup wcsdup +#define wext_atol(str) wcstol (str, 0, 10) +#define wext_sprintf wsprintfW /* Huh? both wsprintfA and wsprintfW? */ +#define wext_getenv _wgetenv +#define build_wext_string(str, cs) build_ext_string ((Extbyte *) str, cs) +#define WEXTTEXT_TO_8_BIT(arg) WEXTTEXT_TO_MULTIBYTE(arg) +#ifdef WIN32_NATIVE +int XCDECL wext_retry_open (const Wexttext *path, int oflag, ...); +#else +#error Cannot handle Wexttext yet on this system +#endif +#define wext_access _waccess +#define wext_stat _wstat +#else +#define WEXTTEXT_ZTERM_SIZE sizeof (char) +#define WEXTSTRING(arg) arg +#define wext_strlen strlen +#define wext_strcmp strcmp +#define wext_strncmp strncmp +#define wext_strcmp_ascii strcmp +#define wext_strncmp_ascii strncmp +#define wext_strcpy strcpy +#define wext_strncpy strncpy +#define wext_strchr strchr +#define wext_strrchr strrchr +#define wext_strdup xstrdup +#define wext_atol(str) atol (str) +#define wext_sprintf sprintf +#define wext_getenv getenv +#define build_wext_string build_ext_string +#define wext_retry_open retry_open +#define wext_access access +#define wext_stat stat +#define WEXTTEXT_TO_8_BIT(arg) ((Extbyte *) arg) +#endif + +/* Standins for various X encodings. About encodings in X: @@ -3042,6 +3175,11 @@ #define Qx_display_name_encoding Qx_hpc_encoding #define Qx_xpm_data_encoding Qx_hpc_encoding +/* !!#### Verify these! */ +#define Qxt_widget_arg_encoding Qnative +#define Qdt_dnd_encoding Qnative +#define Qoffix_dnd_encoding Qnative + /* RedHat 6.2 contains a locale called "Francais" with the C-cedilla encoded in ISO2022! */ #define Qlocale_name_encoding Qctext diff --text -u 'xemacs-21.5.18/src/toolbar-common.c' 'xemacs-21.5.19/src/toolbar-common.c' Index: ./src/toolbar-common.c --- ./src/toolbar-common.c Thu Aug 12 23:51:35 2004 +++ ./src/toolbar-common.c Tue Jan 25 08:34:12 2005 @@ -63,9 +63,9 @@ #define __INTERNAL_APPROPRIATENESS_CHECK(f) assert(FRAME_X_P (f)) #define __INTERNAL_FLUSH(d) XFlush (DEVICE_X_DISPLAY (d)) #else -#define __INTERNAL_MAPPED_P(f) abort() -#define __INTERNAL_APPROPRIATENESS_CHECK(f) abort() -#define __INTERNAL_FLUSH(f) abort() +#define __INTERNAL_MAPPED_P(f) ABORT() +#define __INTERNAL_APPROPRIATENESS_CHECK(f) ABORT() +#define __INTERNAL_FLUSH(f) ABORT() #endif #include "toolbar-common.h" @@ -445,7 +445,7 @@ (frame)->right_toolbar_was_visible = flag; \ break; \ default: \ - abort (); \ + ABORT (); \ } \ } while (0) diff --text -u 'xemacs-21.5.18/src/toolbar-msw.c' 'xemacs-21.5.19/src/toolbar-msw.c' Index: ./src/toolbar-msw.c --- ./src/toolbar-msw.c Tue Sep 21 04:20:03 2004 +++ ./src/toolbar-msw.c Tue Jan 25 08:34:12 2005 @@ -78,7 +78,7 @@ (frame)->right_toolbar_was_visible = flag; \ break; \ default: \ - abort (); \ + ABORT (); \ } \ } while (0) diff --text -u 'xemacs-21.5.18/src/toolbar.c' 'xemacs-21.5.19/src/toolbar.c' Index: ./src/toolbar.c --- ./src/toolbar.c Tue Sep 21 04:20:03 2004 +++ ./src/toolbar.c Tue Jan 25 08:34:12 2005 @@ -1,7 +1,7 @@ /* Generic toolbar implementation. Copyright (C) 1995 Board of Trustees, University of Illinois. Copyright (C) 1995 Sun Microsystems, Inc. - Copyright (C) 1995, 1996, 2003 Ben Wing. + Copyright (C) 1995, 1996, 2003, 2004 Ben Wing. Copyright (C) 1996 Chuck Thompson. This file is part of XEmacs. @@ -778,8 +778,11 @@ if (frame_size_changed) { int width, height; - pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), - &width, &height); + if (!window_system_pixelated_geometry (wrap_frame (f))) + pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), + &width, &height); + else + width = FRAME_PIXWIDTH (f), height = FRAME_PIXHEIGHT (f); if (!HAS_FRAMEMETH_P (f, set_frame_size)) change_frame_size (f, height, width, 0); else @@ -930,7 +933,7 @@ *vert = 1; break; default: - abort (); + ABORT (); } } diff --text -u 'xemacs-21.5.18/src/ui-byhand.c' 'xemacs-21.5.19/src/ui-byhand.c' Index: ./src/ui-byhand.c --- ./src/ui-byhand.c Tue Sep 21 04:20:04 2004 +++ ./src/ui-byhand.c Fri Nov 5 08:06:56 2004 @@ -348,7 +348,7 @@ wtaerror ("Object is not a GtkCurve", curve); } - vector = (gfloat *) ALLOCA (sizeof (gfloat) * XINT (length)); + vector = alloca_array (gfloat, XINT (length)); gtk_curve_get_vector (GTK_CURVE (XGTK_OBJECT (curve)->object), XINT (length), vector); lisp_vector = make_vector (XINT (length), Qnil); @@ -380,7 +380,7 @@ wtaerror ("Object is not a GtkCurve", curve); } - c_vector = (gfloat *) ALLOCA (sizeof (gfloat) * vec_length); + c_vector = alloca_array (gfloat, vec_length); for (i = 0; i < vec_length; i++) { diff --text -u 'xemacs-21.5.18/src/ui-gtk.c' 'xemacs-21.5.19/src/ui-gtk.c' Index: ./src/ui-gtk.c --- ./src/ui-gtk.c Tue Sep 21 04:20:04 2004 +++ ./src/ui-gtk.c Wed Jan 26 19:22:25 2005 @@ -107,18 +107,6 @@ static struct hash_table *internal_type_hash; static int -type_hash_equal(const void *arg1, const void *arg2) -{ - return ((GtkType) arg1 == (GtkType) arg2); -} - -static unsigned long -type_hash_hash(const void *arg) -{ - return ((unsigned long) arg); -} - -static int type_already_imported_p (GtkType t) { void *retval = NULL; @@ -148,7 +136,7 @@ if (!internal_type_hash) { - internal_type_hash = make_general_hash_table (163, type_hash_hash, type_hash_equal); + internal_type_hash = make_hash_table (163); return (0); } @@ -609,18 +597,17 @@ if (!NILP (args)) { - Lisp_Object tail = Qnil; Lisp_Object value = args; Lisp_Object type = Qnil; - EXTERNAL_LIST_LOOP (tail, value) + EXTERNAL_LIST_LOOP_2 (elt, value) { GtkType the_type; Lisp_Object marshaller_type = Qnil; - CHECK_SYMBOL (XCAR (tail)); + CHECK_SYMBOL (elt); - type = Fsymbol_name (XCAR (tail)); + type = Fsymbol_name (elt); the_type = gtk_type_from_name ((char *) XSTRING_DATA (type)); @@ -728,24 +715,25 @@ if (!NILP (args)) { - Lisp_Object tail = Qnil; Lisp_Object value = args; CHECK_LIST (args); n_args = 0; /* First we convert all of the arguments from Lisp to GtkArgs */ - EXTERNAL_LIST_LOOP (tail, value) - { - the_args[n_args].type = XFFI (func)->args[n_args]; + { + EXTERNAL_LIST_LOOP_2 (elt, value) + { + the_args[n_args].type = XFFI (func)->args[n_args]; - if (lisp_to_gtk_type (XCAR (tail), &the_args[n_args])) - { - /* There was some sort of an error */ - gui_error ("Error converting arguments", args); - } - n_args++; - } + if (lisp_to_gtk_type (elt, &the_args[n_args])) + { + /* There was some sort of an error */ + gui_error ("Error converting arguments", args); + } + n_args++; + } + } } /* Now we need to tack on space for a return value, if they have @@ -1128,11 +1116,11 @@ (data1->object_type == data2->object_type)); } -static unsigned long +static Hashcode emacs_gtk_boxed_hash (Lisp_Object obj, int UNUSED (depth)) { emacs_gtk_boxed_data *data = XGTK_BOXED(obj); - return (HASH2 ((unsigned long)data->object, data->object_type)); + return (HASH2 ((Hashcode) data->object, data->object_type)); } DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("GtkBoxed", emacs_gtk_boxed, @@ -1180,7 +1168,7 @@ emacs_gtk_boxed_data *data = NULL; if (GTK_FUNDAMENTAL_TYPE (t) != GTK_TYPE_BOXED) - abort(); + ABORT(); data = allocate_emacs_gtk_boxed_data (); data->object = obj; @@ -1446,13 +1434,13 @@ /* structured types */ case GTK_TYPE_SIGNAL: case GTK_TYPE_ARGS: /* This we can do as a list of values */ - abort(); + ABORT(); case GTK_TYPE_CALLBACK: stderr_out ("callback fn: ...\n"); break; case GTK_TYPE_C_CALLBACK: case GTK_TYPE_FOREIGN: - abort(); + ABORT(); /* base type of the object system */ case GTK_TYPE_OBJECT: @@ -1463,7 +1451,7 @@ break; default: - abort(); + ABORT(); } } #endif @@ -1544,7 +1532,7 @@ } } stderr_out ("Do not know how to convert `%s' to lisp!\n", gtk_type_name (arg->type)); - abort (); + ABORT (); } /* This is chuck reminding GCC to... SHUT UP! */ return (Qnil); @@ -1597,7 +1585,7 @@ break; case GTK_TYPE_LONG: case GTK_TYPE_ULONG: - abort(); + ABORT(); case GTK_TYPE_FLOAT: CHECK_INT_OR_FLOAT (obj); GTK_VALUE_FLOAT(*arg) = extract_float (obj); @@ -1816,7 +1804,7 @@ else { stderr_out ("Do not know how to convert `%s' from lisp!\n", gtk_type_name (arg->type)); - abort(); + ABORT(); } break; } @@ -1877,7 +1865,7 @@ break; case GTK_TYPE_LONG: case GTK_TYPE_ULONG: - abort(); + ABORT(); case GTK_TYPE_FLOAT: CHECK_INT_OR_FLOAT (obj); *(GTK_RETLOC_FLOAT(*arg)) = extract_float (obj); @@ -2096,7 +2084,7 @@ else { stderr_out ("Do not know how to convert `%s' from lisp!\n", gtk_type_name (arg->type)); - abort(); + ABORT(); } break; } @@ -2171,7 +2159,7 @@ } else { - /* abort ()? */ + /* ABORT ()? */ } return (val); } diff --text -u 'xemacs-21.5.18/src/undo.c' 'xemacs-21.5.19/src/undo.c' Index: ./src/undo.c --- ./src/undo.c Wed Sep 22 11:06:52 2004 +++ ./src/undo.c Fri Nov 5 08:06:57 2004 @@ -545,8 +545,6 @@ void vars_of_undo (void) { - reinit_vars_of_undo (); - pending_boundary = Qnil; staticpro (&pending_boundary); last_undo_buffer = Qnil; diff --text -u 'xemacs-21.5.18/src/unexcw.c' 'xemacs-21.5.19/src/unexcw.c' Index: ./src/unexcw.c --- ./src/unexcw.c Tue Sep 21 04:20:05 2004 +++ ./src/unexcw.c Mon Dec 6 12:52:22 2004 @@ -102,7 +102,7 @@ { /* ugly nt hack - should be in lisp */ int a_new, a_out = -1; - char new_name[PATH_MAX], a_name[PATH_MAX]; + char new_name[PATH_MAX_EXTERNAL], a_name[PATH_MAX_EXTERNAL]; char *ptr; /* Make sure that the input and output filenames have the diff --text -u 'xemacs-21.5.18/src/unexnext.c' 'xemacs-21.5.19/src/unexnext.c' Index: ./src/unexnext.c --- ./src/unexnext.c Wed Mar 13 17:53:02 2002 +++ ./src/unexnext.c Mon Dec 6 12:52:23 2004 @@ -279,7 +279,7 @@ void unexec(char *outfile,char *infile) { - char tmpfile[PATH_MAX]; + char tmpfile[PATH_MAX_EXTERNAL]; int infd,outfd; if ((infd=open(infile, O_RDONLY, 0))<0) diff --text -u 'xemacs-21.5.18/src/unexnt.c' 'xemacs-21.5.19/src/unexnt.c' Index: ./src/unexnt.c --- ./src/unexnt.c Tue Sep 21 04:20:06 2004 +++ ./src/unexnt.c Tue Jan 25 08:34:13 2005 @@ -133,11 +133,11 @@ won't work.) */ if (heap_state == HEAP_UNLOADED) { - Extbyte executable_path[MAX_PATH * MAX_XETCHAR_SIZE]; + Extbyte executable_path[PATH_MAX_EXTERNAL]; /* Don't use mswindows_get_module_file_name() because it uses xmalloc() */ - if (qxeGetModuleFileName (NULL, executable_path, MAX_PATH) == 0) + if (qxeGetModuleFileName (NULL, executable_path, _MAX_PATH) == 0) { exit (1); } @@ -150,8 +150,8 @@ /* To allow profiling, make sure executable_path names the .exe file, not the file created by the profiler */ - p = xetcsrchr (executable_path, '\\'); - xetcscpy (p + 1, XETEXT (PATH_PROGNAME ".exe")); + p = qxetcsrchr (executable_path, '\\'); + qxetcscpy (p + 1, XETEXT (PATH_PROGNAME ".exe")); } #endif @@ -194,13 +194,13 @@ ".exe" extension...patch them up if they don't. */ qxestrcpy (in_filename, old_name); ptr = in_filename + qxestrlen (in_filename) - 4; - if (qxestrcmp_c (ptr, ".exe")) - qxestrcat_c (in_filename, ".exe"); + if (qxestrcmp_ascii (ptr, ".exe")) + qxestrcat_ascii (in_filename, ".exe"); qxestrcpy (out_filename, new_name); ptr = out_filename + qxestrlen (out_filename) - 4; - if (qxestrcmp_c (ptr, ".exe")) - qxestrcat_c (out_filename, ".exe"); + if (qxestrcmp_ascii (ptr, ".exe")) + qxestrcat_ascii (out_filename, ".exe"); stdout_out ("Dumping from %s\n", in_filename); stdout_out (" to %s\n", out_filename); @@ -222,7 +222,7 @@ /* The size of the dumped executable is the size of the original executable plus the size of the heap and the size of the .bss section. */ heap_index_in_executable = (unsigned long) - round_to_next ((UChar_Binary *) in_file.size, get_allocation_unit ()); + round_to_next ((Rawbyte *) in_file.size, get_allocation_unit ()); size = heap_index_in_executable + get_committed_heap_size () + bss_size; if (!open_output_file (&out_file, out_filename, size)) { @@ -249,7 +249,7 @@ pfnCheckSumMappedFile_t pfnCheckSumMappedFile; dos_header = (PIMAGE_DOS_HEADER) out_file.file_base; - nt_header = (PIMAGE_NT_HEADERS) ((UChar_Binary *) dos_header + + nt_header = (PIMAGE_NT_HEADERS) ((Rawbyte *) dos_header + dos_header->e_lfanew); nt_header->OptionalHeader.CheckSum = 0; @@ -333,7 +333,7 @@ PIMAGE_DOS_HEADER dos_header; PIMAGE_NT_HEADERS nt_header; PIMAGE_SECTION_HEADER section, data_section; - UChar_Binary *ptr; + Rawbyte *ptr; int i; dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base; @@ -363,26 +363,26 @@ for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) { #ifndef DUMP_SEPARATE_SECTION - if (!qxestrcmp_c (section->Name, ".bss")) + if (!qxestrcmp_ascii (section->Name, ".bss")) { extern int my_ebss; /* From lastfile.c */ - ptr = (UChar_Binary *) nt_header->OptionalHeader.ImageBase + + ptr = (Rawbyte *) nt_header->OptionalHeader.ImageBase + section->VirtualAddress; bss_start = ptr; - bss_size = (UChar_Binary*) &my_ebss - (UChar_Binary*) bss_start; + bss_size = (Rawbyte*) &my_ebss - (Rawbyte*) bss_start; } - if (!qxestrcmp_c (section->Name, ".data")) + if (!qxestrcmp_ascii (section->Name, ".data")) #else - if (!qxestrcmp_c (section->Name, "xdata")) + if (!qxestrcmp_ascii (section->Name, "xdata")) #endif { - extern Char_Binary my_edata[]; /* From lastfile.c */ + extern Rawbyte my_edata[]; /* From lastfile.c */ /* The .data section. */ data_section = section; - ptr = (UChar_Binary *) nt_header->OptionalHeader.ImageBase + + ptr = (Rawbyte *) nt_header->OptionalHeader.ImageBase + section->VirtualAddress; data_start_va = ptr; data_start_file = section->PointerToRawData; @@ -422,7 +422,7 @@ get_bss_info_from_map_file (p_infile, &ptr, &bss_size); bss_start = ptr + nt_header->OptionalHeader.ImageBase + data_section->VirtualAddress; - bss_size = (UChar_Binary *) &my_ebss - (UChar_Binary *) bss_start; + bss_size = (Rawbyte *) &my_ebss - (Rawbyte *) bss_start; } #else bss_size = 0; @@ -443,11 +443,11 @@ copy_executable_and_dump_data_section (file_data *p_infile, file_data *p_outfile) { - UChar_Binary *data_file, *data_va; + Rawbyte *data_file, *data_va; unsigned long size, index; /* Get a pointer to where the raw data should go in the executable file. */ - data_file = (UChar_Binary *) p_outfile->file_base + data_start_file; + data_file = (Rawbyte *) p_outfile->file_base + data_start_file; /* Get a pointer to the raw data in our address space. */ data_va = data_start_va; @@ -463,8 +463,8 @@ DUMP_MSG (("Dumping data section...\n")); DUMP_MSG (("\t0x%08x Address in process.\n", data_va)); DUMP_MSG (("\t0x%08x Offset in output file.\n", - (UChar_Binary *) data_file - - (UChar_Binary *) p_outfile->file_base)); + (Rawbyte *) data_file - + (Rawbyte *) p_outfile->file_base)); DUMP_MSG (("\t0x%08x Size in bytes.\n", size)); memcpy (data_file, data_va, size); @@ -474,14 +474,14 @@ DUMP_MSG (("\t0x%08x Offset in input file.\n", index)); DUMP_MSG (("\t0x%08x Offset in output file.\n", index)); DUMP_MSG (("\t0x%08x Size in bytes.\n", size)); - memcpy ((UChar_Binary *) p_outfile->file_base + index, - (UChar_Binary *) p_infile->file_base + index, size); + memcpy ((Rawbyte *) p_outfile->file_base + index, + (Rawbyte *) p_infile->file_base + index, size); } static void dump_bss_and_heap (file_data *UNUSED (p_infile), file_data *p_outfile) { - UChar_Binary *heap_data; + Rawbyte *heap_data; unsigned long size, index; DUMP_MSG (("Dumping heap onto end of executable...\n")); @@ -505,7 +505,7 @@ DUMP_MSG (("\t0x%08x BSS start in process.\n", bss_start)); DUMP_MSG (("\t0x%08x BSS offset in executable.\n", index)); DUMP_MSG (("\t0x%08x BSS size in bytes.\n", size)); - memcpy ((UChar_Binary *) p_outfile->file_base + index, bss_start, size); + memcpy ((Rawbyte *) p_outfile->file_base + index, bss_start, size); #endif } @@ -526,17 +526,17 @@ file = qxeCreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (file == INVALID_HANDLE_VALUE) - abort (); + ABORT (); /* Seek to where the .bss section is tucked away after the heap... */ index = heap_index_in_executable + get_committed_heap_size (); if (SetFilePointer (file, index, NULL, FILE_BEGIN) == 0xFFFFFFFF) - abort (); + ABORT (); /* Ok, read in the saved .bss section and initialize all uninitialized variables. */ if (!ReadFile (file, bss_start, bss_size, &n_read, NULL)) - abort (); + ABORT (); CloseHandle (file); #endif @@ -554,13 +554,13 @@ file = qxeCreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (file == INVALID_HANDLE_VALUE) - abort (); + ABORT (); size = GetFileSize (file, &upper_size); file_mapping = qxeCreateFileMapping (file, NULL, PAGE_WRITECOPY, 0, size, NULL); if (!file_mapping) - abort (); + ABORT (); size = get_committed_heap_size (); file_base = MapViewOfFileEx (file_mapping, FILE_MAP_COPY, 0, @@ -578,17 +578,17 @@ if (VirtualAlloc (get_heap_start (), get_committed_heap_size (), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) == NULL) - abort (); + ABORT (); /* Seek to the location of the heap data in the executable. */ if (SetFilePointer (file, heap_index_in_executable, NULL, FILE_BEGIN) == 0xFFFFFFFF) - abort (); + ABORT (); /* Read in the data. */ if (!ReadFile (file, get_heap_start (), get_committed_heap_size (), &n_read, NULL)) - abort (); + ABORT (); CloseHandle (file); } diff --text -u 'xemacs-21.5.18/src/unicode.c' 'xemacs-21.5.19/src/unicode.c' Index: ./src/unicode.c --- ./src/unicode.c Fri Oct 15 02:26:25 2004 +++ ./src/unicode.c Fri Feb 4 01:14:08 2005 @@ -1,5 +1,5 @@ /* Code to handle Unicode conversion. - Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Ben Wing. This file is part of XEmacs. @@ -43,6 +43,126 @@ #include "sysfile.h" +/* For more info about how Unicode works under Windows, see intl-win32.c. */ + +/* Info about Unicode translation tables [ben]: + + FORMAT: + ------- + + We currently use the following format for tables: + + If dimension == 1, to_unicode_table is a 96-element array of ints + (Unicode code points); else, it's a 96-element array of int * pointers, + each of which points to a 96-element array of ints. If no elements in a + row have been filled in, the pointer will point to a default empty + table; that way, memory usage is more reasonable but lookup still fast. + + -- If from_unicode_levels == 1, from_unicode_table is a 256-element + array of shorts (octet 1 in high byte, octet 2 in low byte; we don't + store Ichars directly to save space). + + -- If from_unicode_levels == 2, from_unicode_table is a 256-element + array of short * pointers, each of which points to a 256-element array + of shorts. + + -- If from_unicode_levels == 3, from_unicode_table is a 256-element + array of short ** pointers, each of which points to a 256-element array + of short * pointers, each of which points to a 256-element array of + shorts. + + -- If from_unicode_levels == 4, same thing but one level deeper. + + Just as for to_unicode_table, we use default tables to fill in all + entries with no values in them. + + #### An obvious space-saving optimization is to use variable-sized + tables, where each table instead of just being a 256-element array, is a + structure with a start value, an end value, and a variable number of + entries (END - START + 1). Only 8 bits are needed for END and START, + and could be stored at the end to avoid alignment problems. However, + before charging off and implementing this, we need to consider whether + it's worth it: + + (1) Most tables will be highly localized in which code points are + defined, heavily reducing the possible memory waste. Before doing any + rewriting, write some code to see how much memory is actually being + wasted (i.e. ratio of empty entries to total # of entries) and only + start rewriting if it's unacceptably high. You have to check over all + charsets. + + (2) Since entries are usually added one at a time, you have to be very + careful when creating the tables to avoid realloc()/free() thrashing in + the common case when you are in an area of high localization and are + going to end up using most entries in the table. You'd certainly want + to allow only certain sizes, not arbitrary ones (probably powers of 2, + where you want the entire block including the START/END values to fit + into a power of 2, minus any malloc overhead if there is any -- there's + none under gmalloc.c, and probably most system malloc() functions are + quite smart nowadays and also have no overhead). You could optimize + somewhat during the in-C initializations, because you can compute the + actual usage of various tables by scanning the entries you're going to + add in a separate pass before adding them. (You could actually do the + same thing when entries are added on the Lisp level by making the + assumption that all the entries will come in one after another before + any use is made of the data. So as they're coming in, you just store + them in a big long list, and the first time you need to retrieve an + entry, you compute the whole table at once.) You'd still have to deal + with the possibility of later entries coming in, though. + + (3) You do lose some speed using START/END values, since you need a + couple of comparisons at each level. This could easily make each single + lookup become 3-4 times slower. The Unicode book considers this a big + issue, and recommends against variable-sized tables for this reason; + however, they almost certainly have in mind applications that primarily + involve conversion of large amounts of data. Most Unicode strings that + are translated in XEmacs are fairly small. The only place where this + might matter is in loading large files -- e.g. a 3-megabyte + Unicode-encoded file. So think about this, and maybe do a trial + implementation where you don't worry too much about the intricacies of + (2) and just implement some basic "multiply by 1.5" trick or something + to do the resizing. There is a very good FAQ on Unicode called + something like the Linux-Unicode How-To (it should be part of the Linux + How-To's, I think), that lists the url of a guy with a whole bunch of + unicode files you can use to stress-test your implementations, and he's + highly likely to have a good multi-megabyte Unicode-encoded file (with + normal text in it -- if you created your own just by creating repeated + strings of letters and numbers, you probably wouldn't get accurate + results). + + INITIALIZATION: + --------------- + + There are advantages and disadvantages to loading the tables at + run-time. + + Advantages: + + They're big, and it's very fast to recreate them (a fraction of a second + on modern processors). + + Disadvantages: + + (1) User-defined charsets: It would be inconvenient to require all + dumped user-defined charsets to be reloaded at init time. + + (2) Starting up in a non-ISO-8859-1 directory. If we load at run-time, + we don't load the tables until after we've parsed the current + directories, and we run into a real bootstrapping problem, if the + directories themselves are non-ISO-8859-1. This is potentially fixable + once we switch to using Unicode internally, so we don't have to do any + conversion (other than the automatic kind, e.g. UTF-16 to UTF-8). + + NB With run-time loading, we load in init-mule-at-startup, in + mule-cmds.el. This is called from startup.el, which is quite late in + the initialization process -- but data-directory isn't set until then. + With dump-time loading, you still can't dump in a Japanese directory + (again, until we move to Unicode internally), but this is not such an + imposition. + + +*/ + /* #### WARNING! The current sledgehammer routines have a fundamental problem in that they can't handle two characters mapping to a single Unicode codepoint or vice-versa in a single charset table. @@ -56,97 +176,12 @@ (1-to-1). Any character set that does not behave that way is broken according to the Unicode standard. - Answer: You will get an abort(), since the purpose of the sledgehammer + Answer: You will get an ABORT(), since the purpose of the sledgehammer routines is self-checking. The above problem with non-1-to-1 mapping occurs in the Big5 tables, as provided by the Unicode Consortium. */ /* #define SLEDGEHAMMER_CHECK_UNICODE */ - /* We currently use the following format for tables: - - If dimension == 1, to_unicode_table is a 96-element array of ints - (Unicode code points); else, it's a 96-element array of int * - pointers, each of which points to a 96-element array of ints. If no - elements in a row have been filled in, the pointer will point to a - default empty table; that way, memory usage is more reasonable but - lookup still fast. - - -- If from_unicode_levels == 1, from_unicode_table is a 256-element - array of shorts (octet 1 in high byte, octet 2 in low byte; we don't - store Ichars directly to save space). - - -- If from_unicode_levels == 2, from_unicode_table is a - 256-element array of short * pointers, each of which points to a - 256-element array of shorts. - - -- If from_unicode_levels == 3, from_unicode_table is a - 256-element array of short ** pointers, each of which points to - a 256-element array of short * pointers, each of which points to - a 256-element array of shorts. - - -- If from_unicode_levels == 4, same thing but one level deeper. - - Just as for to_unicode_table, we use default tables to fill in - all entries with no values in them. - - #### An obvious space-saving optimization is to use variable-sized - tables, where each table instead of just being a 256-element array, - is a structure with a start value, an end value, and a variable - number of entries (END - START + 1). Only 8 bits are needed for - END and START, and could be stored at the end to avoid alignment - problems. However, before charging off and implementing this, - we need to consider whether it's worth it: - - (1) Most tables will be highly localized in which code points are - defined, heavily reducing the possible memory waste. Before - doing any rewriting, write some code to see how much memory is - actually being wasted (i.e. ratio of empty entries to total # of - entries) and only start rewriting if it's unacceptably high. You - have to check over all charsets. - - (2) Since entries are usually added one at a time, you have to be - very careful when creating the tables to avoid realloc()/free() - thrashing in the common case when you are in an area of high - localization and are going to end up using most entries in the - table. You'd certainly want to allow only certain sizes, not - arbitrary ones (probably powers of 2, where you want the entire - block including the START/END values to fit into a power of 2, - minus any malloc overhead if there is any -- there's none under - gmalloc.c, and probably most system malloc() functions are quite - smart nowadays and also have no overhead). You could optimize - somewhat during the in-C initializations, because you can compute - the actual usage of various tables by scanning the entries you're - going to add in a separate pass before adding them. (You could - actually do the same thing when entries are added on the Lisp - level by making the assumption that all the entries will come in - one after another before any use is made of the data. So as - they're coming in, you just store them in a big long list, and - the first time you need to retrieve an entry, you compute the - whole table at once.) You'd still have to deal with the - possibility of later entries coming in, though. - - (3) You do lose some speed using START/END values, since you need - a couple of comparisons at each level. This could easily make - each single lookup become 3-4 times slower. The Unicode book - considers this a big issue, and recommends against variable-sized - tables for this reason; however, they almost certainly have in - mind applications that primarily involve conversion of large - amounts of data. Most Unicode strings that are translated in - XEmacs are fairly small. The only place where this might matter - is in loading large files -- e.g. a 3-megabyte Unicode-encoded - file. So think about this, and maybe do a trial implementation - where you don't worry too much about the intricacies of (2) and - just implement some basic "multiply by 1.5" trick or something to - do the resizing. There is a very good FAQ on Unicode called - something like the Linux-Unicode How-To (it should be part of the - Linux How-To's, I think), that lists the url of a guy with a - whole bunch of unicode files you can use to stress-test your - implementations, and he's highly likely to have a good - multi-megabyte Unicode-encoded file (with normal text in it -- if - you created your own just by creating repeated strings of letters - and numbers, you probably wouldn't get accurate results). - */ - /* When MULE is not defined, we may still need some Unicode support -- in particular, some Windows API's always want Unicode, and the way we've set up the Unicode encapsulation, we may as well go ahead and @@ -189,7 +224,7 @@ }; static const struct memory_description to_unicode_level_1_desc_1[] = { - { XD_STRUCT_PTR, 0, 96, &to_unicode_level_0_desc }, + { XD_BLOCK_PTR, 0, 96, { &to_unicode_level_0_desc } }, { XD_END } }; @@ -198,8 +233,8 @@ }; static const struct memory_description to_unicode_description_1[] = { - { XD_STRUCT_PTR, 1, 96, &to_unicode_level_0_desc }, - { XD_STRUCT_PTR, 2, 96, &to_unicode_level_1_desc }, + { XD_BLOCK_PTR, 1, 96, { &to_unicode_level_0_desc } }, + { XD_BLOCK_PTR, 2, 96, { &to_unicode_level_1_desc } }, { XD_END } }; @@ -209,6 +244,12 @@ sizeof (void *), to_unicode_description_1 }; +/* Used only for to_unicode_blank_2 */ +static const struct memory_description to_unicode_level_2_desc_1[] = { + { XD_BLOCK_PTR, 0, 96, { &to_unicode_level_1_desc } }, + { XD_END } +}; + static const struct memory_description from_unicode_level_0_desc_1[] = { { XD_END } }; @@ -218,7 +259,7 @@ }; static const struct memory_description from_unicode_level_1_desc_1[] = { - { XD_STRUCT_PTR, 0, 256, &from_unicode_level_0_desc }, + { XD_BLOCK_PTR, 0, 256, { &from_unicode_level_0_desc } }, { XD_END } }; @@ -227,7 +268,7 @@ }; static const struct memory_description from_unicode_level_2_desc_1[] = { - { XD_STRUCT_PTR, 0, 256, &from_unicode_level_1_desc }, + { XD_BLOCK_PTR, 0, 256, { &from_unicode_level_1_desc } }, { XD_END } }; @@ -236,7 +277,7 @@ }; static const struct memory_description from_unicode_level_3_desc_1[] = { - { XD_STRUCT_PTR, 0, 256, &from_unicode_level_2_desc }, + { XD_BLOCK_PTR, 0, 256, { &from_unicode_level_2_desc } }, { XD_END } }; @@ -245,10 +286,10 @@ }; static const struct memory_description from_unicode_description_1[] = { - { XD_STRUCT_PTR, 1, 256, &from_unicode_level_0_desc }, - { XD_STRUCT_PTR, 2, 256, &from_unicode_level_1_desc }, - { XD_STRUCT_PTR, 3, 256, &from_unicode_level_2_desc }, - { XD_STRUCT_PTR, 4, 256, &from_unicode_level_3_desc }, + { XD_BLOCK_PTR, 1, 256, { &from_unicode_level_0_desc } }, + { XD_BLOCK_PTR, 2, 256, { &from_unicode_level_1_desc } }, + { XD_BLOCK_PTR, 3, 256, { &from_unicode_level_2_desc } }, + { XD_BLOCK_PTR, 4, 256, { &from_unicode_level_3_desc } }, { XD_END } }; @@ -258,6 +299,12 @@ sizeof (void *), from_unicode_description_1 }; +/* Used only for from_unicode_blank_4 */ +static const struct memory_description from_unicode_level_4_desc_1[] = { + { XD_BLOCK_PTR, 0, 256, { &from_unicode_level_3_desc } }, + { XD_END } +}; + static Lisp_Object_dynarr *unicode_precedence_dynarr; static const struct memory_description lod_description_1[] = { @@ -359,7 +406,7 @@ return newtab; } default: - abort (); + ABORT (); return 0; } } @@ -383,7 +430,8 @@ } { - XCHARSET_FROM_UNICODE_TABLE (charset) = create_new_from_unicode_table (1); + XCHARSET_FROM_UNICODE_TABLE (charset) = + create_new_from_unicode_table (1); XCHARSET_FROM_UNICODE_LEVELS (charset) = 1; } } @@ -654,7 +702,7 @@ break; } default: - abort (); + ABORT (); } } @@ -701,7 +749,7 @@ case 2: val = ((short **) frtab)[u2][u1]; break; case 3: val = ((short ***) frtab)[u3][u2][u1]; break; case 4: val = ((short ****) frtab)[u4][u3][u2][u1]; break; - default: abort (); + default: ABORT (); } ch = make_ichar (charset, val >> 8, val & 0xFF); @@ -724,7 +772,7 @@ case 1: assert_not_any_blank_table (frtab); break; - default: abort (); + default: ABORT (); } } } @@ -748,7 +796,7 @@ break; } default: - abort (); + ABORT (); } } @@ -869,7 +917,7 @@ case 4: ((short ****) table)[0] = (short ***) old_table; break; - default: abort (); + default: ABORT (); } } } @@ -905,7 +953,7 @@ ((short *) create_new_from_unicode_table (1)); table = ((short **) table)[u2]; break; - default: abort (); + default: ABORT (); } } } @@ -920,7 +968,7 @@ case 2: ((short **) table)[u2][u1] = (c1 << 8) + c2; break; case 3: ((short ***) table)[u3][u2][u1] = (c1 << 8) + c2; break; case 4: ((short ****) table)[u4][u3][u2][u1] = (c1 << 8) + c2; break; - default: abort (); + default: ABORT (); } } } @@ -983,7 +1031,7 @@ case 2: retval = ((short **) table)[u2][u1]; break; case 3: retval = ((short ***) table)[u3][u2][u1]; break; case 4: retval = ((short ****) table)[u4][u3][u2][u1]; break; - default: abort (); retval = 0; + default: ABORT (); retval = 0; } if (retval != -1) @@ -1391,7 +1439,16 @@ if ((!ignore_first_column ? sscanf (p, "%i %i%n", &cp1, &cp2, &endcount) < 2 : sscanf (p, "%i %i %i%n", &dummy, &cp1, &cp2, &endcount) < 3) - || *(p + endcount + strspn (p + endcount, " \t\n\r\f"))) + /* #### Temporary code! Cygwin newlib fucked up scanf() handling + of numbers beginning 0x0... starting in 04/2004, in an attempt + to fix another bug. A partial fix for this was put in in + 06/2004, but as of 10/2004 the value of ENDCOUNT returned in + such case is still wrong. If this gets fixed soon, remove + this code. --ben */ +#ifndef CYGWIN_SCANF_BUG + || *(p + endcount + strspn (p + endcount, " \t\n\r\f")) +#endif + ) { warn_when_safe (Qunicode, Qwarning, "Unrecognized line in translation file %s:\n%s", @@ -1439,7 +1496,7 @@ break; case CHARSET_TYPE_96X96: l1 = 32; h1 = 127; l2 = 32; h2 = 127; break; - default: abort (); l1 = 0; h1 = 0; l2 = 0; h2 = 0; + default: ABORT (); l1 = 0; h1 = 0; l2 = 0; h2 = 0; } if (cp1high < l2 || cp1high > h2 || cp1low < l1 || cp1low > h1) @@ -1631,9 +1688,9 @@ } break; - case UNICODE_UTF_7: abort (); + case UNICODE_UTF_7: ABORT (); - default: abort (); + default: ABORT (); } } @@ -1772,10 +1829,10 @@ break; case UNICODE_UTF_7: - abort (); + ABORT (); break; - default: abort (); + default: ABORT (); } } @@ -1902,7 +1959,7 @@ } break; default: - abort (); + ABORT (); } } } @@ -2287,7 +2344,7 @@ case UNICODE_UTF_8: return Qutf_8; case UNICODE_UTF_7: return Qutf_7; case UNICODE_UCS_4: return Qucs_4; - default: abort (); + default: ABORT (); } } else if (EQ (prop, Qlittle_endian)) @@ -2405,18 +2462,8 @@ } void -reinit_vars_of_unicode (void) -{ -#ifdef MULE - init_blank_unicode_tables (); -#endif /* MULE */ -} - -void vars_of_unicode (void) { - reinit_vars_of_unicode (); - Fprovide (intern ("unicode")); #ifdef MULE @@ -2427,7 +2474,30 @@ Vdefault_unicode_precedence_list = Qnil; unicode_precedence_dynarr = Dynarr_new (Lisp_Object); - dump_add_root_struct_ptr (&unicode_precedence_dynarr, + dump_add_root_block_ptr (&unicode_precedence_dynarr, &lisp_object_dynarr_description); + + init_blank_unicode_tables (); + + /* Note that the "block" we are describing is a single pointer, and hence + we could potentially use dump_add_root_block_ptr(). However, given + the way the descriptions are written, we couldn't use them, and would + have to write new descriptions for each of the pointers below, since + we would have to make use of a description with an XD_BLOCK_ARRAY + in it. */ + + dump_add_root_block (&to_unicode_blank_1, sizeof (void *), + to_unicode_level_1_desc_1); + dump_add_root_block (&to_unicode_blank_2, sizeof (void *), + to_unicode_level_2_desc_1); + + dump_add_root_block (&from_unicode_blank_1, sizeof (void *), + from_unicode_level_1_desc_1); + dump_add_root_block (&from_unicode_blank_2, sizeof (void *), + from_unicode_level_2_desc_1); + dump_add_root_block (&from_unicode_blank_3, sizeof (void *), + from_unicode_level_3_desc_1); + dump_add_root_block (&from_unicode_blank_4, sizeof (void *), + from_unicode_level_4_desc_1); #endif /* MULE */ } diff --text -u 'xemacs-21.5.18/src/win32.c' 'xemacs-21.5.19/src/win32.c' Index: ./src/win32.c --- ./src/win32.c Tue Sep 21 04:20:07 2004 +++ ./src/win32.c Fri Jan 28 11:36:28 2005 @@ -1,5 +1,5 @@ /* Utility routines for XEmacs on Windows 9x, NT and Cygwin. - Copyright (C) 2000, 2001, 2002 Ben Wing. + Copyright (C) 2000, 2001, 2002, 2004 Ben Wing. This file is part of XEmacs. @@ -23,17 +23,35 @@ #include "buffer.h" #include "console-msw.h" +#include "hash.h" +#include "profile.h" #include "sysfile.h" #include "sysproc.h" #include "syssignal.h" #include "systime.h" + + +/* + +Info on Windows issues: + + (Info-goto-node "(internals)Interface to MS Windows") + + ------- @file{src/config.h}.in vs. @file{nt/xemacs.mak} ------- + + See @file{src/config.h.in} more more info. +*/ + /* Control conversion of upper case file names to lower case. nil means no, t means yes. */ Lisp_Object Vmswindows_downcase_file_names; +struct hash_table *mswindows_read_link_hash; + int mswindows_windows9x_p; +Boolint mswindows_shortcuts_are_symlinks; pfSwitchToThread_t xSwitchToThread; @@ -54,7 +72,7 @@ WIN32_TO_LOCAL_FILE_FORMAT (filename, filename); pseudo_url = xnew_array (Ibyte, 5 + qxestrlen (filename) + 1); - qxestrcpy_c (pseudo_url, "file:"); + qxestrcpy_ascii (pseudo_url, "file:"); qxestrcat (pseudo_url, filename); /* URL's only have /, no backslash */ for (filename = pseudo_url; *filename; filename++) @@ -224,7 +242,7 @@ #else case 0: lang = 0; break; #endif - default: abort (); + default: ABORT (); } retval = qxeFormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER @@ -256,7 +274,7 @@ TSTR_TO_C_STRING (lpMsgBuf, inres); len = qxestrlen (inres); /* Messages tend to end with a period and newline */ - if (len >= 3 && !qxestrcmp_c (inres + len - 3, ".\r\n")) + if (len >= 3 && !qxestrcmp_ascii (inres + len - 3, ".\r\n")) len -= 3; result = make_string (inres, len); @@ -328,6 +346,7 @@ if (STRINGP (operation)) LISP_STRING_TO_TSTR (operation, opext); + /* #### What about path names, which may be links? */ if (STRINGP (parameters)) LISP_STRING_TO_TSTR (parameters, parmext); if (STRINGP (current_dir)) @@ -390,6 +409,228 @@ } #endif +struct read_link_hash +{ + Ibyte *resolved; + DWORD ticks; +}; + +static Ibyte * +mswindows_read_link_1 (const Ibyte *fname) +{ +#ifdef NO_CYGWIN_COM_SUPPORT + return NULL; +#else + Ibyte *retval = NULL; + Extbyte *fnameext; + HANDLE fh; + struct read_link_hash *rlh; + DWORD ticks; + + /* The call below to resolve a link is rather time-consuming. + I tried implementing a simple cache based on creation and write time + of the file, but that didn't help enough -- maybe 30% faster but still + a lot of time spent here. So just do something cheesy and don't + check again if we've recently (< a second) done so. */ + + if (!mswindows_read_link_hash) + mswindows_read_link_hash = make_string_hash_table (1000); + C_STRING_TO_TSTR (fname, fnameext); + + /* See if we can find a cached value. */ + + /* The intermediate cast fools gcc into not outputting strict-aliasing + complaints */ + ticks = GetTickCount (); + if (!gethash (fname, mswindows_read_link_hash, + (const void **) (void *) &rlh)) + { + rlh = xnew_and_zero (struct read_link_hash); + puthash (qxestrdup (fname), rlh, mswindows_read_link_hash); + } + else if (ticks - rlh->ticks < 1000) + { + return rlh->resolved ? qxestrdup (rlh->resolved) : NULL; + } + + rlh->ticks = ticks; + + /* Retrieve creation/write time of link file. */ + + /* No access rights required to get info. */ + if ((fh = qxeCreateFile (fnameext, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) + == INVALID_HANDLE_VALUE) + { + CloseHandle (fh); + return NULL; + } + + CloseHandle (fh); + + /* #### + + Note the following in the docs: + + Note: The IShellLink interface has an ANSI version + (IShellLinkA) and a Unicode version (IShellLinkW). The + version that will be used depends on whether you compile + for ANSI or Unicode. However, Microsoft® Windows 95 and + Microsoft® Windows 98 only support IShellLinkA. + + We haven't yet implemented COM support in the + Unicode-splitting library. I don't quite understand how + COM works yet, but it looks like what's happening is + that the ShellLink class implements both the IShellLinkA + and IShellLinkW interfaces. To make this work at + run-time, we have to do something like this: + + -- define a new interface qxeIShellLink that uses + Extbyte * instead of LPSTR or LPWSTR. (not totally + necessary since Extbyte * == LPSTR). + + -- define a new class qxeShellLink that implements + qxeIShellLink. the methods on this class need to create + a shadow ShellLink object to do all the real work, and + call the corresponding function from either the + IShellLinkA or IShellLinkW interfaces on this object, + depending on whether XEUNICODE_P is defined. + + -- with appropriate preprocessor magic, of course, we + could make things appear transparent; but we've decided + not to do preprocessor magic for the moment. + */ + + /* #### Not Unicode-split for the moment; we have to do it + ourselves. */ + if (XEUNICODE_P) + { + IShellLinkW *psl; + + if (CoCreateInstance ( + XECOMID (CLSID_ShellLink), + NULL, + CLSCTX_INPROC_SERVER, + XECOMID (IID_IShellLinkW), + &VOIDP_CAST (psl)) == S_OK) + { + IPersistFile *ppf; + + if (XECOMCALL2 (psl, QueryInterface, + XECOMID (IID_IPersistFile), + &VOIDP_CAST (ppf)) == S_OK) + { + Extbyte *fname_unicode; + WIN32_FIND_DATAW wfd; + LPWSTR resolved = alloca_array (WCHAR, PATH_MAX_EXTERNAL + 1); + + /* Always Unicode. Not obvious from the + IPersistFile documentation, but look under + "Shell Link" for example code. */ + fname_unicode = fnameext; + + if (XECOMCALL2 (ppf, Load, + (LPWSTR) fname_unicode, + STGM_READ) == S_OK && + /* #### YUCK! Docs read + + cchMaxPath + + Maximum number of bytes to copy to the buffer pointed + to by the pszFile parameter. + + But "cch" means "count of characters", not bytes. + I'll assume the doc writers messed up and the + programmer was correct. Also, this approach is safe + even if it's actually the other way around. */ +#if defined (CYGWIN_HEADERS) && W32API_INSTALLED_VER < W32API_VER(2,2) + /* Another Cygwin prototype error, + fixed in v2.2 of w32api */ + XECOMCALL4 (psl, GetPath, (LPSTR) resolved, + PATH_MAX_EXTERNAL, &wfd, 0) +#else + XECOMCALL4 (psl, GetPath, resolved, + PATH_MAX_EXTERNAL, &wfd, 0) +#endif + == S_OK) + TSTR_TO_C_STRING_MALLOC (resolved, retval); + + XECOMCALL0 (ppf, Release); + } + + XECOMCALL0 (psl, Release); + } + } + else + { + IShellLinkA *psl; + + if (CoCreateInstance ( + XECOMID (CLSID_ShellLink), + NULL, + CLSCTX_INPROC_SERVER, + XECOMID (IID_IShellLinkA), + &VOIDP_CAST (psl)) == S_OK) + { + IPersistFile *ppf; + + if (XECOMCALL2 (psl, QueryInterface, + XECOMID (IID_IPersistFile), + &VOIDP_CAST (ppf)) == S_OK) + { + Extbyte *fname_unicode; + WIN32_FIND_DATAA wfd; + LPSTR resolved = alloca_array (CHAR, PATH_MAX_EXTERNAL + 1); + + /* Always Unicode. Not obvious from the + IPersistFile documentation, but look under + "Shell Link" for example code. */ + C_STRING_TO_EXTERNAL (fname, fname_unicode, + Qmswindows_unicode); + + if (XECOMCALL2 (ppf, Load, + (LPWSTR) fname_unicode, + STGM_READ) == S_OK + && XECOMCALL4 (psl, GetPath, resolved, + PATH_MAX_EXTERNAL, &wfd, 0) == S_OK) + TSTR_TO_C_STRING_MALLOC (resolved, retval); + + XECOMCALL0 (ppf, Release); + } + + XECOMCALL0 (psl, Release); + } + } + + /* Cache newly found value */ + if (rlh->resolved) + xfree (rlh->resolved, Ibyte *); + rlh->resolved = retval ? qxestrdup (retval) : NULL; + + return retval; +#endif /* NO_CYGWIN_COM_SUPPORT */ +} + +/* Resolve a file that may be a shortcut. Accepts either a file ending + with .LNK or without the ending. If a shortcut is found, returns + a value that you must xfree(); otherwise NULL. */ + +Ibyte * +mswindows_read_link (const Ibyte *fname) +{ + int len = qxestrlen (fname); + if (len > 4 && !qxestrcasecmp_ascii (fname + len - 4, ".LNK")) + return mswindows_read_link_1 (fname); + else + { + DECLARE_EISTRING (name2); + + eicpy_rawz (name2, fname); + eicat_ascii (name2, ".LNK"); + return mswindows_read_link_1 (eidata (name2)); + } +} + + #if defined (WIN32_NATIVE) || defined (CYGWIN_BROKEN_SIGNALS) /* setitimer() does not exist on native MS Windows, and appears broken @@ -401,7 +642,6 @@ mechanism for SIGCHLD. Yuck.) */ - /*--------------------------------------------------------------------*/ /* Signal support */ /*--------------------------------------------------------------------*/ @@ -651,11 +891,20 @@ void vars_of_win32 (void) { - DEFVAR_LISP ("mswindows-downcase-file-names", &Vmswindows_downcase_file_names /* + DEFVAR_LISP ("mswindows-downcase-file-names", + &Vmswindows_downcase_file_names /* Non-nil means convert all-upper case file names to lower case. This applies when performing completions and file name expansion. */ ); Vmswindows_downcase_file_names = Qnil; + + DEFVAR_BOOL ("mswindows-shortcuts-are-symlinks", + &mswindows_shortcuts_are_symlinks /* +Non-nil means shortcuts (.LNK files) are treated as symbolic links. +This works also for symlinks created under Cygwin, because they use .LNK +files to implement symbolic links. +*/ ); + mswindows_shortcuts_are_symlinks = 1; } void @@ -665,7 +914,7 @@ } void -init_win32_very_early (void) +init_win32_very_very_early (void) { mswindows_windows9x_p = GetVersion () & 0x80000000; } diff --text -u 'xemacs-21.5.18/src/window.c' 'xemacs-21.5.19/src/window.c' Index: ./src/window.c --- ./src/window.c Tue Sep 21 12:28:15 2004 +++ ./src/window.c Fri Feb 4 01:14:08 2005 @@ -170,8 +170,8 @@ }; static const struct memory_description face_cachel_description_1[] = { - { XD_STRUCT_PTR, offsetof (face_cachel, merged_faces), - 1, &int_dynarr_description }, + { XD_BLOCK_PTR, offsetof (face_cachel, merged_faces), + 1, { &int_dynarr_description } }, { XD_LISP_OBJECT, offsetof (face_cachel, face) }, { XD_LISP_OBJECT, offsetof (face_cachel, foreground) }, { XD_LISP_OBJECT, offsetof (face_cachel, background) }, @@ -241,12 +241,12 @@ { XD_LISP_OBJECT_ARRAY, offsetof (struct window, slot), size }, #include "winslots.h" - { XD_STRUCT_PTR, offsetof (struct window, face_cachels), - 1, &face_cachel_dynarr_description }, - { XD_STRUCT_PTR, offsetof (struct window, glyph_cachels), - 1, &glyph_cachel_dynarr_description }, - { XD_STRUCT_PTR, offsetof (struct window, line_start_cache), - 1, &line_start_cache_dynarr_description }, + { XD_BLOCK_PTR, offsetof (struct window, face_cachels), + 1, { &face_cachel_dynarr_description } }, + { XD_BLOCK_PTR, offsetof (struct window, glyph_cachels), + 1, { &glyph_cachel_dynarr_description } }, + { XD_BLOCK_PTR, offsetof (struct window, line_start_cache), + 1, { &line_start_cache_dynarr_description } }, { XD_END } }; @@ -422,10 +422,10 @@ { XD_LISP_OBJECT, offsetof (struct window_mirror, hchild) }, { XD_LISP_OBJECT, offsetof (struct window_mirror, vchild) }, - { XD_STRUCT_PTR, offsetof (struct window_mirror, current_display_lines), - 1, &display_line_dynarr_description }, - { XD_STRUCT_PTR, offsetof (struct window_mirror, desired_display_lines), - 1, &display_line_dynarr_description }, + { XD_BLOCK_PTR, offsetof (struct window_mirror, current_display_lines), + 1, { &display_line_dynarr_description } }, + { XD_BLOCK_PTR, offsetof (struct window_mirror, desired_display_lines), + 1, { &display_line_dynarr_description } }, { XD_LISP_OBJECT, offsetof (struct window_mirror, buffer) }, @@ -643,7 +643,7 @@ real_window_internal (mir->frame->root_window, XWINDOW_MIRROR (mir->frame->root_mirror), mir); if (NILP (retval) && !no_abort) - abort (); + ABORT (); return retval; } @@ -706,7 +706,7 @@ update_frame_window_mirror (XFRAME (w->frame)); t = find_window_mirror (w); if (!t) - abort (); + ABORT (); if (which == CURRENT_DISP) return t->current_display_lines; @@ -716,7 +716,7 @@ /* The CMOTION_DISP display lines are global. */ return cmotion_display_lines; else - abort (); + ABORT (); return 0; /* shut up compiler */ } @@ -730,7 +730,7 @@ update_frame_window_mirror (XFRAME (w->frame)); t = find_window_mirror (w); if (!t) - abort (); + ABORT (); return t->buffer; } @@ -744,7 +744,7 @@ update_frame_window_mirror (XFRAME (w->frame)); t = find_window_mirror (w); if (!t) - abort (); + ABORT (); t->buffer = b; } @@ -1963,7 +1963,7 @@ struct buffer *b = XBUFFER (buf); if (b != XMARKER (w->pointm[CURRENT_DISP])->buffer) - abort (); + ABORT (); /* FSF disables this check, so I'll do it too. I hope it won't break things. --ben */ @@ -2833,14 +2833,14 @@ I feel no shame about putting this piece of shit in. */ if (++lose_lose >= 500) { - /* Call to abort() added by Darryl Okahata (16 Nov. 2001), + /* Call to ABORT() added by Darryl Okahata (16 Nov. 2001), at Ben's request, to catch any remaining bugs. If you find that XEmacs is aborting here, and you need to be up and running ASAP, it should be safe to - comment out the following abort(), as long as you + comment out the following ABORT(), as long as you leave the "break;" alone. */ - abort(); + ABORT(); break; /* <--- KEEP THIS HERE! Do not delete! */ } @@ -2984,7 +2984,7 @@ } default: - abort (); + ABORT (); } if (EQ (w, last_window)) @@ -3076,7 +3076,7 @@ w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices); /* At this point we damn well better have found something. */ - if (NILP (w)) abort (); + if (NILP (w)) ABORT (); #endif return w; @@ -5488,8 +5488,6 @@ void vars_of_window (void) { - reinit_vars_of_window (); - DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /* *Non-nil means to scroll if point lands on a line which is clipped. */ ); diff --text -u 'xemacs-21.5.18/src/xemacs.def.in.in' 'xemacs-21.5.19/src/xemacs.def.in.in' Index: ./src/xemacs.def.in.in --- ./src/xemacs.def.in.in Thu Feb 26 05:05:33 2004 +++ ./src/xemacs.def.in.in Sat Nov 13 00:09:18 2004 @@ -94,7 +94,7 @@ make_vector maybe_invalid_operation message -new_dfc_convert_alloca /* C_STRING_TO_EXTERNAL, ... */ +new_dfc_convert_copy_data /* C_STRING_TO_EXTERNAL, ... */ new_dfc_convert_malloc /* C_STRING_TO_EXTERNAL_MALLOC, ... */ new_dfc_convert_size /* C_STRING_TO_EXTERNAL, ... */ #ifdef MULE diff --text -u 'xemacs-21.5.18/src/xgccache.c' 'xemacs-21.5.19/src/xgccache.c' Index: ./src/xgccache.c --- ./src/xgccache.c Wed Oct 1 00:27:01 2003 +++ ./src/xgccache.c Tue Feb 15 12:17:07 2005 @@ -92,12 +92,12 @@ }; #ifdef GCCACHE_HASH -static unsigned long +static Hashcode gc_cache_hash (const void *arg) { const struct gcv_and_mask *gcvm = (const struct gcv_and_mask *) arg; unsigned long *longs = (unsigned long *) &gcvm->gcv; - unsigned long hash = gcvm->mask; + Hashcode hash = gcvm->mask; int i; /* This could look at the mask and only use the used slots in the hash code. That would win in that we wouldn't have to initialize @@ -105,7 +105,7 @@ the hash function to be as fast as possible; some timings should be done. */ for (i = 0; i < (int) (sizeof (XGCValues) / sizeof (unsigned long)); i++) - hash = (hash<<1) ^ *longs++; + hash = (hash << 1) ^ *longs++; return hash; } @@ -158,15 +158,17 @@ struct gc_cache_cell *cell, *next, *prev; struct gcv_and_mask gcvm; - if ((!!cache->head) != (!!cache->tail)) abort (); - if (cache->head && (cache->head->prev || cache->tail->next)) abort (); + if ((!!cache->head) != (!!cache->tail)) ABORT (); + if (cache->head && (cache->head->prev || cache->tail->next)) ABORT (); gcvm.mask = mask; gcvm.gcv = *gcv; /* this copies... */ #ifdef GCCACHE_HASH - if (gethash (&gcvm, cache->table, (const void **) &cell)) + /* The intermediate cast fools gcc into not outputting strict-aliasing + complaints */ + if (gethash (&gcvm, cache->table, (const void **) (void *) &cell)) #else /* !GCCACHE_HASH */ @@ -206,10 +208,10 @@ cell->prev = cache->tail; cache->tail->next = cell; cache->tail = cell; - if (cache->head == cell) abort (); - if (cell->next) abort (); - if (cache->head->prev) abort (); - if (cache->tail->next) abort (); + if (cache->head == cell) ABORT (); + if (cell->next) ABORT (); + if (cache->head->prev) ABORT (); + if (cache->tail->next) ABORT (); return cell->gc; } @@ -231,7 +233,7 @@ #endif } else if (cache->size > GC_CACHE_SIZE) - abort (); + ABORT (); else { /* Allocate a new cell (don't put it in the list or table yet). */ diff --text -u 'xemacs-21.5.18/tests/ChangeLog' 'xemacs-21.5.19/tests/ChangeLog' Index: ./tests/ChangeLog --- ./tests/ChangeLog Fri Oct 22 14:10:31 2004 +++ ./tests/ChangeLog Fri Feb 18 14:22:08 2005 @@ -1,11 +1,31 @@ +2005-02-18 Stephen J. Turnbull <stephen@xemacs.org> + + * XEmacs 21.5.19 "chives" is released. + +2005-02-01 Vin Shelton <acs@xemacs.org> + + * automated/regexp-tests.el: Added test for stale match data with + shy groups authored by Arnaud Giersch <arnaud.giersch@free.fr> + +2005-01-13 Stephen J. Turnbull <stephen@xemacs.org> + + * automated/regexp-tests.el: + Test trivial subpatterns and backreferences with shy groups. + +2004-10-28 Stephen J. Turnbull <stephen@xemacs.org> + + * automated/os-tests.el: New file. Add tests for bug reported by + Katsumi Yamaoka 2004-10-26 <b9yvfcyuscf.fsf@jpl.org>. Test + suggested by Katsumi Yamaoka <b9yoeipvwn0.fsf@jpl.org>. + 2004-10-22 Stephen J. Turnbull <stephen@xemacs.org> * XEmacs 21.5.18 "chestnut" is released. 2004-10-07 Stephen J. Turnbull <stephen@xemacs.org> - * automated/regexp-tests.el: Add tests for bug identified by - Steve Youngs 2004-09-30 <microsoft-free.87ekkjhj7t.fsf@youngs.au.com> + * automated/regexp-tests.el: Add tests for bug identified by Steve + Youngs 2004-09-30 <microsoft-free.87ekkjhj7t.fsf@youngs.au.com>. 2004-09-08 Stephen J. Turnbull <stephen@xemacs.org> diff --text -u /dev/null 'xemacs-21.5.19/tests/automated/os-tests.el' Index: ./tests/automated/os-tests.el --- ./tests/automated/os-tests.el Thu Jan 1 09:00:00 1970 +++ ./tests/automated/os-tests.el Thu Oct 28 20:31:23 2004 @@ -0,0 +1,91 @@ +;;; os-tests.el --- test support for OS interaction + +;; Copyright (C) 2004 Free Software Foundation + +;; Author: Stephen J. Turnbull <stephen@xemacs.org> +;; Maintainer: Stephen J. Turnbull <stephen@xemacs.org> +;; Created: 2004 October 28 +;; Keywords: tests, process support + +;; 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. + +;;; Commentary: + +;; Test OS support. Processes, environment variables, etc. +;; See test-harness.el for instructions on how to run these tests. + +;; call-process-region bug reported by Katsumi Yamaoka on 2004-10-26 +;; in <b9yvfcyuscf.fsf@jpl.org>, who suggested the basic test scheme +;; in <b9yoeipvwn0.fsf@jpl.org>. + +;; tac works by lines, unfortunately +(let* ((original-string "a\nb\nc\nd\n") + (tac-cases (if (executable-find "tac") + '((1 . "c\nb\na\nd\n") + (3 . "a\nc\nb\nd\n") + (5 . "a\nc\nb\nd\n") + (7 . "a\nc\nb\nd\n") + (9 . "a\nd\nc\nb\n")) + nil)) + (cat-cases (if (executable-find "cat") + '((1 . "b\nc\na\nd\n") + (3 . "a\nb\nc\nd\n") + (5 . "a\nb\nc\nd\n") + (7 . "a\nb\nc\nd\n") + (9 . "a\nd\nb\nc\n")) + nil)) + cases case) + (with-temp-buffer + (Skip-Test-Unless tac-cases + "tac executable not found" + "Tests of call-process-region with region deleted after inserting +tac process output." + (setq cases tac-cases) + (while cases + (setq case (car cases) + cases (cdr cases)) + (flet ((do-test (pos result) + (erase-buffer) + (insert original-string) + (goto-char pos) + (call-process-region 3 7 "tac" t t) + (goto-char (point-min)) + (Assert (looking-at result)))) + (do-test (car case) (cdr case))))) + ;; if you're in that much of a hurry you can blow cat off + ;; if you've done tac, but I'm not going to bother + (Skip-Test-Unless cat-cases + "cat executable not found" + "Tests of call-process-region with region deleted after inserting +cat process output." + (setq cases cat-cases) + (while cases + (setq case (car cases) + cases (cdr cases)) + (flet ((do-test (pos result) + (erase-buffer) + (insert original-string) + (goto-char pos) + (call-process-region 3 7 "cat" t t) + (goto-char (point-min)) + (Assert (looking-at result)))) + (do-test (car case) (cdr case))))))) + +;;; end of os-tests.el diff --text -u 'xemacs-21.5.18/tests/automated/regexp-tests.el' 'xemacs-21.5.19/tests/automated/regexp-tests.el' Index: ./tests/automated/regexp-tests.el --- ./tests/automated/regexp-tests.el Thu Oct 7 17:01:44 2004 +++ ./tests/automated/regexp-tests.el Wed Feb 2 20:37:21 2005 @@ -393,7 +393,13 @@ (Assert (string= (progn (string-match "\\(a\\)" a) (string-match "b" a) (match-string 1 a)) - a))) + a)) + ;; in 21.4.16, registers from num_shy_groups to num_groups were not cleared, + ;; resulting in stale match data + (Assert (progn (string-match "\\(a\\)" a) + (string-match "\\(?:a\\)" a) + (not (match-beginning 1)))) + ) ;; bug identified by Katsumi Yamaoka 2004-09-03 <b9ywtzbbpue.fsf_-_@jpl.org> ;; fix submitted by sjt 2004-09-08 @@ -423,3 +429,33 @@ (Assert (null (match-string 4 text))) ; nil ) +;; trivial subpatterns and backreferences with shy groups +(let ((text1 "abb") + (text2 "aba") + (re0 "\\(a\\)\\(b\\)\\2") + (re1 "\\(?:a\\)\\(b\\)\\2") + (re2 "\\(?:a\\)\\(b\\)\\1") + (re3 "\\(a\\)\\(?:b\\)\\1")) + + (Assert (eq 0 (string-match re0 text1))) + (Assert (string= text1 (match-string 0 text1))) + (Assert (string= "a" (match-string 1 text1))) + (Assert (string= "b" (match-string 2 text1))) + (Assert (null (string-match re0 text2))) + + (Check-Error-Message 'invalid-regexp "Invalid back reference" + (string-match re1 text1)) + + (Assert (eq 0 (string-match re2 text1))) + (Assert (string= text1 (match-string 0 text1))) + (Assert (string= "b" (match-string 1 text1))) + (Assert (null (match-string 2 text1))) + (Assert (null (string-match re2 text2))) + + (Assert (null (string-match re3 text1))) + (Assert (eq 0 (string-match re3 text2))) + (Assert (string= text2 (match-string 0 text2))) + (Assert (string= "a" (match-string 1 text2))) + (Assert (null (match-string 2 text2))) +) + diff --text -u 'xemacs-21.5.18/version.sh' 'xemacs-21.5.19/version.sh' Index: ./version.sh --- ./version.sh Fri Oct 22 14:10:31 2004 +++ ./version.sh Fri Feb 18 14:22:09 2005 @@ -2,10 +2,10 @@ emacs_is_beta=t emacs_major_version=21 emacs_minor_version=5 -emacs_beta_version=18 -xemacs_codename="chestnut" +emacs_beta_version=19 +xemacs_codename="chives" emacs_kit_version= infodock_major_version=4 infodock_minor_version=0 infodock_build_version=8 -xemacs_extra_name="(+CVS-20041021)" +xemacs_extra_name="(+CVS-20050217)" #### End of Patch data #### #### ApplyPatch data follows #### # Data version : 1.0 # Date generated : Fri Feb 18 14:22:16 2005 # 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 # (\A|/).*\~\Z # (\A|/)\.cvsignore\Z # (\A|/)CVS\Z # (\A|/)MANIFEST\Z # (\A|/)\.precious\Z # (\A|/)TAGS\Z # (\A|/)xemacs\-packages\Z # (\A|/)mule\-packages\Z # (\A|/).*\.gz\Z # (\A|/)display\Z # (\A|/)TUTORIAL\.ru\Z # (\A|/)TUTORIAL\.th\Z # (\A|/).*\.png\Z # (\A|/).*\.bmp\Z # (\A|/).*\.ico\Z # (\A|/).*\.elc\Z # (\A|/).*\.info.*\Z # r './src/xemacs.dmp' 3048560 0 # r './src/nt.h' 1075 0 # r './src/m/gec63.h' 1941 0 # r './src/dump-size' 8 0 # r './modules/postgresql/Makefile.in' 4101 0 # r './modules/postgresql/GNUmakefile' 1754 0 # r './man/internals/index.texi' 1239 0 # r './etc/sink.xbm' 2297 0 # r './etc/ms-kermit-7bit' 9426 0 # r './etc/ms-kermit' 3934 0 # r './etc/gnu.xpm' 3182 0 # r './etc/gnu.xbm' 2270 0 # r './etc/check_cygwin_setup.sh' 4330 0 # r './etc/aliases.ksh' 1588 0 # r './etc/TERMS' 9269 0 # r './etc/SERVICE' 48713 0 # r './etc/README.OO-BROWSER' 640 0 # r './etc/README.HYPERBOLE' 609 0 # r './etc/PACKAGES' 8205 0 # r './etc/ORDERS.JAPAN' 9373 0 # r './etc/ORDERS.EUROPE' 244 0 # r './etc/ORDERS' 139073 0 # r './etc/MOTIVATION' 8793 0 # r './etc/MORE.STUFF' 1633 0 # r './etc/MAILINGLISTS' 4479 0 # r './etc/MACHINES' 1737 0 # r './etc/LPF' 5007 0 # r './etc/GNU' 26338 0 # r './etc/FTP' 4865 0 # r './etc/DISTRIB' 763 0 # r './etc/DEBUG' 5595 0 # r './etc/COPYING.LIB' 25338 0 # r './etc/CODINGS' 12794 0 # r './etc/CODING-STANDARDS' 3426 0 # r './etc/CHARSETS' 3315 0 # r './etc/BETA' 25535 0 # r './README.packages' 11260 0 # r './GETTING.GNU.SOFTWARE' 4868 0 # r './BUGS' 888 0 # p './CHANGES-beta' 70357 1108702436 0100644 # p './ChangeLog' 160373 1108704128 0100644 # p './INSTALL' 36293 1102423951 0100644 # p './Makefile.in.in' 24306 1107201710 0100644 # p './PROBLEMS' 91746 1107201709 0100644 # p './README' 11418 1107486245 0100644 # p './configure' 483685 1108704128 0100755 # p './configure.in' 191280 1107452033 0100644 # p './configure.usage' 18065 1106733733 0100644 # p './etc/ChangeLog' 44710 1108704128 0100644 # p './etc/ETAGS.EBNF' 3336 1107454170 0100644 # p './etc/README' 2997 1107202117 0100644 # p './etc/gnuserv.1' 11702 1103018198 0100644 # p './etc/gnuserv.README' 4575 1103018198 0100644 # p './lib-src/ChangeLog' 50061 1108704128 0100644 # p './lib-src/digest-doc.c' 978 1099609547 0100644 # p './lib-src/ellcc.h.in' 1188 1099926885 0100644 # p './lib-src/etags.c' 177316 1107454166 0100644 # p './lib-src/fakemail.c' 15536 1106733208 0100644 # p './lib-src/gnuclient.c' 18400 1102375421 0100644 # p './lib-src/i.c' 7147 1102378851 0100644 # p './lib-src/insert-data-in-exec.c' 3560 1106710810 0100644 # p './lib-src/make-docfile.c' 30914 1102305053 0100644 # p './lib-src/make-dump-id.c' 2118 1099609547 0100644 # p './lib-src/make-msgfile.c' 14807 1099609548 0100644 # p './lib-src/make-msgfile.lex' 24191 1099609548 0100644 # p './lib-src/make-mswin-unicode.pl' 12577 1099609548 0100644 # p './lib-src/movemail.c' 23116 1108352445 0100644 # p './lib-src/profile.c' 2912 1099609548 0100644 # p './lib-src/sorted-doc.c' 5822 1099609548 0100644 # p './lisp/ChangeLog' 761392 1108704128 0100644 # p './lisp/about.el' 94104 1107485803 0100644 # p './lisp/autoload.el' 36572 1107489454 0100644 # p './lisp/behavior-defs.el' 23553 1107408401 0100644 # p './lisp/behavior.el' 6891 1107408400 0100644 # p './lisp/buffer.el' 4054 1108552050 0100644 # p './lisp/bytecomp-runtime.el' 23540 1103307089 0100644 # p './lisp/cl-extra.el' 28608 1099609554 0100644 # p './lisp/cl.el' 25685 1106733212 0100644 # p './lisp/code-init.el' 14949 1106733083 0100644 # p './lisp/code-process.el' 17087 1098963071 0100644 # p './lisp/cus-dep.el' 9166 1107404973 0100644 # p './lisp/cus-edit.el' 129884 1107404973 0100644 # p './lisp/custom.el' 28719 1107404973 0100644 # p './lisp/dialog-gtk.el' 11216 1099609554 0100644 # p './lisp/dumped-lisp.el' 9541 1108005975 0100644 # c './lisp/easy-mmode.el' 0 1107414680 0100644 # p './lisp/easymenu.el' 9965 1107407018 0100644 # p './lisp/files.el' 172341 1102819629 0100644 # p './lisp/fill.el' 40799 1106733366 0100644 # p './lisp/find-paths.el' 8857 1105802256 0100644 # p './lisp/font-lock.el' 119775 1106713095 0100644 # p './lisp/font-menu.el' 16982 1106881119 0100644 # p './lisp/font.el' 48348 1106881120 0100644 # p './lisp/frame.el' 79340 1106881120 0100644 # p './lisp/gnuserv.el' 29816 1103018208 0100644 # p './lisp/gtk-font-menu.el' 9987 1106881120 0100644 # p './lisp/gtk-marshal.el' 10309 1106872340 0100644 # p './lisp/help.el' 65610 1107202125 0100644 # p './lisp/info.el' 118857 1102305081 0100644 # p './lisp/loadup.el' 9882 1104150314 0100644 # p './lisp/make-docfile.el' 9003 1104150314 0100644 # p './lisp/map-ynp.el' 9797 1107407018 0100644 # p './lisp/menubar-items.el' 77295 1107407018 0100644 # p './lisp/menubar.el' 28135 1107804608 0100644 # p './lisp/minibuf.el' 92759 1106881120 0100644 # p './lisp/mouse.el' 66809 1106714834 0100644 # p './lisp/msw-faces.el' 12976 1106881120 0100644 # p './lisp/msw-font-menu.el' 8022 1106881120 0100644 # p './lisp/mule/devan-util.el' 44558 1100549722 0100644 # p './lisp/mule/european.el' 14823 1107972400 0100644 # p './lisp/mule/mule-ccl.el' 47303 1099609561 0100644 # p './lisp/mule/mule-cmds.el' 62180 1099609562 0100644 # p './lisp/mwheel.el' 4606 1107408401 0100644 # p './lisp/newcomment.el' 41651 1106733434 0100644 # p './lisp/obsolete.el' 15648 1106881121 0100644 # p './lisp/package-admin.el' 21378 1104150314 0100644 # p './lisp/package-ui.el' 25179 1099609555 0100644 # p './lisp/packages.el' 19205 1107475013 0100644 # p './lisp/page.el' 5096 1106733366 0100644 # p './lisp/paragraphs.el' 15972 1108005419 0100644 # p './lisp/process.el' 26147 1105263884 0100644 # c './lisp/regexp-opt.el' 0 1107415822 0100644 # p './lisp/register.el' 11165 1106733366 0100644 # p './lisp/setup-paths.el' 19838 1104150315 0100644 # p './lisp/shadow.el' 8860 1107485967 0100644 # p './lisp/simple.el' 178144 1105960981 0100644 # p './lisp/startup.el' 53519 1106715378 0100644 # p './lisp/subr.el' 61618 1106877905 0100644 # p './lisp/unicode.el' 11738 1107962947 0100644 # p './lisp/update-elc-2.el' 7796 1107414680 0100644 # p './lisp/update-elc.el' 14481 1107414680 0100644 # p './lisp/wid-edit.el' 138218 1099609556 0100644 # p './lisp/widgets-gtk.el' 5273 1099609556 0100644 # p './lisp/win32-native.el' 10553 1099609556 0100644 # p './lisp/window-xemacs.el' 37706 1108552050 0100644 # p './lisp/x-faces.el' 29834 1106881121 0100644 # p './lisp/x-font-menu.el' 9646 1106881121 0100644 # p './lwlib/ChangeLog' 27244 1108704128 0100644 # p './man/ChangeLog' 119419 1108704128 0100644 # p './man/Makefile' 10317 1107202127 0100644 # c './man/beta.texi' 0 1107411280 0100644 # p './man/internals/internals.texi' 450834 1106732907 0100644 # p './man/lispref/eval.texi' 23923 1106300591 0100644 # p './man/lispref/functions.texi' 39291 1106300592 0100644 # p './man/lispref/help.texi' 28959 1103307107 0100644 # p './man/lispref/lispref.texi' 55068 1106300592 0100644 # p './man/lispref/macros.texi' 20350 1106300592 0100644 # p './man/lispref/mule.texi' 133896 1099609567 0100644 # p './man/lispref/range-tables.texi' 2155 1102305101 0100644 # p './man/lispref/symbols.texi' 22838 1106300592 0100644 # p './man/lispref/variables.texi' 48610 1106300592 0100644 # p './man/lispref/windows.texi' 73783 1098960677 0100644 # p './man/xemacs-faq.texi' 274764 1107485481 0100644 # p './man/xemacs/help.texi' 18910 1107202130 0100644 # p './man/xemacs/major.texi' 4819 1106871159 0100644 # p './man/xemacs/new.texi' 11167 1107202130 0100644 # p './man/xemacs/packages.texi' 23425 1102305106 0100644 # p './man/xemacs/programs.texi' 85634 1106871159 0100644 # p './man/xemacs/xemacs.texi' 47475 1107202130 0100644 # p './modules/ChangeLog' 9249 1108704128 0100644 # p './modules/common/Makefile.common' 2494 1099926892 0100644 # p './modules/ldap/eldap.c' 25220 1100396592 0100644 # c './modules/postgresql/configure' 0 1037602353 0100755 # p './netinstall/ChangeLog' 12838 1108704128 0100644 # p './nt/ChangeLog' 64528 1108704128 0100644 # p './nt/config.inc.samp' 9053 1107485912 0100644 # p './nt/installer/Wise/ChangeLog' 1858 1108704128 0100644 # p './nt/installer/Wise/dirs.py' 517 1099696302 0100755 # p './nt/installer/Wise/display-readme.dlg' 1673 1100658736 0100644 # p './nt/installer/Wise/libs.dlg' 6636 1099696302 0100755 # p './nt/installer/Wise/pre_wise.py' 4326 1099696302 0100755 # p './nt/installer/Wise/type.dlg' 764 1099696302 0100755 # p './nt/installer/Wise/version.py' 391 1099696302 0100755 # p './nt/installer/Wise/welcome.dlg' 1901 1099696302 0100755 # p './nt/installer/Wise/xemacs.tmpl' 39884 1099696302 0100755 # p './nt/xemacs.mak' 47317 1107202132 0100644 # p './src/.gdbinit' 11669 1098960495 0100644 # p './src/ChangeLog' 1389693 1108704128 0100644 # p './src/EmacsFrame.c' 22700 1106609625 0100644 # p './src/EmacsManager.c' 8404 1103713149 0100644 # p './src/EmacsShell-sub.c' 13330 1106609626 0100644 # p './src/EmacsShell.c' 4690 1106609626 0100644 # p './src/Makefile.in.in' 33156 1106710815 0100644 # p './src/abbrev.c' 14389 1099609575 0100644 # p './src/alloc.c' 162693 1107447244 0100644 # p './src/alloca.c' 13251 1106609626 0100644 # p './src/backtrace.h' 15154 1106990158 0100644 # p './src/buffer.c' 97701 1107447244 0100644 # p './src/buffer.h' 44140 1099609576 0100644 # p './src/bytecode.c' 65316 1107447244 0100644 # p './src/callint.c' 33699 1099609576 0100644 # p './src/casefiddle.c' 10230 1099609576 0100644 # p './src/charset.h' 20834 1106609627 0100644 # p './src/chartab.c' 52199 1106609627 0100644 # p './src/cm.c' 11876 1106609628 0100644 # p './src/cmdloop.c' 21679 1106990159 0100644 # p './src/compiler.h' 7389 1106609628 0100644 # p './src/config.h.in' 31332 1107448235 0100644 # p './src/console-impl.h' 23538 1106881131 0100644 # p './src/console-msw.c' 19142 1099609578 0100644 # p './src/console-msw.h' 6945 1099609578 0100644 # p './src/console-stream.c' 10803 1106609628 0100644 # p './src/console-x-impl.h' 13824 1099609578 0100644 # p './src/console-x.h' 7061 1105956618 0100644 # p './src/console.c' 47464 1107447244 0100644 # p './src/data.c' 98341 1107447244 0100644 # p './src/database.c' 20962 1106338026 0100644 # p './src/debug.c' 6019 1099609579 0100644 # p './src/debug.h' 2161 1106609629 0100644 # p './src/depend' 41995 1106952748 0100644 # p './src/device-msw.c' 41332 1106609629 0100644 # p './src/device-tty.c' 5774 1106609629 0100644 # p './src/device-x.c' 65515 1107448235 0100644 # p './src/device.c' 43779 1107447244 0100644 # p './src/dialog-msw.c' 25114 1102305123 0100644 # p './src/dired-msw.c' 17698 1106879784 0100644 # p './src/dired.c' 29019 1099609581 0100644 # p './src/doc.c' 29408 1099609581 0100644 # p './src/doprnt.c' 30447 1106609630 0100644 # p './src/dragdrop.c' 4247 1099609581 0100644 # p './src/dragdrop.h' 1323 1099609582 0100644 # p './src/dump-data.c' 1786 1099609582 0100644 # p './src/dump-data.h' 1181 1099609582 0100644 # p './src/dumper.c' 43814 1107486080 0100644 # p './src/dumper.h' 1117 1108437427 0100644 # p './src/dynarr.c' 8699 1106609630 0100644 # p './src/editfns.c' 79722 1102305123 0100644 # p './src/elhash.c' 53795 1107447245 0100644 # p './src/elhash.h' 3093 1106734945 0100644 # p './src/emacs-marshals.c' 74707 1106734945 0100644 # p './src/emacs.c' 137251 1107199788 0100644 # p './src/emodules.c' 20834 1099609584 0100644 # p './src/emodules.h' 4300 1099609584 0100644 # p './src/esd.c' 3839 1099609585 0100644 # p './src/eval.c' 198443 1107448236 0100644 # p './src/event-Xt.c' 107717 1106609632 0100644 # p './src/event-gtk.c' 60596 1106609632 0100644 # p './src/event-gtk.h' 1389 1099609586 0100644 # p './src/event-msw.c' 152798 1106879784 0100644 # p './src/event-stream.c' 174782 1106609633 0100644 # p './src/event-tty.c' 8581 1099609587 0100644 # p './src/events.c' 78128 1107447245 0100644 # p './src/events.h' 51859 1099609587 0100644 # p './src/extents.c' 235954 1107447246 0100644 # p './src/extents.h' 6584 1106716272 0100644 # p './src/faces.c' 70393 1106609634 0100644 # p './src/file-coding.c' 173314 1107447246 0100644 # p './src/file-coding.h' 44053 1099609588 0100644 # p './src/fileio.c' 133575 1106879784 0100644 # p './src/filelock.c' 14596 1099609589 0100644 # p './src/fns.c' 114902 1106609635 0100644 # p './src/font-lock.c' 27084 1106609635 0100644 # p './src/frame-gtk.c' 43383 1106609636 0100644 # p './src/frame-msw.c' 38237 1099609590 0100644 # p './src/frame-x.c' 85098 1106609636 0100644 # p './src/frame.c' 118611 1107448236 0100644 # p './src/free-hook.c' 15468 1106735768 0100644 # p './src/gccache-gtk.c' 8245 1106734946 0100644 # p './src/glyphs-eimage.c' 40604 1107486081 0100644 # p './src/glyphs-gtk.c' 87332 1106734946 0100644 # p './src/glyphs-msw.c' 92785 1106609637 0100644 # p './src/glyphs-shared.c' 9007 1099609593 0100644 # p './src/glyphs-widget.c' 67566 1099609593 0100644 # p './src/glyphs-x.c' 90358 1106609638 0100644 # p './src/glyphs.c' 170263 1107447246 0100644 # p './src/glyphs.h' 45973 1099609594 0100644 # p './src/gtk-glue.c' 6832 1106609639 0100644 # p './src/gui-gtk.c' 2620 1107448237 0100644 # p './src/gui-msw.c' 5203 1099609594 0100644 # p './src/gui-x.c' 19498 1107448237 0100644 # p './src/gui.c' 21332 1099609595 0100644 # p './src/gutter.c' 52320 1106609639 0100644 # p './src/hash.c' 10268 1106734944 0100644 # p './src/hash.h' 3191 1106734945 0100644 # p './src/hftctl.c' 11655 1099609595 0100644 # p './src/hpplay.c' 7775 1099609595 0100644 # p './src/imgproc.c' 14397 1099609596 0100644 # p './src/indent.c' 26800 1106716272 0100644 # p './src/input-method-xlib.c' 33624 1106609639 0100644 # p './src/insdel.c' 56912 1106609639 0100644 # p './src/intl-auto-encap-win32.c' 129400 1106609640 0100644 # p './src/intl-auto-encap-win32.h' 118581 1106609640 0100644 # p './src/intl-encap-win32.c' 82386 1106609640 0100644 # p './src/intl-win32.c' 61920 1106609640 0100644 # p './src/keymap.c' 140289 1106609641 0100644 # p './src/libsst.c' 11051 1099609599 0100644 # p './src/linuxplay.c' 14507 1099609599 0100644 # p './src/lisp.h' 196000 1107448237 0100644 # p './src/lread.c' 92248 1107518249 0100644 # p './src/lrecord.h' 62209 1107447247 0100644 # p './src/lstream.c' 52386 1107447247 0100644 # p './src/m/7300.h' 2422 1099609671 0100644 # p './src/m/acorn.h' 3970 1099609671 0100644 # p './src/m/alliant-2800.h' 3233 1099609671 0100644 # p './src/m/alliant.h' 3128 1099609671 0100644 # p './src/m/altos.h' 1417 1099609671 0100644 # p './src/m/amdahl.h' 3627 1099609672 0100644 # p './src/m/apollo.h' 2658 1099609672 0100644 # p './src/m/att3b.h' 3759 1099609672 0100644 # p './src/m/aviion.h' 2952 1099609673 0100644 # p './src/m/celerity.h' 1532 1099609673 0100644 # p './src/m/clipper.h' 2117 1099609673 0100644 # p './src/m/cnvrgnt.h' 2176 1099609673 0100644 # p './src/m/convex.h' 4469 1099609673 0100644 # p './src/m/cydra5.h' 2706 1099609674 0100644 # p './src/m/delta.h' 4935 1099609674 0100644 # p './src/m/delta88k.h' 3515 1099609674 0100644 # p './src/m/dpx2.h' 4248 1099609674 0100644 # p './src/m/elxsi.h' 2958 1099609674 0100644 # p './src/m/ews4800r.h' 2227 1099609675 0100644 # p './src/m/gould.h' 4502 1099609675 0100644 # p './src/m/hp300bsd.h' 1264 1099609675 0100644 # p './src/m/hp800.h' 3611 1099609675 0100644 # p './src/m/hp9000s300.h' 4041 1099609676 0100644 # p './src/m/i860.h' 2324 1099609676 0100644 # p './src/m/ibmps2-aix.h' 4641 1099609676 0100644 # p './src/m/ibmrs6000.h' 3262 1099609676 0100644 # p './src/m/ibmrt-aix.h' 4169 1099609676 0100644 # p './src/m/ibmrt.h' 2803 1099609676 0100644 # p './src/m/intel386.h' 4826 1099609676 0100644 # p './src/m/iris4d.h' 3522 1099609677 0100644 # p './src/m/iris5d.h' 3716 1099609677 0100644 # p './src/m/iris6d.h' 3525 1099609677 0100644 # p './src/m/irist.h' 3755 1099609678 0100644 # p './src/m/isi-ov.h' 2188 1099609678 0100644 # p './src/m/luna88k.h' 2525 1099609678 0100644 # p './src/m/m68k.h' 1285 1099609678 0100644 # p './src/m/masscomp.h' 3068 1099609678 0100644 # p './src/m/mg1.h' 2848 1099609678 0100644 # p './src/m/mips-nec.h' 3397 1099609679 0100644 # p './src/m/mips-siemens.h' 3460 1099609679 0100644 # p './src/m/mips.h' 4037 1099609679 0100644 # p './src/m/news.h' 1683 1099609679 0100644 # p './src/m/nh3000.h' 2423 1099609679 0100644 # p './src/m/nh4000.h' 2357 1099609679 0100644 # p './src/m/ns32000.h' 2314 1099609680 0100644 # p './src/m/orion105.h' 1606 1099609680 0100644 # p './src/m/pfa50.h' 1795 1099609680 0100644 # p './src/m/plexus.h' 2531 1099609680 0100644 # p './src/m/pmax.h' 3196 1099609680 0100644 # p './src/m/powerpc.h' 2864 1099609680 0100644 # p './src/m/pyrmips.h' 230 1099609681 0100644 # p './src/m/sequent-ptx.h' 3568 1099609681 0100644 # p './src/m/sequent.h' 4667 1099609681 0100644 # p './src/m/sgi-challenge.h' 4220 1099609681 0100644 # p './src/m/symmetry.h' 3595 1099609682 0100644 # p './src/m/tad68k.h' 2685 1099609682 0100644 # p './src/m/tahoe.h' 1726 1099609683 0100644 # p './src/m/targon31.h' 2278 1099609683 0100644 # p './src/m/tekxd88.h' 3251 1099609683 0100644 # p './src/m/template.h' 2534 1099609683 0100644 # p './src/m/tower32.h' 2661 1099609683 0100644 # p './src/m/tower32v3.h' 2834 1099609683 0100644 # p './src/m/ustation.h' 2972 1099609683 0100644 # p './src/m/vax.h' 2598 1099609684 0100644 # p './src/m/wicat.h' 3116 1099609684 0100644 # p './src/m/xps100.h' 2319 1099609684 0100644 # p './src/macros.c' 9278 1106990160 0100644 # p './src/malloc.c' 22665 1106609643 0100644 # p './src/marker.c' 14887 1107447247 0100644 # p './src/menubar-gtk.c' 41227 1106609643 0100644 # p './src/menubar-msw.c' 27182 1106609643 0100644 # p './src/menubar-x.c' 37539 1106609644 0100644 # p './src/menubar.c' 27980 1107407025 0100644 # p './src/minibuf.c' 27509 1099609602 0100644 # p './src/miscplay.c' 27835 1099609602 0100644 # p './src/miscplay.h' 3033 1099609602 0100644 # p './src/mule-charset.c' 43119 1107447247 0100644 # p './src/mule-coding.c' 97892 1107447247 0100644 # p './src/mule-wnnfns.c' 58014 1099609603 0100644 # p './src/nas.c' 23449 1099609603 0100644 # p './src/native-gtk-toolbar.c' 7173 1106609644 0100644 # p './src/nt.c' 58588 1106879785 0100644 # p './src/ntheap.c' 10710 1099609604 0100644 # p './src/ntplay.c' 2937 1106879786 0100644 # p './src/number-gmp.c' 3324 1099609605 0100644 # p './src/number-gmp.h' 10333 1107447247 0100644 # p './src/number.c' 20758 1107447247 0100644 # p './src/objects-gtk.c' 16687 1106881131 0100644 # p './src/objects-msw.c' 79586 1106881131 0100644 # p './src/objects-tty.c' 10550 1106881131 0100644 # p './src/objects-x.c' 34069 1106881132 0100644 # p './src/objects.c' 35656 1107447247 0100644 # p './src/opaque.c' 5310 1106734948 0100644 # p './src/print.c' 70884 1106609645 0100644 # p './src/process-nt.c' 44091 1106879786 0100644 # p './src/process-unix.c' 66668 1107489994 0100644 # p './src/process.c' 80980 1106609646 0100644 # p './src/profile.c' 24829 1107447248 0100644 # p './src/profile.h' 3250 1106734160 0100644 # p './src/ralloc.c' 58586 1106609646 0100644 # p './src/rangetab.c' 22286 1107447248 0100644 # p './src/rangetab.h' 1665 1102305137 0100644 # p './src/realpath.c' 8719 1106879786 0100644 # p './src/redisplay-gtk.c' 54967 1106609646 0100644 # p './src/redisplay-msw.c' 39356 1106609647 0100644 # p './src/redisplay-output.c' 84766 1106609647 0100644 # p './src/redisplay-tty.c' 42726 1106609647 0100644 # p './src/redisplay-x.c' 60644 1106609647 0100644 # p './src/redisplay.c' 313516 1107448238 0100644 # p './src/redisplay.h' 29576 1106735622 0100644 # p './src/regex.c' 223862 1106609648 0100644 # p './src/s/cxux.h' 2951 1099609708 0100644 # p './src/s/mingw32.h' 3192 1099609708 0100644 # p './src/s/usg5-4-2.h' 403 1099609708 0100644 # p './src/s/win32-common.h' 1139 1099609708 0100644 # p './src/s/win32-native.h' 1435 1099609708 0100644 # p './src/s/windowsnt.h' 9128 1106609674 0100644 # p './src/scrollbar-gtk.c' 16367 1106609649 0100644 # p './src/scrollbar-x.c' 22636 1106609649 0100644 # p './src/scrollbar.c' 32111 1104983132 0100644 # p './src/search.c' 98270 1106609649 0100644 # p './src/select-common.h' 10526 1099609612 0100644 # p './src/select-gtk.c' 14696 1099609612 0100644 # p './src/select-x.c' 46865 1106609649 0100644 # p './src/sgiplay.c' 18547 1099609613 0100644 # p './src/signal.c' 47499 1106735622 0100644 # p './src/sound.c' 20669 1106879786 0100644 # p './src/sound.h' 1571 1106879786 0100644 # p './src/specifier.c' 106769 1107447248 0100644 # p './src/specifier.h' 21263 1106734948 0100644 # p './src/strftime.c' 12038 1106609650 0100644 # p './src/sunplay.c' 6690 1106609650 0100644 # p './src/symbols.c' 116303 1106609651 0100644 # p './src/symsinit.h' 19213 1106879786 0100644 # p './src/syntax.c' 69391 1106716272 0100644 # p './src/sysdep.c' 116073 1106879787 0100644 # p './src/sysfile.h' 11899 1106879787 0100644 # p './src/sysproc.h' 6971 1107486081 0100644 # p './src/syswindows.h' 34575 1106879787 0100644 # p './src/text.c' 119019 1106609652 0100644 # p './src/text.h' 115552 1106879787 0100644 # p './src/toolbar-common.c' 20019 1106609652 0100644 # p './src/toolbar-msw.c' 18544 1106609652 0100644 # p './src/toolbar.c' 62233 1106609652 0100644 # p './src/ui-byhand.c' 18971 1099609616 0100644 # p './src/ui-gtk.c' 53693 1106734945 0100644 # p './src/undo.c' 15135 1099609617 0100644 # p './src/unexcw.c' 16238 1102305142 0100644 # p './src/unexnext.c' 9002 1102305143 0100644 # p './src/unexnt.c' 18786 1106609653 0100644 # p './src/unicode.c' 67845 1107447248 0100644 # p './src/win32.c' 18589 1106879788 0100644 # p './src/window.c' 174992 1107447248 0100644 # p './src/xemacs.def.in.in' 5641 1100272158 0100644 # p './src/xgccache.c' 9606 1108437427 0100644 # p './tests/ChangeLog' 21243 1108704128 0100644 # c './tests/automated/os-tests.el' 0 1098963083 0100644 # p './tests/automated/regexp-tests.el' 15115 1107344241 0100644 # p './version.sh' 250 1108704129 0100644 #### End of ApplyPatch data #### #### End of Patch kit [created: Fri Feb 18 14:22:16 2005] #### #### Patch checksum: 126782 5079373 55866 #### #### Checksum: 126859 5081738 48451 ####